compositor-x11: Implement mode switching
Signed-off-by: Armin Krezović <krezovic.armin@gmail.com> Reviewed-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
parent
7861fa9151
commit
b9906aaead
@ -65,6 +65,12 @@
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE 10
|
||||
|
||||
#define WINDOW_MIN_WIDTH 128
|
||||
#define WINDOW_MIN_HEIGHT 128
|
||||
|
||||
#define WINDOW_MAX_WIDTH 8192
|
||||
#define WINDOW_MAX_HEIGHT 8192
|
||||
|
||||
struct x11_backend {
|
||||
struct weston_backend base;
|
||||
struct weston_compositor *compositor;
|
||||
@ -114,6 +120,7 @@ struct x11_output {
|
||||
|
||||
xcb_window_t window;
|
||||
struct weston_mode mode;
|
||||
struct weston_mode native;
|
||||
struct wl_event_source *finish_frame_timer;
|
||||
|
||||
xcb_gc_t gc;
|
||||
@ -123,6 +130,8 @@ struct x11_output {
|
||||
void *buf;
|
||||
uint8_t depth;
|
||||
int32_t scale;
|
||||
bool resize_pending;
|
||||
bool window_resized;
|
||||
};
|
||||
|
||||
struct window_delete_data {
|
||||
@ -772,6 +781,89 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
||||
{
|
||||
struct x11_backend *b;
|
||||
struct x11_output *output;
|
||||
static uint32_t values[2];
|
||||
int ret;
|
||||
|
||||
if (base == NULL) {
|
||||
weston_log("output is NULL.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode == NULL) {
|
||||
weston_log("mode is NULL.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
b = to_x11_backend(base->compositor);
|
||||
output = to_x11_output(base);
|
||||
|
||||
if (mode->width == output->mode.width &&
|
||||
mode->height == output->mode.height)
|
||||
return 0;
|
||||
|
||||
if (mode->width < WINDOW_MIN_WIDTH || mode->width > WINDOW_MAX_WIDTH)
|
||||
return -1;
|
||||
|
||||
if (mode->height < WINDOW_MIN_HEIGHT || mode->height > WINDOW_MAX_HEIGHT)
|
||||
return -1;
|
||||
|
||||
/* xcb_configure_window will create an event, and we could end up
|
||||
being called twice */
|
||||
output->resize_pending = true;
|
||||
|
||||
/* window could've been resized by the user, so don't do it twice */
|
||||
if (!output->window_resized) {
|
||||
values[0] = mode->width;
|
||||
values[1] = mode->height;
|
||||
xcb_configure_window(b->conn, output->window, XCB_CONFIG_WINDOW_WIDTH |
|
||||
XCB_CONFIG_WINDOW_HEIGHT, values);
|
||||
}
|
||||
|
||||
output->mode.width = mode->width;
|
||||
output->mode.height = mode->height;
|
||||
|
||||
if (b->use_pixman) {
|
||||
pixman_renderer_output_destroy(&output->base);
|
||||
x11_output_deinit_shm(b, output);
|
||||
|
||||
if (x11_output_init_shm(b, output,
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height) < 0) {
|
||||
weston_log("Failed to initialize SHM for the X11 output\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pixman_renderer_output_create(&output->base) < 0) {
|
||||
weston_log("Failed to create pixman renderer for output\n");
|
||||
x11_output_deinit_shm(b, output);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
Window xid = (Window) output->window;
|
||||
|
||||
gl_renderer->output_destroy(&output->base);
|
||||
|
||||
ret = gl_renderer->output_window_create(&output->base,
|
||||
(EGLNativeWindowType) output->window,
|
||||
&xid,
|
||||
gl_renderer->opaque_attribs,
|
||||
NULL,
|
||||
0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
output->resize_pending = false;
|
||||
output->window_resized = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
x11_output_disable(struct weston_output *base)
|
||||
{
|
||||
@ -864,14 +956,13 @@ x11_output_enable(struct weston_output *base)
|
||||
XCB_ATOM_ATOM, 32,
|
||||
ARRAY_LENGTH(atom_list), atom_list);
|
||||
} else {
|
||||
/* Don't resize me. */
|
||||
memset(&normal_hints, 0, sizeof normal_hints);
|
||||
normal_hints.flags =
|
||||
WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
|
||||
normal_hints.min_width = output->base.current_mode->width;
|
||||
normal_hints.min_height = output->base.current_mode->height;
|
||||
normal_hints.max_width = output->base.current_mode->width;
|
||||
normal_hints.max_height = output->base.current_mode->height;
|
||||
normal_hints.min_width = WINDOW_MIN_WIDTH;
|
||||
normal_hints.min_height = WINDOW_MIN_HEIGHT;
|
||||
normal_hints.max_width = WINDOW_MAX_WIDTH;
|
||||
normal_hints.max_height = WINDOW_MAX_HEIGHT;
|
||||
xcb_change_property(b->conn, XCB_PROP_MODE_REPLACE, output->window,
|
||||
b->atom.wm_normal_hints,
|
||||
b->atom.wm_size_hints, 32,
|
||||
@ -945,7 +1036,7 @@ x11_output_enable(struct weston_output *base)
|
||||
output->base.assign_planes = NULL;
|
||||
output->base.set_backlight = NULL;
|
||||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = NULL;
|
||||
output->base.switch_mode = x11_output_switch_mode;
|
||||
|
||||
loop = wl_display_get_event_loop(b->compositor->wl_display);
|
||||
output->finish_frame_timer =
|
||||
@ -978,13 +1069,13 @@ x11_output_set_size(struct weston_output *base, int width, int height)
|
||||
/* Make sure we have scale set. */
|
||||
assert(output->base.scale);
|
||||
|
||||
if (width < 1) {
|
||||
if (width < WINDOW_MIN_WIDTH) {
|
||||
weston_log("Invalid width \"%d\" for output %s\n",
|
||||
width, output->base.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (height < 1) {
|
||||
if (height < WINDOW_MIN_HEIGHT) {
|
||||
weston_log("Invalid height \"%d\" for output %s\n",
|
||||
height, output->base.name);
|
||||
return -1;
|
||||
@ -999,6 +1090,7 @@ x11_output_set_size(struct weston_output *base, int width, int height)
|
||||
output->mode.width = output_width;
|
||||
output->mode.height = output_height;
|
||||
output->mode.refresh = 60000;
|
||||
output->native = output->mode;
|
||||
output->scale = output->base.scale;
|
||||
wl_list_insert(&output->base.mode_list, &output->mode.link);
|
||||
|
||||
@ -1006,6 +1098,9 @@ x11_output_set_size(struct weston_output *base, int width, int height)
|
||||
output->base.make = "weston-X11";
|
||||
output->base.model = "none";
|
||||
|
||||
output->base.native_mode = &output->native;
|
||||
output->base.native_scale = output->base.scale;
|
||||
|
||||
output->base.mm_width = width * b->screen->width_in_millimeters /
|
||||
b->screen->width_in_pixels;
|
||||
output->base.mm_height = height * b->screen->height_in_millimeters /
|
||||
@ -1319,6 +1414,7 @@ x11_backend_handle_event(int fd, uint32_t mask, void *data)
|
||||
xcb_keymap_notify_event_t *keymap_notify;
|
||||
xcb_focus_in_event_t *focus_in;
|
||||
xcb_expose_event_t *expose;
|
||||
xcb_configure_notify_event_t *configure;
|
||||
xcb_atom_t atom;
|
||||
xcb_window_t window;
|
||||
uint32_t *k;
|
||||
@ -1474,6 +1570,31 @@ x11_backend_handle_event(int fd, uint32_t mask, void *data)
|
||||
}
|
||||
break;
|
||||
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
configure = (struct xcb_configure_notify_event_t *) event;
|
||||
struct x11_output *output =
|
||||
x11_backend_find_output(b, configure->window);
|
||||
|
||||
if (!output || output->resize_pending)
|
||||
break;
|
||||
|
||||
struct weston_mode mode = output->mode;
|
||||
|
||||
if (mode.width == configure->width &&
|
||||
mode.height == configure->height)
|
||||
break;
|
||||
|
||||
output->window_resized = true;
|
||||
|
||||
mode.width = configure->width;
|
||||
mode.height = configure->height;
|
||||
|
||||
if (weston_output_mode_set_native(&output->base,
|
||||
&mode, output->scale) < 0)
|
||||
weston_log("Mode switch failed\n");
|
||||
|
||||
break;
|
||||
|
||||
case XCB_FOCUS_IN:
|
||||
focus_in = (xcb_focus_in_event_t *) event;
|
||||
if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED)
|
||||
|
Loading…
x
Reference in New Issue
Block a user