diff --git a/src/compositor-android.c b/src/compositor-android.c index a9c45d22..b0952621 100644 --- a/src/compositor-android.c +++ b/src/compositor-android.c @@ -238,7 +238,8 @@ android_compositor_add_output(struct android_compositor *compositor, mm_width = output->fb->width / output->fb->xdpi * 25.4f; mm_height = output->fb->height / output->fb->ydpi * 25.4f; weston_output_init(&output->base, &compositor->base, - 0, 0, round(mm_width), round(mm_height)); + 0, 0, round(mm_width), round(mm_height), + WL_OUTPUT_TRANSFORM_NORMAL); wl_list_insert(compositor->base.output_list.prev, &output->base.link); } diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 8c8c8c0e..bcc9a0da 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -46,6 +46,7 @@ static int option_current_mode = 0; static char *output_name; static char *output_mode; +static char *output_transform; static struct wl_list configured_output_list; enum output_config { @@ -60,6 +61,7 @@ enum output_config { struct drm_configured_output { char *name; char *mode; + uint32_t transform; int32_t width, height; drmModeModeInfo crtc_mode; enum output_config config; @@ -1434,7 +1436,8 @@ create_output_for_connector(struct drm_compositor *ec, wl_list_for_each(temp, &configured_output_list, link) { if (strcmp(temp->name, output->name) == 0) { - weston_log("%s mode \"%s\" in config\n", + if (temp->mode) + weston_log("%s mode \"%s\" in config\n", temp->name, temp->mode); o = temp; break; @@ -1450,9 +1453,9 @@ create_output_for_connector(struct drm_compositor *ec, } wl_list_for_each(drm_mode, &output->base.mode_list, base.link) { - if (o && o->width == drm_mode->base.width && - o->height == drm_mode->base.height && - o->config == OUTPUT_CONFIG_MODE) + if (o && o->config == OUTPUT_CONFIG_MODE && + o->width == drm_mode->base.width && + o->height == drm_mode->base.height) configured = drm_mode; if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode)) current = drm_mode; @@ -1528,7 +1531,8 @@ create_output_for_connector(struct drm_compositor *ec, } weston_output_init(&output->base, &ec->base, x, y, - connector->mmWidth, connector->mmHeight); + connector->mmWidth, connector->mmHeight, + o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL); wl_list_insert(ec->base.output_list.prev, &output->base.link); @@ -1695,7 +1699,7 @@ create_outputs(struct drm_compositor *ec, uint32_t option_connector, x += container_of(ec->base.output_list.prev, struct weston_output, - link)->current->width; + link)->width; } drmModeFreeConnector(connector); @@ -1751,7 +1755,7 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device) /* XXX: not yet needed, we die with 0 outputs */ if (!wl_list_empty(&ec->base.output_list)) - x = last->x + last->current->width; + x = last->x + last->width; else x = 0; y = 0; @@ -1779,7 +1783,7 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device) disconnects &= ~(1 << output->connector_id); weston_log("connector %d disconnected\n", output->connector_id); - x_offset += output->base.current->width; + x_offset += output->base.width; drm_output_destroy(&output->base); } } @@ -2411,6 +2415,40 @@ check_for_modeline(struct drm_configured_output *output) return 0; } +static void +drm_output_set_transform(struct drm_configured_output *output) +{ + if (!output_transform) { + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + return; + } + + if (!strcmp(output_transform, "normal")) + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + else if (!strcmp(output_transform, "90")) + output->transform = WL_OUTPUT_TRANSFORM_90; + else if (!strcmp(output_transform, "180")) + output->transform = WL_OUTPUT_TRANSFORM_180; + else if (!strcmp(output_transform, "270")) + output->transform = WL_OUTPUT_TRANSFORM_270; + else if (!strcmp(output_transform, "flipped")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; + else if (!strcmp(output_transform, "flipped-90")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; + else if (!strcmp(output_transform, "flipped-180")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; + else if (!strcmp(output_transform, "flipped-270")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; + else { + weston_log("Invalid transform \"%s\" for output %s\n", + output_transform, output_name); + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + } + + free(output_transform); + output_transform = NULL; +} + static void output_section_done(void *data) { @@ -2418,11 +2456,14 @@ output_section_done(void *data) output = malloc(sizeof *output); - if (!output || !output_name || !output_mode) { + if (!output || !output_name || (output_name[0] == 'X') || + (!output_mode && !output_transform)) { free(output_name); - output_name = NULL; free(output_mode); + free(output_transform); + output_name = NULL; output_mode = NULL; + output_transform = NULL; return; } @@ -2430,24 +2471,32 @@ output_section_done(void *data) output->name = output_name; output->mode = output_mode; - if (strcmp(output_mode, "off") == 0) - output->config = OUTPUT_CONFIG_OFF; - else if (strcmp(output_mode, "preferred") == 0) - output->config = OUTPUT_CONFIG_PREFERRED; - else if (strcmp(output_mode, "current") == 0) - output->config = OUTPUT_CONFIG_CURRENT; - else if (sscanf(output_mode, "%dx%d", &output->width, &output->height) == 2) - output->config = OUTPUT_CONFIG_MODE; - else if (check_for_modeline(output) == 0) - output->config = OUTPUT_CONFIG_MODELINE; - - if (output->config != OUTPUT_CONFIG_INVALID) - wl_list_insert(&configured_output_list, &output->link); - else { - weston_log("Invalid mode \"%s\" for output %s\n", - output_mode, output_name); - drm_free_configured_output(output); + if (output_mode) { + if (strcmp(output_mode, "off") == 0) + output->config = OUTPUT_CONFIG_OFF; + else if (strcmp(output_mode, "preferred") == 0) + output->config = OUTPUT_CONFIG_PREFERRED; + else if (strcmp(output_mode, "current") == 0) + output->config = OUTPUT_CONFIG_CURRENT; + else if (sscanf(output_mode, "%dx%d", + &output->width, &output->height) == 2) + output->config = OUTPUT_CONFIG_MODE; + else if (check_for_modeline(output) == 0) + output->config = OUTPUT_CONFIG_MODELINE; + + if (output->config == OUTPUT_CONFIG_INVALID) + weston_log("Invalid mode \"%s\" for output %s\n", + output_mode, output_name); + output_mode = NULL; } + + drm_output_set_transform(output); + + wl_list_insert(&configured_output_list, &output->link); + + if (output_transform) + free(output_transform); + output_transform = NULL; } WL_EXPORT struct weston_compositor * @@ -2471,6 +2520,7 @@ backend_init(struct wl_display *display, int argc, char *argv[], const struct config_key drm_config_keys[] = { { "name", CONFIG_KEY_STRING, &output_name }, { "mode", CONFIG_KEY_STRING, &output_mode }, + { "transform", CONFIG_KEY_STRING, &output_transform }, }; const struct config_section config_section[] = { diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 4fc77f1b..84eaf6c3 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -395,7 +395,8 @@ wayland_compositor_create_output(struct wayland_compositor *c, wl_list_insert(&output->base.mode_list, &output->mode.link); output->base.current = &output->mode; - weston_output_init(&output->base, &c->base, 0, 0, width, height); + weston_output_init(&output->base, &c->base, 0, 0, width, height, + WL_OUTPUT_TRANSFORM_NORMAL); output->base.border.top = c->border.top; output->base.border.bottom = c->border.bottom; diff --git a/src/compositor-x11.c b/src/compositor-x11.c index c02911d4..5b1cdd99 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -52,6 +52,7 @@ static char *output_name; static char *output_mode; +static char *output_transform; static int option_width; static int option_height; static int option_count; @@ -60,6 +61,7 @@ static struct wl_list configured_output_list; struct x11_configured_output { char *name; int width, height; + uint32_t transform; struct wl_list link; }; @@ -471,12 +473,15 @@ x11_output_set_icon(struct x11_compositor *c, pixman_image_unref(image); } -static int +static struct x11_output * x11_compositor_create_output(struct x11_compositor *c, int x, int y, int width, int height, int fullscreen, - int no_input, const char *name) + int no_input, char *configured_name, + uint32_t transform) { + static const char name[] = "Weston Compositor"; static const char class[] = "weston-1\0Weston Compositor"; + char title[32]; struct x11_output *output; xcb_screen_iterator_t iter; struct wm_normal_hints normal_hints; @@ -488,6 +493,11 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, 0 }; + if (configured_name) + sprintf(title, "%s - %s", name, configured_name); + else + strcpy(title, name); + if (!no_input) values[0] |= XCB_EVENT_MASK_KEY_PRESS | @@ -502,7 +512,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, output = malloc(sizeof *output); if (output == NULL) - return -1; + return NULL; memset(output, 0, sizeof *output); @@ -517,7 +527,8 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, output->base.current = &output->mode; output->base.make = "xwayland"; output->base.model = "none"; - weston_output_init(&output->base, &c->base, x, y, width, height); + weston_output_init(&output->base, &c->base, + x, y, width, height, transform); values[1] = c->null_cursor; output->window = xcb_generate_id(c->conn); @@ -550,7 +561,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, /* Set window name. Don't bother with non-EWMH WMs. */ xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, c->atom.net_wm_name, c->atom.utf8_string, 8, - strlen(name), name); + strlen(title), title); xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window, c->atom.wm_class, c->atom.string, 8, sizeof class, class); @@ -570,12 +581,12 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, output->window, NULL); if (!output->egl_surface) { weston_log("failed to create window surface\n"); - return -1; + return NULL; } if (!eglMakeCurrent(c->base.egl_display, output->egl_surface, output->egl_surface, c->base.egl_context)) { weston_log("failed to make surface current\n"); - return -1; + return NULL; } loop = wl_display_get_event_loop(c->base.wl_display); @@ -595,7 +606,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y, weston_log("x11 output %dx%d, window id %d\n", width, height, output->window); - return 0; + return output; } static struct x11_output * @@ -739,6 +750,98 @@ x11_compositor_deliver_button_event(struct x11_compositor *c, WL_POINTER_BUTTON_STATE_RELEASED); } +static void +x11_output_transform_coordinate(struct x11_output *x11_output, + wl_fixed_t *x, wl_fixed_t *y) +{ + struct weston_output *output = &x11_output->base; + wl_fixed_t tx, ty; + wl_fixed_t width = wl_fixed_from_int(output->width - 1); + wl_fixed_t height = wl_fixed_from_int(output->height - 1); + + switch(output->transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + default: + tx = *x; + ty = *y; + break; + case WL_OUTPUT_TRANSFORM_90: + tx = *y; + ty = height - *x; + break; + case WL_OUTPUT_TRANSFORM_180: + tx = width - *x; + ty = height - *y; + break; + case WL_OUTPUT_TRANSFORM_270: + tx = width - *y; + ty = *x; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + tx = width - *x; + ty = *y; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + tx = width - *y; + ty = height - *x; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + tx = *x; + ty = height - *y; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + tx = *y; + ty = *x; + break; + } + + tx += wl_fixed_from_int(output->x); + ty += wl_fixed_from_int(output->y); + + *x = tx; + *y = ty; +} + +static void +x11_compositor_deliver_motion_event(struct x11_compositor *c, + xcb_generic_event_t *event) +{ + struct x11_output *output; + wl_fixed_t x, y; + xcb_motion_notify_event_t *motion_notify = + (xcb_motion_notify_event_t *) event; + + if (!c->has_xkb) + update_xkb_state_from_core(c, motion_notify->state); + output = x11_compositor_find_output(c, motion_notify->event); + x = wl_fixed_from_int(motion_notify->event_x); + y = wl_fixed_from_int(motion_notify->event_y); + x11_output_transform_coordinate(output, &x, &y); + + notify_motion(&c->core_seat, weston_compositor_get_time(), x, y); +} + +static void +x11_compositor_deliver_enter_event(struct x11_compositor *c, + xcb_generic_event_t *event) +{ + struct x11_output *output; + wl_fixed_t x, y; + + xcb_enter_notify_event_t *enter_notify = + (xcb_enter_notify_event_t *) event; + if (enter_notify->state >= Button1Mask) + return; + if (!c->has_xkb) + update_xkb_state_from_core(c, enter_notify->state); + output = x11_compositor_find_output(c, enter_notify->event); + x = wl_fixed_from_int(enter_notify->event_x); + y = wl_fixed_from_int(enter_notify->event_y); + x11_output_transform_coordinate(output, &x, &y); + + notify_pointer_focus(&c->core_seat, &output->base, x, y); +} + static int x11_compositor_next_event(struct x11_compositor *c, xcb_generic_event_t **event, uint32_t mask) @@ -763,7 +866,6 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) struct x11_output *output; xcb_generic_event_t *event, *prev; xcb_client_message_event_t *client_message; - xcb_motion_notify_event_t *motion_notify; xcb_enter_notify_event_t *enter_notify; xcb_key_press_event_t *key_press, *key_release; xcb_keymap_notify_event_t *keymap_notify; @@ -772,7 +874,6 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) xcb_atom_t atom; uint32_t *k; uint32_t i, set; - wl_fixed_t x, y; int count; prev = NULL; @@ -872,14 +973,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) x11_compositor_deliver_button_event(c, event, 0); break; case XCB_MOTION_NOTIFY: - motion_notify = (xcb_motion_notify_event_t *) event; - if (!c->has_xkb) - update_xkb_state_from_core(c, motion_notify->state); - output = x11_compositor_find_output(c, motion_notify->event); - x = wl_fixed_from_int(output->base.x + motion_notify->event_x); - y = wl_fixed_from_int(output->base.y + motion_notify->event_y); - notify_motion(&c->core_seat, - weston_compositor_get_time(), x, y); + x11_compositor_deliver_motion_event(c, event); break; case XCB_EXPOSE: @@ -889,17 +983,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) break; case XCB_ENTER_NOTIFY: - enter_notify = (xcb_enter_notify_event_t *) event; - if (enter_notify->state >= Button1Mask) - break; - if (!c->has_xkb) - update_xkb_state_from_core(c, enter_notify->state); - output = x11_compositor_find_output(c, enter_notify->event); - x = wl_fixed_from_int(output->base.x + enter_notify->event_x); - y = wl_fixed_from_int(output->base.y + enter_notify->event_y); - - notify_pointer_focus(&c->core_seat, - &output->base, x, y); + x11_compositor_deliver_enter_event(c, event); break; case XCB_LEAVE_NOTIFY: @@ -1063,10 +1147,9 @@ x11_compositor_create(struct wl_display *display, int no_input, int argc, char *argv[], const char *config_file) { - static const char name[] = "Weston Compositor"; - char configured_name[32]; struct x11_compositor *c; struct x11_configured_output *o; + struct x11_output *output; xcb_screen_iterator_t s; int i, x = 0, output_count = 0; int width, height, count; @@ -1117,26 +1200,30 @@ x11_compositor_create(struct wl_display *display, count = option_count ? option_count : 1; wl_list_for_each(o, &configured_output_list, link) { - sprintf(configured_name, "%s - %s", name, o->name); - if (x11_compositor_create_output(c, x, 0, - option_width ? option_width : - o->width, - option_height ? option_height : - o->height, - fullscreen, no_input, - configured_name) < 0) + output = x11_compositor_create_output(c, x, 0, + option_width ? width : + o->width, + option_height ? height : + o->height, + fullscreen, no_input, + o->name, o->transform); + if (output == NULL) goto err_x11_input; - x += option_width ? option_width : o->width; + + x = pixman_region32_extents(&output->base.region)->x2; + output_count++; if (option_count && output_count >= option_count) break; } for (i = output_count; i < count; i++) { - if (x11_compositor_create_output(c, x, 0, width, height, - fullscreen, no_input, name) < 0) + output = x11_compositor_create_output(c, x, 0, width, height, + fullscreen, no_input, NULL, + WL_OUTPUT_TRANSFORM_NORMAL); + if (output == NULL) goto err_x11_input; - x += width; + x = pixman_region32_extents(&output->base.region)->x2; } c->xcb_source = @@ -1159,6 +1246,37 @@ err_free: return NULL; } +static void +x11_output_set_transform(struct x11_configured_output *output) +{ + if (!output_transform) { + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + return; + } + + if (!strcmp(output_transform, "normal")) + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + else if (!strcmp(output_transform, "90")) + output->transform = WL_OUTPUT_TRANSFORM_90; + else if (!strcmp(output_transform, "180")) + output->transform = WL_OUTPUT_TRANSFORM_180; + else if (!strcmp(output_transform, "270")) + output->transform = WL_OUTPUT_TRANSFORM_270; + else if (!strcmp(output_transform, "flipped")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; + else if (!strcmp(output_transform, "flipped-90")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; + else if (!strcmp(output_transform, "flipped-180")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; + else if (!strcmp(output_transform, "flipped-270")) + output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; + else { + weston_log("Invalid transform \"%s\" for output %s\n", + output_transform, output_name); + output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + } +} + static void output_section_done(void *data) { @@ -1166,31 +1284,40 @@ output_section_done(void *data) output = malloc(sizeof *output); - if (!output || !output_name || !output_mode) { - free(output_name); + if (!output || !output_name || (output_name[0] != 'X') || + (!output_mode && !output_transform)) { + if (output_name) + free(output_name); output_name = NULL; goto err_free; } output->name = output_name; - if (output_name[0] != 'X') { - x11_free_configured_output(output); - goto err_free; + if (output_mode) { + if (sscanf(output_mode, "%dx%d", &output->width, + &output->height) != 2) { + weston_log("Invalid mode \"%s\" for output %s\n", + output_mode, output_name); + x11_free_configured_output(output); + goto err_free; + } + } else { + output->width = 1024; + output->height = 640; } - if (sscanf(output_mode, "%dx%d", &output->width, &output->height) != 2) { - weston_log("Invalid mode \"%s\" for output %s\n", - output_mode, output_name); - x11_free_configured_output(output); - goto err_free; - } + x11_output_set_transform(output); wl_list_insert(configured_output_list.prev, &output->link); err_free: - free(output_mode); + if (output_mode) + free(output_mode); + if (output_transform) + free(output_transform); output_mode = NULL; + output_transform = NULL; } WL_EXPORT struct weston_compositor * @@ -1215,6 +1342,7 @@ backend_init(struct wl_display *display, int argc, char *argv[], const struct config_key x11_config_keys[] = { { "name", CONFIG_KEY_STRING, &output_name }, { "mode", CONFIG_KEY_STRING, &output_mode }, + { "transform", CONFIG_KEY_STRING, &output_transform }, }; const struct config_section config_section[] = { diff --git a/src/compositor.c b/src/compositor.c index 1bf7c96f..df28cb76 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1148,6 +1148,7 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs) output->border.left + output->border.right; height = output->current->height + output->border.top + output->border.bottom; + glViewport(0, 0, width, height); /* Rebuild the surface list and update surface transforms up front. */ @@ -1731,14 +1732,14 @@ clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy) if (!valid) { if (x < prev->x) *fx = wl_fixed_from_int(prev->x); - else if (x >= prev->x + prev->current->width) + else if (x >= prev->x + prev->width) *fx = wl_fixed_from_int(prev->x + - prev->current->width - 1); + prev->width - 1); if (y < prev->y) *fy = wl_fixed_from_int(prev->y); else if (y >= prev->y + prev->current->height) *fy = wl_fixed_from_int(prev->y + - prev->current->height - 1); + prev->height - 1); } } @@ -2972,6 +2973,62 @@ weston_output_destroy(struct weston_output *output) wl_display_remove_global(c->wl_display, output->global); } +static void +weston_output_compute_transform(struct weston_output *output) +{ + struct weston_matrix transform; + int flip; + + weston_matrix_init(&transform); + + switch(output->transform) { + case WL_OUTPUT_TRANSFORM_FLIPPED: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + flip = -1; + break; + default: + flip = 1; + break; + } + + switch(output->transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + case WL_OUTPUT_TRANSFORM_FLIPPED: + transform.d[0] = flip; + transform.d[1] = 0; + transform.d[4] = 0; + transform.d[5] = 1; + break; + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + transform.d[0] = 0; + transform.d[1] = -flip; + transform.d[4] = 1; + transform.d[5] = 0; + break; + case WL_OUTPUT_TRANSFORM_180: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + transform.d[0] = -flip; + transform.d[1] = 0; + transform.d[4] = 0; + transform.d[5] = -1; + break; + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + transform.d[0] = 0; + transform.d[1] = flip; + transform.d[4] = -1; + transform.d[5] = 0; + break; + default: + break; + } + + weston_matrix_multiply(&output->matrix, &transform); +} + WL_EXPORT void weston_output_update_matrix(struct weston_output *output) { @@ -2981,12 +3038,14 @@ weston_output_update_matrix(struct weston_output *output) weston_matrix_init(&output->matrix); weston_matrix_translate(&output->matrix, - -(output->x + (output->border.right + output->current->width - output->border.left) / 2.0), - -(output->y + (output->border.bottom + output->current->height - output->border.top) / 2.0), 0); + -(output->x + (output->border.right + output->width - output->border.left) / 2.0), + -(output->y + (output->border.bottom + output->height - output->border.top) / 2.0), 0); weston_matrix_scale(&output->matrix, - 2.0 / (output->current->width + output->border.left + output->border.right), - -2.0 / (output->current->height + output->border.top + output->border.bottom), 1); + 2.0 / (output->width + output->border.left + output->border.right), + -2.0 / (output->height + output->border.top + output->border.bottom), 1); + + weston_output_compute_transform(output); if (output->zoom.active) { magnification = 1 / (1 - output->zoom.spring_z.current); @@ -3003,6 +3062,32 @@ weston_output_update_matrix(struct weston_output *output) output->dirty = 0; } +static void +weston_output_transform_init(struct weston_output *output, uint32_t transform) +{ + output->transform = transform; + + switch (transform) { + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + /* Swap width and height */ + output->width = output->current->height; + output->height = output->current->width; + break; + case WL_OUTPUT_TRANSFORM_NORMAL: + case WL_OUTPUT_TRANSFORM_180: + case WL_OUTPUT_TRANSFORM_FLIPPED: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + output->width = output->current->width; + output->height = output->current->height; + break; + default: + break; + } +} + WL_EXPORT void weston_output_move(struct weston_output *output, int x, int y) { @@ -3011,13 +3096,13 @@ weston_output_move(struct weston_output *output, int x, int y) pixman_region32_init(&output->previous_damage); pixman_region32_init_rect(&output->region, x, y, - output->current->width, - output->current->height); + output->width, + output->height); } WL_EXPORT void weston_output_init(struct weston_output *output, struct weston_compositor *c, - int x, int y, int width, int height) + int x, int y, int width, int height, uint32_t transform) { output->compositor = c; output->x = x; @@ -3029,8 +3114,11 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c, output->mm_width = width; output->mm_height = height; output->dirty = 1; - output->transform = WL_OUTPUT_TRANSFORM_NORMAL; + if (transform != WL_OUTPUT_TRANSFORM_NORMAL) + output->disable_planes++; + + weston_output_transform_init(output, transform); weston_output_init_zoom(output); weston_output_move(output, x, y); diff --git a/src/compositor.h b/src/compositor.h index b8e767db..ac887ee1 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -155,7 +155,8 @@ struct weston_output { struct weston_compositor *compositor; struct weston_matrix matrix; struct wl_list animation_list; - int32_t x, y, mm_width, mm_height; + int32_t x, y, width, height; + int32_t mm_width, mm_height; struct weston_border border; pixman_region32_t region; pixman_region32_t previous_damage; @@ -678,7 +679,7 @@ void weston_output_move(struct weston_output *output, int x, int y); void weston_output_init(struct weston_output *output, struct weston_compositor *c, - int x, int y, int width, int height); + int x, int y, int width, int height, uint32_t transform); void weston_output_destroy(struct weston_output *output); diff --git a/src/shell.c b/src/shell.c index 4d6bc4ff..2bd23fc6 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1373,8 +1373,8 @@ shell_surface_set_maximized(struct wl_client *client, edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT; shsurf->client->send_configure(shsurf->surface, edges, - shsurf->output->current->width, - shsurf->output->current->height - panel_height); + shsurf->output->width, + shsurf->output->height - panel_height); shsurf->next_type = SHELL_SURFACE_MAXIMIZED; } @@ -1419,8 +1419,8 @@ shell_configure_fullscreen(struct shell_surface *shsurf) create_black_surface(surface->compositor, surface, output->x, output->y, - output->current->width, - output->current->height); + output->width, + output->height); wl_list_remove(&shsurf->fullscreen.black_surface->layer_link); wl_list_insert(&surface->layer_link, @@ -1436,23 +1436,23 @@ shell_configure_fullscreen(struct shell_surface *shsurf) matrix = &shsurf->fullscreen.transform.matrix; weston_matrix_init(matrix); - output_aspect = (float) output->current->width / - (float) output->current->height; + output_aspect = (float) output->width / + (float) output->height; surface_aspect = (float) surface->geometry.width / (float) surface->geometry.height; if (output_aspect < surface_aspect) - scale = (float) output->current->width / + scale = (float) output->width / (float) surface->geometry.width; else - scale = (float) output->current->height / + scale = (float) output->height / (float) surface->geometry.height; weston_matrix_scale(matrix, scale, scale, 1); wl_list_remove(&shsurf->fullscreen.transform.link); wl_list_insert(&surface->geometry.transformation_list, &shsurf->fullscreen.transform.link); - x = output->x + (output->current->width - surface->geometry.width * scale) / 2; - y = output->y + (output->current->height - surface->geometry.height * scale) / 2; + x = output->x + (output->width - surface->geometry.width * scale) / 2; + y = output->y + (output->height - surface->geometry.height * scale) / 2; weston_surface_set_position(surface, x, y); break; @@ -1466,8 +1466,8 @@ shell_configure_fullscreen(struct shell_surface *shsurf) if (weston_output_switch_mode(output, &mode) == 0) { weston_surface_configure(shsurf->fullscreen.black_surface, output->x, output->y, - output->current->width, - output->current->height); + output->width, + output->height); weston_surface_set_position(surface, output->x, output->y); break; } @@ -1498,8 +1498,8 @@ shell_stack_fullscreen(struct shell_surface *shsurf) create_black_surface(surface->compositor, surface, output->x, output->y, - output->current->width, - output->current->height); + output->width, + output->height); wl_list_remove(&shsurf->fullscreen.black_surface->layer_link); wl_list_insert(&surface->layer_link, @@ -1537,8 +1537,8 @@ shell_surface_set_fullscreen(struct wl_client *client, shsurf->next_type = SHELL_SURFACE_FULLSCREEN; shsurf->client->send_configure(shsurf->surface, 0, - shsurf->output->current->width, - shsurf->output->current->height); + shsurf->output->width, + shsurf->output->height); } static void @@ -1915,8 +1915,8 @@ desktop_shell_set_background(struct wl_client *client, surface->output = output_resource->data; desktop_shell_send_configure(resource, 0, surface_resource, - surface->output->current->width, - surface->output->current->height); + surface->output->width, + surface->output->height); } static void @@ -1948,8 +1948,8 @@ desktop_shell_set_panel(struct wl_client *client, surface->output = output_resource->data; desktop_shell_send_configure(resource, 0, surface_resource, - surface->output->current->width, - surface->output->current->height); + surface->output->width, + surface->output->height); } static void @@ -2567,9 +2567,8 @@ hide_input_panels(struct wl_listener *listener, void *data) static void center_on_output(struct weston_surface *surface, struct weston_output *output) { - struct weston_mode *mode = output->current; - GLfloat x = (mode->width - surface->buffer->width) / 2; - GLfloat y = (mode->height - surface->buffer->height) / 2; + GLfloat x = (output->width - surface->buffer->width) / 2; + GLfloat y = (output->height - surface->buffer->height) / 2; weston_surface_configure(surface, output->x + x, output->y + y, surface->buffer->width, @@ -2618,8 +2617,8 @@ weston_surface_set_initial_position (struct weston_surface *surface, * output. */ panel_height = get_output_panel_height(shell, target_output); - range_x = target_output->current->width - surface->geometry.width; - range_y = (target_output->current->height - panel_height) - + range_x = target_output->width - surface->geometry.width; + range_y = (target_output->height - panel_height) - surface->geometry.height; if (range_x > 0) diff --git a/src/zoom.c b/src/zoom.c index 56a9eadb..674a80ea 100644 --- a/src/zoom.c +++ b/src/zoom.c @@ -187,13 +187,57 @@ zoom_area_center_from_pointer(struct weston_output *output, float level = output->zoom.spring_z.current; wl_fixed_t offset_x = wl_fixed_from_int(output->x); wl_fixed_t offset_y = wl_fixed_from_int(output->y); - wl_fixed_t w = wl_fixed_from_int(output->current->width); - wl_fixed_t h = wl_fixed_from_int(output->current->height); + wl_fixed_t w = wl_fixed_from_int(output->width); + wl_fixed_t h = wl_fixed_from_int(output->height); *x -= ((((*x - offset_x) / (float) w) - 0.5) * (w * (1.0 - level))); *y -= ((((*y - offset_y) / (float) h) - 0.5) * (h * (1.0 - level))); } +static void +weston_zoom_apply_output_transform(struct weston_output *output, + float *x, float *y) +{ + float tx, ty; + + switch(output->transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + default: + return; + case WL_OUTPUT_TRANSFORM_90: + tx = -*y; + ty = *x; + break; + case WL_OUTPUT_TRANSFORM_180: + tx = -*x; + ty = -*y; + break; + case WL_OUTPUT_TRANSFORM_270: + tx = *y; + ty = -*x; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + tx = -*x; + ty = *y; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + tx = -*y; + ty = -*x; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + tx = *x; + ty = -*y; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + tx = *y; + ty = *x; + break; + } + + *x = tx; + *y = ty; +} + static void weston_output_update_zoom_transform(struct weston_output *output) { @@ -218,12 +262,15 @@ weston_output_update_zoom_transform(struct weston_output *output) global_y = wl_fixed_to_double(y); output->zoom.trans_x = - ((((global_x - output->x) / output->current->width) * + ((((global_x - output->x) / output->width) * (level * 2)) - level) * ratio; output->zoom.trans_y = - ((((global_y - output->y) / output->current->height) * + ((((global_y - output->y) / output->height) * (level * 2)) - level) * ratio; + weston_zoom_apply_output_transform(output, &output->zoom.trans_x, + &output->zoom.trans_y); + trans_max = level * 2 - level; trans_min = -trans_max; diff --git a/weston.ini b/weston.ini index 3fda31b5..99d24dd3 100644 --- a/weston.ini +++ b/weston.ini @@ -37,11 +37,14 @@ duration=600 #[output] #name=LVDS1 #mode=1680x1050 +#transform=90 #[output] #name=VGA1 #mode=173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync +#transform=flipped #[output] #name=X1 #mode=1024x768 +#transform=flipped-270