summaryrefslogtreecommitdiff
path: root/src/compositor-x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor-x11.c')
-rw-r--r--src/compositor-x11.c214
1 files changed, 116 insertions, 98 deletions
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index e6022f77..6b5eb648 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -115,6 +115,8 @@ struct x11_output {
int32_t scale;
};
+struct gl_renderer_interface *gl_renderer;
+
static struct xkb_keymap *
x11_compositor_get_keymap(struct x11_compositor *c)
{
@@ -160,7 +162,7 @@ x11_compositor_get_keymap(struct x11_compositor *c)
static uint32_t
get_xkb_mod_mask(struct x11_compositor *c, uint32_t in)
{
- struct weston_xkb_info *info = c->core_seat.xkb_info;
+ struct weston_xkb_info *info = c->core_seat.keyboard->xkb_info;
uint32_t ret = 0;
if ((in & ShiftMask) && info->shift_mod != XKB_MOD_INVALID)
@@ -201,6 +203,7 @@ x11_compositor_setup_xkb(struct x11_compositor *c)
xcb_xkb_per_client_flags_reply_t *pcf_reply;
xcb_xkb_get_state_cookie_t state;
xcb_xkb_get_state_reply_t *state_reply;
+ uint32_t values[1] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
c->has_xkb = 0;
c->xkb_event_base = 0;
@@ -270,7 +273,7 @@ x11_compositor_setup_xkb(struct x11_compositor *c)
return;
}
- xkb_state_update_mask(c->core_seat.xkb_state.state,
+ xkb_state_update_mask(c->core_seat.keyboard->xkb_state.state,
get_xkb_mod_mask(c, state_reply->baseMods),
get_xkb_mod_mask(c, state_reply->latchedMods),
get_xkb_mod_mask(c, state_reply->lockedMods),
@@ -280,10 +283,29 @@ x11_compositor_setup_xkb(struct x11_compositor *c)
free(state_reply);
+ xcb_change_window_attributes(c->conn, c->screen->root,
+ XCB_CW_EVENT_MASK, values);
+
c->has_xkb = 1;
#endif
}
+#ifdef HAVE_XCB_XKB
+static void
+update_xkb_keymap(struct x11_compositor *c)
+{
+ struct xkb_keymap *keymap;
+
+ keymap = x11_compositor_get_keymap(c);
+ if (!keymap) {
+ weston_log("failed to get XKB keymap\n");
+ return;
+ }
+ weston_seat_update_keymap(&c->core_seat, keymap);
+ xkb_keymap_unref(keymap);
+}
+#endif
+
static int
x11_input_create(struct x11_compositor *c, int no_input)
{
@@ -346,92 +368,39 @@ set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region
struct x11_output *output = (struct x11_output *)output_base;
struct weston_compositor *ec = output->base.compositor;
struct x11_compositor *c = (struct x11_compositor *)ec;
+ pixman_region32_t transformed_region;
pixman_box32_t *rects;
xcb_rectangle_t *output_rects;
- pixman_box32_t rect, transformed_rect;
xcb_void_cookie_t cookie;
- int width, height, nrects, i;
+ int nrects, i;
xcb_generic_error_t *err;
- rects = pixman_region32_rectangles(region, &nrects);
+ pixman_region32_init(&transformed_region);
+ pixman_region32_copy(&transformed_region, region);
+ pixman_region32_translate(&transformed_region,
+ -output_base->x, -output_base->y);
+ weston_transformed_region(output_base->width, output_base->height,
+ output_base->transform,
+ output_base->current_scale,
+ &transformed_region, &transformed_region);
+
+ rects = pixman_region32_rectangles(&transformed_region, &nrects);
output_rects = calloc(nrects, sizeof(xcb_rectangle_t));
- if (output_rects == NULL)
+ if (output_rects == NULL) {
+ pixman_region32_fini(&transformed_region);
return;
-
- width = output_base->width;
- height = output_base->height;
+ }
for (i = 0; i < nrects; i++) {
- rect = rects[i];
- rect.x1 -= output_base->x;
- rect.y1 -= output_base->y;
- rect.x2 -= output_base->x;
- rect.y2 -= output_base->y;
-
- switch (output_base->transform) {
- default:
- case WL_OUTPUT_TRANSFORM_NORMAL:
- transformed_rect.x1 = rect.x1;
- transformed_rect.y1 = rect.y1;
- transformed_rect.x2 = rect.x2;
- transformed_rect.y2 = rect.y2;
- break;
- case WL_OUTPUT_TRANSFORM_90:
- transformed_rect.x1 = height - rect.y2;
- transformed_rect.y1 = rect.x1;
- transformed_rect.x2 = height - rect.y1;
- transformed_rect.y2 = rect.x2;
- break;
- case WL_OUTPUT_TRANSFORM_180:
- transformed_rect.x1 = width - rect.x2;
- transformed_rect.y1 = height - rect.y2;
- transformed_rect.x2 = width - rect.x1;
- transformed_rect.y2 = height - rect.y1;
- break;
- case WL_OUTPUT_TRANSFORM_270:
- transformed_rect.x1 = rect.y1;
- transformed_rect.y1 = width - rect.x2;
- transformed_rect.x2 = rect.y2;
- transformed_rect.y2 = width - rect.x1;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED:
- transformed_rect.x1 = width - rect.x2;
- transformed_rect.y1 = rect.y1;
- transformed_rect.x2 = width - rect.x1;
- transformed_rect.y2 = rect.y2;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_90:
- transformed_rect.x1 = height - rect.y2;
- transformed_rect.y1 = width - rect.x2;
- transformed_rect.x2 = height - rect.y1;
- transformed_rect.y2 = width - rect.x1;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_180:
- transformed_rect.x1 = rect.x1;
- transformed_rect.y1 = height - rect.y2;
- transformed_rect.x2 = rect.x2;
- transformed_rect.y2 = height - rect.y1;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_270:
- transformed_rect.x1 = rect.y1;
- transformed_rect.y1 = rect.x1;
- transformed_rect.x2 = rect.y2;
- transformed_rect.y2 = rect.x2;
- break;
- }
-
- transformed_rect.x1 *= output_base->current_scale;
- transformed_rect.y1 *= output_base->current_scale;
- transformed_rect.x2 *= output_base->current_scale;
- transformed_rect.y2 *= output_base->current_scale;
-
- output_rects[i].x = transformed_rect.x1;
- output_rects[i].y = transformed_rect.y1;
- output_rects[i].width = transformed_rect.x2 - transformed_rect.x1;
- output_rects[i].height = transformed_rect.y2 - transformed_rect.y1;
+ output_rects[i].x = rects[i].x1;
+ output_rects[i].y = rects[i].y1;
+ output_rects[i].width = rects[i].x2 - rects[i].x1;
+ output_rects[i].height = rects[i].y2 - rects[i].y1;
}
+ pixman_region32_fini(&transformed_region);
+
cookie = xcb_set_clip_rectangles_checked(c->conn, XCB_CLIP_ORDERING_UNSORTED,
output->gc,
0, 0, nrects,
@@ -514,14 +483,13 @@ x11_output_destroy(struct weston_output *output_base)
struct x11_compositor *compositor =
(struct x11_compositor *)output->base.compositor;
- wl_list_remove(&output->base.link);
wl_event_source_remove(output->finish_frame_timer);
if (compositor->use_pixman) {
pixman_renderer_output_destroy(output_base);
x11_output_deinit_shm(compositor, output);
} else
- gl_renderer_output_destroy(output_base);
+ gl_renderer->output_destroy(output_base);
xcb_destroy_window(compositor->conn, output->window);
@@ -734,6 +702,12 @@ x11_output_init_shm(struct x11_compositor *c, struct x11_output *output,
visual_type->blue_mask == 0x0000ff) {
weston_log("Will use x8r8g8b8 format for SHM surfaces\n");
pixman_format = PIXMAN_x8r8g8b8;
+ } else if (bitsperpixel == 16 &&
+ visual_type->red_mask == 0x00f800 &&
+ visual_type->green_mask == 0x0007e0 &&
+ visual_type->blue_mask == 0x00001f) {
+ weston_log("Will use r5g6b5 format for SHM surfaces\n");
+ pixman_format = PIXMAN_r5g6b5;
} else {
weston_log("Can't find appropriate format for SHM pixmap\n");
errno = ENOTSUP;
@@ -787,6 +761,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
struct wm_normal_hints normal_hints;
struct wl_event_loop *loop;
int output_width, output_height;
+ int ret;
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
xcb_atom_t atom_list[1];
uint32_t values[2] = {
@@ -896,6 +871,10 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
output->base.current_mode = &output->mode;
output->base.make = "xwayland";
output->base.model = "none";
+
+ if (configured_name)
+ output->base.name = strdup(configured_name);
+
weston_output_init(&output->base, &c->base,
x, y, width, height, transform, scale);
@@ -909,7 +888,9 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
return NULL;
}
} else {
- if (gl_renderer_output_create(&output->base, (EGLNativeWindowType)output->window) < 0)
+ ret = gl_renderer->output_create(&output->base,
+ (EGLNativeWindowType) output->window);
+ if (ret < 0)
return NULL;
}
@@ -938,11 +919,25 @@ x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window)
assert(0);
}
+static void
+x11_compositor_delete_window(struct x11_compositor *c, xcb_window_t window)
+{
+ struct x11_output *output;
+
+ output = x11_compositor_find_output(c, window);
+ x11_output_destroy(&output->base);
+
+ xcb_flush(c->conn);
+
+ if (wl_list_empty(&c->base.output_list))
+ wl_display_terminate(c->base.wl_display);
+}
+
#ifdef HAVE_XCB_XKB
static void
update_xkb_state(struct x11_compositor *c, xcb_xkb_state_notify_event_t *state)
{
- xkb_state_update_mask(c->core_seat.xkb_state.state,
+ xkb_state_update_mask(c->core_seat.keyboard->xkb_state.state,
get_xkb_mod_mask(c, state->baseMods),
get_xkb_mod_mask(c, state->latchedMods),
get_xkb_mod_mask(c, state->lockedMods),
@@ -972,7 +967,7 @@ update_xkb_state_from_core(struct x11_compositor *c, uint16_t x11_mask)
uint32_t mask = get_xkb_mod_mask(c, x11_mask);
struct weston_keyboard *keyboard = c->core_seat.keyboard;
- xkb_state_update_mask(c->core_seat.xkb_state.state,
+ xkb_state_update_mask(c->core_seat.keyboard->xkb_state.state,
keyboard->modifiers.mods_depressed & mask,
keyboard->modifiers.mods_latched & mask,
keyboard->modifiers.mods_locked & mask,
@@ -1072,8 +1067,9 @@ x11_compositor_deliver_motion_event(struct x11_compositor *c,
update_xkb_state_from_core(c, motion_notify->state);
output = x11_compositor_find_output(c, motion_notify->event);
weston_output_transform_coordinate(&output->base,
- motion_notify->event_x,
- motion_notify->event_y, &x, &y);
+ wl_fixed_from_int(motion_notify->event_x),
+ wl_fixed_from_int(motion_notify->event_y),
+ &x, &y);
notify_motion(&c->core_seat, weston_compositor_get_time(),
x - c->prev_x, y - c->prev_y);
@@ -1097,8 +1093,8 @@ x11_compositor_deliver_enter_event(struct x11_compositor *c,
update_xkb_state_from_core(c, enter_notify->state);
output = x11_compositor_find_output(c, enter_notify->event);
weston_output_transform_coordinate(&output->base,
- enter_notify->event_x,
- enter_notify->event_y, &x, &y);
+ wl_fixed_from_int(enter_notify->event_x),
+ wl_fixed_from_int(enter_notify->event_y), &x, &y);
notify_pointer_focus(&c->core_seat, &output->base, x, y);
@@ -1136,6 +1132,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
xcb_focus_in_event_t *focus_in;
xcb_expose_event_t *expose;
xcb_atom_t atom;
+ xcb_window_t window;
uint32_t *k;
uint32_t i, set;
uint8_t response_type;
@@ -1244,6 +1241,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
case XCB_EXPOSE:
expose = (xcb_expose_event_t *) event;
output = x11_compositor_find_output(c, expose->window);
+ weston_output_damage(&output->base);
weston_output_schedule_repaint(&output->base);
break;
@@ -1263,8 +1261,9 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
case XCB_CLIENT_MESSAGE:
client_message = (xcb_client_message_event_t *) event;
atom = client_message->data.data32[0];
+ window = client_message->window;
if (atom == c->atom.wm_delete_window)
- wl_display_terminate(c->base.wl_display);
+ x11_compositor_delete_window(c, window);
break;
case XCB_FOCUS_IN:
@@ -1288,12 +1287,20 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
}
#ifdef HAVE_XCB_XKB
- if (c->has_xkb &&
- response_type == c->xkb_event_base) {
- xcb_xkb_state_notify_event_t *state =
- (xcb_xkb_state_notify_event_t *) event;
- if (state->xkbType == XCB_XKB_STATE_NOTIFY)
- update_xkb_state(c, state);
+ if (c->has_xkb) {
+ if (response_type == c->xkb_event_base) {
+ xcb_xkb_state_notify_event_t *state =
+ (xcb_xkb_state_notify_event_t *) event;
+ if (state->xkbType == XCB_XKB_STATE_NOTIFY)
+ update_xkb_state(c, state);
+ } else if (response_type == XCB_PROPERTY_NOTIFY) {
+ xcb_property_notify_event_t *prop_notify =
+ (xcb_property_notify_event_t *) event;
+ if (prop_notify->window == c->screen->root &&
+ prop_notify->atom == c->atom.xkb_names &&
+ prop_notify->state == XCB_PROPERTY_NEW_VALUE)
+ update_xkb_keymap(c);
+ }
}
#endif
@@ -1414,8 +1421,6 @@ x11_destroy(struct weston_compositor *ec)
weston_compositor_shutdown(ec); /* destroys outputs, too */
- ec->renderer->destroy(ec);
-
XCloseDisplay(compositor->dpy);
free(ec);
}
@@ -1445,6 +1450,21 @@ parse_transform(const char *transform, const char *output_name)
return WL_OUTPUT_TRANSFORM_NORMAL;
}
+static int
+init_gl_renderer(struct x11_compositor *c)
+{
+ int ret;
+
+ gl_renderer = weston_load_module("gl-renderer.so",
+ "gl_renderer_interface");
+ if (!gl_renderer)
+ return -1;
+
+ ret = gl_renderer->create(&c->base, (EGLNativeDisplayType) c->dpy,
+ gl_renderer->opaque_attribs, NULL);
+
+ return ret;
+}
static struct weston_compositor *
x11_compositor_create(struct wl_display *display,
int fullscreen,
@@ -1501,10 +1521,8 @@ x11_compositor_create(struct wl_display *display,
if (pixman_renderer_init(&c->base) < 0)
goto err_xdisplay;
}
- else {
- if (gl_renderer_create(&c->base, (EGLNativeDisplayType)c->dpy, gl_renderer_opaque_attribs,
- NULL) < 0)
- goto err_xdisplay;
+ else if (init_gl_renderer(c) < 0) {
+ goto err_xdisplay;
}
weston_log("Using %s renderer\n", use_pixman ? "pixman" : "gl");