return ret;
}
-static int
-weston_x11_backend_config_append_output_config(struct weston_x11_backend_config *config,
- struct weston_x11_backend_output_config *output_config) {
- struct weston_x11_backend_output_config *new_outputs;
-
- new_outputs = realloc(config->outputs, (config->num_outputs+1) *
- sizeof(struct weston_x11_backend_output_config));
- if (new_outputs == NULL)
- return -1;
-
- config->outputs = new_outputs;
- config->outputs[config->num_outputs].width = output_config->width;
- config->outputs[config->num_outputs].height = output_config->height;
- config->outputs[config->num_outputs].transform = output_config->transform;
- config->outputs[config->num_outputs].scale = output_config->scale;
- config->outputs[config->num_outputs].name = strdup(output_config->name);
- config->num_outputs++;
+static void
+x11_backend_output_configure(struct wl_listener *listener, void *data)
+{
+ struct weston_output *output = data;
+ struct wet_output_config defaults = {
+ .width = 1024,
+ .height = 600,
+ .scale = 1,
+ .transform = WL_OUTPUT_TRANSFORM_NORMAL
+ };
- return 0;
+ if (wet_configure_windowed_output_from_config(output, &defaults) < 0)
+ weston_log("Cannot configure output \"%s\".\n", output->name);
}
static int
load_x11_backend(struct weston_compositor *c,
int *argc, char **argv, struct weston_config *wc)
{
- struct weston_x11_backend_output_config default_output;
+ char *default_output;
+ const struct weston_windowed_output_api *api;
struct weston_x11_backend_config config = {{ 0, }};
struct weston_config_section *section;
int ret = 0;
- int option_width = 0;
- int option_height = 0;
- int option_scale = 0;
int option_count = 1;
int output_count = 0;
char const *section_name;
int i;
- uint32_t j;
+
+ struct wet_output_config *parsed_options = wet_init_parsed_options(c);
+ if (!parsed_options)
+ return -1;
const struct weston_option options[] = {
- { WESTON_OPTION_INTEGER, "width", 0, &option_width },
- { WESTON_OPTION_INTEGER, "height", 0, &option_height },
- { WESTON_OPTION_INTEGER, "scale", 0, &option_scale },
+ { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
+ { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
+ { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
{ WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &config.fullscreen },
{ WESTON_OPTION_INTEGER, "output-count", 0, &option_count },
{ WESTON_OPTION_BOOLEAN, "no-input", 0, &config.no_input },
parse_options(options, ARRAY_LENGTH(options), argc, argv);
+ config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
+ config.base.struct_size = sizeof(struct weston_x11_backend_config);
+
+ /* load the actual backend and configure it */
+ ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
+ &config.base);
+
+ if (ret < 0)
+ return ret;
+
+ wet_set_pending_output_handler(c, x11_backend_output_configure);
+
+ api = weston_windowed_output_get_api(c);
+
+ if (!api) {
+ weston_log("Cannot use weston_windowed_output_api.\n");
+ return -1;
+ }
+
section = NULL;
while (weston_config_next_section(wc, §ion, §ion_name)) {
- struct weston_x11_backend_output_config current_output = { 0, };
- char *t;
- char *mode;
+ char *output_name;
+
+ if (output_count >= option_count)
+ break;
if (strcmp(section_name, "output") != 0) {
continue;
}
- weston_config_section_get_string(section, "name", ¤t_output.name, NULL);
- if (current_output.name == NULL || current_output.name[0] != 'X') {
- free(current_output.name);
+ weston_config_section_get_string(section, "name", &output_name, NULL);
+ if (output_name == NULL || output_name[0] != 'X') {
+ free(output_name);
continue;
}
- weston_config_section_get_string(section, "mode", &mode, "1024x600");
- if (sscanf(mode, "%dx%d", ¤t_output.width,
- ¤t_output.height) != 2) {
- weston_log("Invalid mode \"%s\" for output %s\n",
- mode, current_output.name);
- current_output.width = 1024;
- current_output.height = 600;
- }
- free(mode);
- if (current_output.width < 1)
- current_output.width = 1024;
- if (current_output.height < 1)
- current_output.height = 600;
- if (option_width)
- current_output.width = option_width;
- if (option_height)
- current_output.height = option_height;
-
- weston_config_section_get_int(section, "scale", ¤t_output.scale, 1);
- if (option_scale)
- current_output.scale = option_scale;
-
- weston_config_section_get_string(section,
- "transform", &t, "normal");
- if (weston_parse_transform(t, ¤t_output.transform) < 0)
- weston_log("Invalid transform \"%s\" for output %s\n",
- t, current_output.name);
- free(t);
-
- if (weston_x11_backend_config_append_output_config(&config, ¤t_output) < 0) {
- ret = -1;
- goto out;
+ if (api->output_create(c, output_name) < 0) {
+ free(output_name);
+ return -1;
}
+ free(output_name);
output_count++;
- if (output_count >= option_count)
- break;
}
- default_output.name = NULL;
- default_output.width = option_width ? option_width : 1024;
- default_output.height = option_height ? option_height : 600;
- default_output.scale = option_scale ? option_scale : 1;
- default_output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ default_output = NULL;
for (i = output_count; i < option_count; i++) {
- if (asprintf(&default_output.name, "screen%d", i) < 0) {
- ret = -1;
- goto out;
+ if (asprintf(&default_output, "screen%d", i) < 0) {
+ return -1;
}
- if (weston_x11_backend_config_append_output_config(&config, &default_output) < 0) {
- ret = -1;
- free(default_output.name);
- goto out;
+ if (api->output_create(c, default_output) < 0) {
+ free(default_output);
+ return -1;
}
- free(default_output.name);
+ free(default_output);
}
- config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
- config.base.struct_size = sizeof(struct weston_x11_backend_config);
-
- /* load the actual backend and configure it */
- ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
- &config.base);
-
-out:
- for (j = 0; j < config.num_outputs; ++j)
- free(config.outputs[j].name);
- free(config.outputs);
-
- return ret;
+ return 0;
}
static void
#include "pixman-renderer.h"
#include "presentation-time-server-protocol.h"
#include "linux-dmabuf.h"
+#include "windowed-output-api.h"
#define DEFAULT_AXIS_STEP_DISTANCE 10
struct xkb_keymap *xkb_keymap;
unsigned int has_xkb;
uint8_t xkb_event_base;
+ int fullscreen;
+ int no_input;
int use_pixman;
int has_net_wm_state_fullscreen;
}
static void
-x11_output_destroy(struct weston_output *output_base)
-{
- struct x11_output *output = to_x11_output(output_base);
- struct x11_backend *backend =
- to_x11_backend(output->base.compositor);
-
- wl_event_source_remove(output->finish_frame_timer);
-
- if (backend->use_pixman) {
- pixman_renderer_output_destroy(output_base);
- x11_output_deinit_shm(backend, output);
- } else
- gl_renderer->output_destroy(output_base);
-
- xcb_destroy_window(backend->conn, output->window);
-
- xcb_flush(backend->conn);
-
- weston_output_destroy(&output->base);
-
- free(output);
-}
-
-static void
x11_output_set_wm_protocols(struct x11_backend *b,
struct x11_output *output)
{
return 0;
}
-static struct x11_output *
-x11_backend_create_output(struct x11_backend *b, int x, int y,
- int width, int height, int fullscreen,
- int no_input, char *configured_name,
- uint32_t transform, int32_t scale)
+static int
+x11_output_disable(struct weston_output *base)
+{
+ struct x11_output *output = to_x11_output(base);
+ struct x11_backend *backend = to_x11_backend(base->compositor);
+
+ if (!output->base.enabled)
+ return 0;
+
+ wl_event_source_remove(output->finish_frame_timer);
+
+ if (backend->use_pixman) {
+ pixman_renderer_output_destroy(&output->base);
+ x11_output_deinit_shm(backend, output);
+ } else {
+ gl_renderer->output_destroy(&output->base);
+ }
+
+ xcb_destroy_window(backend->conn, output->window);
+ xcb_flush(backend->conn);
+
+ return 0;
+}
+
+static void
+x11_output_destroy(struct weston_output *base)
+{
+ struct x11_output *output = to_x11_output(base);
+
+ x11_output_disable(&output->base);
+ weston_output_destroy(&output->base);
+
+ free(output);
+}
+
+static int
+x11_output_enable(struct weston_output *base)
{
+ struct x11_output *output = to_x11_output(base);
+ struct x11_backend *b = to_x11_backend(base->compositor);
+
static const char name[] = "Weston Compositor";
static const char class[] = "weston-1\0Weston Compositor";
char *title = NULL;
- struct x11_output *output;
xcb_screen_t *screen;
struct wm_normal_hints normal_hints;
struct wl_event_loop *loop;
- int output_width, output_height, width_mm, height_mm;
+
int ret;
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
xcb_atom_t atom_list[1];
0
};
- output_width = width * scale;
- output_height = height * scale;
-
- if (!no_input)
+ if (!b->no_input)
values[0] |=
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_KEYMAP_STATE |
XCB_EVENT_MASK_FOCUS_CHANGE;
- output = zalloc(sizeof *output);
- if (output == NULL) {
- perror("zalloc");
- return NULL;
- }
-
- output->mode.flags =
- WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
-
- output->mode.width = output_width;
- output->mode.height = output_height;
- output->mode.refresh = 60000;
- output->scale = scale;
- wl_list_init(&output->base.mode_list);
- wl_list_insert(&output->base.mode_list, &output->mode.link);
-
values[1] = b->null_cursor;
output->window = xcb_generate_id(b->conn);
screen = x11_compositor_get_default_screen(b);
output->window,
screen->root,
0, 0,
- output_width, output_height,
+ output->base.current_mode->width,
+ output->base.current_mode->height,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, values);
- if (fullscreen) {
+ if (b->fullscreen) {
atom_list[0] = b->atom.net_wm_state_fullscreen;
xcb_change_property(b->conn, XCB_PROP_MODE_REPLACE,
output->window,
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_width;
- normal_hints.min_height = output_height;
- normal_hints.max_width = output_width;
- normal_hints.max_height = output_height;
+ 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;
xcb_change_property(b->conn, XCB_PROP_MODE_REPLACE, output->window,
b->atom.wm_normal_hints,
b->atom.wm_size_hints, 32,
}
/* Set window name. Don't bother with non-EWMH WMs. */
- if (configured_name) {
- if (asprintf(&title, "%s - %s", name, configured_name) < 0)
+ if (output->base.name) {
+ if (asprintf(&title, "%s - %s", name, output->base.name) < 0)
title = NULL;
} else {
title = strdup(name);
strlen(title), title);
free(title);
} else {
- xcb_destroy_window(b->conn, output->window);
- free(output);
- return NULL;
+ goto err;
}
xcb_change_property(b->conn, XCB_PROP_MODE_REPLACE, output->window,
xcb_map_window(b->conn, output->window);
- if (fullscreen)
+ if (b->fullscreen)
x11_output_wait_for_map(b, output);
- output->base.start_repaint_loop = x11_output_start_repaint_loop;
- if (b->use_pixman)
- output->base.repaint = x11_output_repaint_shm;
- else
- output->base.repaint = x11_output_repaint_gl;
- output->base.destroy = x11_output_destroy;
- output->base.assign_planes = NULL;
- output->base.set_backlight = NULL;
- output->base.set_dpms = NULL;
- output->base.switch_mode = NULL;
- output->base.current_mode = &output->mode;
- output->base.make = "weston-X11";
- output->base.model = "none";
-
- if (configured_name)
- output->base.name = strdup(configured_name);
-
- width_mm = width * b->screen->width_in_millimeters /
- b->screen->width_in_pixels;
- height_mm = height * b->screen->height_in_millimeters /
- b->screen->height_in_pixels;
- weston_output_init(&output->base, b->compositor,
- x, y, width_mm, height_mm, transform, scale);
-
if (b->use_pixman) {
if (x11_output_init_shm(b, output,
- output->mode.width,
- output->mode.height) < 0) {
+ output->base.current_mode->width,
+ output->base.current_mode->height) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
- return NULL;
+ goto err;
}
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 NULL;
+ goto err;
}
} else {
/* eglCreatePlatformWindowSurfaceEXT takes a Window*
NULL,
0);
if (ret < 0)
- return NULL;
+ goto err;
}
loop = wl_display_get_event_loop(b->compositor->wl_display);
output->finish_frame_timer =
wl_event_loop_add_timer(loop, finish_frame_handler, output);
- weston_compositor_add_output(b->compositor, &output->base);
-
weston_log("x11 output %dx%d, window id %d\n",
- width, height, output->window);
+ output->base.current_mode->width,
+ output->base.current_mode->height,
+ output->window);
+
+ return 0;
- return output;
+err:
+ xcb_destroy_window(b->conn, output->window);
+ xcb_flush(b->conn);
+
+ return -1;
+}
+
+static int
+x11_output_set_size(struct weston_output *base, int width, int height)
+{
+ struct x11_output *output = to_x11_output(base);
+ struct x11_backend *b = to_x11_backend(base->compositor);
+ int output_width, output_height;
+
+ /* We can only be called once. */
+ assert(!output->base.current_mode);
+
+ /* Make sure we have scale set. */
+ assert(output->base.scale);
+
+ if (width < 1) {
+ weston_log("Invalid width \"%d\" for output %s\n",
+ width, output->base.name);
+ return -1;
+ }
+
+ if (height < 1) {
+ weston_log("Invalid height \"%d\" for output %s\n",
+ height, output->base.name);
+ return -1;
+ }
+
+ output_width = width * output->base.scale;
+ output_height = height * output->base.scale;
+
+ output->mode.flags =
+ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+
+ output->mode.width = output_width;
+ output->mode.height = output_height;
+ output->mode.refresh = 60000;
+ output->scale = output->base.scale;
+ wl_list_init(&output->base.mode_list);
+ wl_list_insert(&output->base.mode_list, &output->mode.link);
+
+ output->base.current_mode = &output->mode;
+ output->base.make = "weston-X11";
+ output->base.model = "none";
+
+ 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 /
+ b->screen->height_in_pixels;
+
+ if (b->use_pixman)
+ output->base.repaint = x11_output_repaint_shm;
+ else
+ output->base.repaint = x11_output_repaint_gl;
+
+ output->base.start_repaint_loop = x11_output_start_repaint_loop;
+ output->base.assign_planes = NULL;
+ output->base.set_backlight = NULL;
+ output->base.set_dpms = NULL;
+ output->base.switch_mode = NULL;
+
+ return 0;
+}
+
+static int
+x11_output_create(struct weston_compositor *compositor,
+ const char *name)
+{
+ struct x11_output *output;
+
+ /* name can't be NULL. */
+ assert(name);
+
+ output = zalloc(sizeof *output);
+ if (output == NULL) {
+ perror("zalloc");
+ return -1;
+ }
+
+ output->base.name = strdup(name);
+ output->base.destroy = x11_output_destroy;
+ output->base.disable = x11_output_disable;
+ output->base.enable = x11_output_enable;
+
+ weston_output_init_pending(&output->base, compositor);
+ weston_compositor_add_pending_output(&output->base, compositor);
+
+ return 0;
}
static struct x11_output *
return ret;
}
+static const struct weston_windowed_output_api api = {
+ x11_output_set_size,
+ x11_output_create,
+};
+
static struct x11_backend *
x11_backend_create(struct weston_compositor *compositor,
struct weston_x11_backend_config *config)
{
struct x11_backend *b;
- struct x11_output *output;
struct wl_event_loop *loop;
- int x = 0;
- unsigned i;
+ int ret;
b = zalloc(sizeof *b);
if (b == NULL)
return NULL;
b->compositor = compositor;
+ b->fullscreen = config->fullscreen;
+ b->no_input = config->no_input;
+
if (weston_compositor_set_presentation_clock_software(compositor) < 0)
goto err_free;
goto err_renderer;
}
- for (i = 0; i < config->num_outputs; ++i) {
- struct weston_x11_backend_output_config *output_iterator =
- &config->outputs[i];
-
- if (output_iterator->name == NULL) {
- continue;
- }
-
- if (output_iterator->width < 1) {
- weston_log("Invalid width \"%d\" for output %s\n",
- output_iterator->width, output_iterator->name);
- goto err_x11_input;
- }
-
- if (output_iterator->height < 1) {
- weston_log("Invalid height \"%d\" for output %s\n",
- output_iterator->height, output_iterator->name);
- goto err_x11_input;
- }
-
- output = x11_backend_create_output(b,
- x,
- 0,
- output_iterator->width,
- output_iterator->height,
- config->fullscreen,
- config->no_input,
- output_iterator->name,
- output_iterator->transform,
- output_iterator->scale);
- if (output == NULL) {
- weston_log("Failed to create configured x11 output\n");
- goto err_x11_input;
- }
-
- x = pixman_region32_extents(&output->base.region)->x2;
- }
-
loop = wl_display_get_event_loop(compositor->wl_display);
b->xcb_source =
wl_event_loop_add_fd(loop,
compositor->backend = &b->base;
+ ret = weston_plugin_api_register(compositor, WESTON_WINDOWED_OUTPUT_API_NAME,
+ &api, sizeof(api));
+
+ if (ret < 0) {
+ weston_log("Failed to register output API.\n");
+ goto err_x11_input;
+ }
+
return b;
err_x11_input: