mirror of
https://github.com/Llewellynvdm/conky.git
synced 2025-01-27 00:58:36 +00:00
wayland: implement buffer scaling
This commit is contained in:
parent
9ce6ffbb87
commit
4c71e4527b
@ -291,6 +291,7 @@ struct window {
|
||||
struct wl_surface *surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
int scale;
|
||||
cairo_surface_t *cairo_surface;
|
||||
cairo_t *cr;
|
||||
PangoLayout *layout;
|
||||
@ -321,6 +322,63 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||
.ping = &xdg_wm_base_ping,
|
||||
};
|
||||
|
||||
static void
|
||||
output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y,
|
||||
int32_t physical_width, int32_t physical_height,
|
||||
int32_t subpixel, const char *make, const char *model,
|
||||
int32_t transform)
|
||||
{}
|
||||
|
||||
static void
|
||||
output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
|
||||
int32_t width, int32_t height, int32_t refresh)
|
||||
{}
|
||||
|
||||
#ifdef WL_OUTPUT_DONE_SINCE_VERSION
|
||||
static void
|
||||
output_done(void *data, struct wl_output *wl_output)
|
||||
{}
|
||||
#endif
|
||||
|
||||
#ifdef WL_OUTPUT_SCALE_SINCE_VERSION
|
||||
void
|
||||
output_scale(void *data, struct wl_output *wl_output, int32_t factor)
|
||||
{
|
||||
/* For now, assume we have one output and adopt its scale unconditionally. */
|
||||
/* We should also re-render immediately when scale changes. */
|
||||
global_window->scale = factor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
|
||||
static void
|
||||
output_name(void *data, struct wl_output *wl_output, const char *name)
|
||||
{}
|
||||
#endif
|
||||
|
||||
#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
|
||||
static void
|
||||
output_description(void *data, struct wl_output *wl_output,
|
||||
const char *description)
|
||||
{}
|
||||
#endif
|
||||
|
||||
const struct wl_output_listener output_listener = {
|
||||
/*.geometry =*/ output_geometry,
|
||||
/*.mode =*/ output_mode,
|
||||
#ifdef WL_OUTPUT_DONE_SINCE_VERSION
|
||||
/*.done =*/ output_done,
|
||||
#endif
|
||||
#ifdef WL_OUTPUT_SCALE_SINCE_VERSION
|
||||
/*.scale =*/ &output_scale,
|
||||
#endif
|
||||
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
|
||||
/*.name =*/ &output_name,
|
||||
#endif
|
||||
#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
|
||||
/*.description =*/ &output_description,
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||
@ -334,7 +392,8 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||
wl_globals.seat = static_cast<wl_seat*>(wl_registry_bind(registry, name,
|
||||
&wl_seat_interface, 1));
|
||||
} else if(strcmp(interface, "wl_output") == 0) {
|
||||
wl_globals.output = static_cast<wl_output*>(wl_registry_bind(registry, name, &wl_output_interface, 1));
|
||||
wl_globals.output = static_cast<wl_output*>(wl_registry_bind(registry, name, &wl_output_interface, 2));
|
||||
wl_output_add_listener(wl_globals.output, &output_listener, nullptr);
|
||||
} else if(strcmp(interface, "xdg_wm_base") == 0) {
|
||||
wl_globals.shell = static_cast<xdg_wm_base*>(wl_registry_bind(registry, name, &xdg_wm_base_interface, 1));
|
||||
xdg_wm_base_add_listener(wl_globals.shell, &xdg_wm_base_listener, nullptr);
|
||||
@ -385,6 +444,9 @@ window_create(struct wl_surface* surface, struct wl_shm* shm, int width, int hei
|
||||
void
|
||||
window_resize(struct window *window, int width, int height);
|
||||
|
||||
void
|
||||
window_allocate_buffer(struct window *window);
|
||||
|
||||
void
|
||||
window_destroy(struct window *window);
|
||||
|
||||
@ -413,6 +475,8 @@ bool display_output_wayland::initialize() {
|
||||
|
||||
struct wl_surface *surface = wl_compositor_create_surface(wl_globals.compositor);
|
||||
global_window = window_create(surface, wl_globals.shm, 1, 1);
|
||||
global_window->scale = 1;
|
||||
window_allocate_buffer(global_window);
|
||||
|
||||
global_window->xdg_surface = xdg_wm_base_get_xdg_surface(wl_globals.shell, global_window->surface);
|
||||
xdg_surface_add_listener(global_window->xdg_surface, &xdg_surface_listener, nullptr);
|
||||
@ -423,7 +487,7 @@ bool display_output_wayland::initialize() {
|
||||
xdg_toplevel_set_app_id(global_window->xdg_toplevel, "conky");
|
||||
xdg_toplevel_set_title(global_window->xdg_toplevel, "conky");
|
||||
xdg_toplevel_set_parent(global_window->xdg_toplevel, 0);
|
||||
wl_surface_set_buffer_scale(global_window->surface, 1);
|
||||
wl_surface_set_buffer_scale(global_window->surface, global_window->scale);
|
||||
wl_surface_commit(global_window->surface);
|
||||
wl_display_roundtrip(global_display);
|
||||
|
||||
@ -950,19 +1014,23 @@ shm_pool_destroy(struct shm_pool *pool)
|
||||
}
|
||||
|
||||
static int
|
||||
data_length_for_shm_surface(struct rectangle *rect)
|
||||
{
|
||||
stride_for_shm_surface(struct rectangle *rect, int scale) {
|
||||
return cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, rect->width * scale);
|
||||
}
|
||||
|
||||
static int
|
||||
data_length_for_shm_surface(struct rectangle *rect, int scale) {
|
||||
int stride;
|
||||
|
||||
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
|
||||
rect->width);
|
||||
return stride * rect->height;
|
||||
stride = stride_for_shm_surface(rect, scale);
|
||||
return stride * rect->height * scale;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
create_shm_surface_from_pool(void *none,
|
||||
struct rectangle *rectangle,
|
||||
struct shm_pool *pool)
|
||||
struct shm_pool *pool,
|
||||
int scale)
|
||||
{
|
||||
struct shm_surface_data *data;
|
||||
uint32_t format;
|
||||
@ -977,8 +1045,8 @@ create_shm_surface_from_pool(void *none,
|
||||
|
||||
cairo_format = CAIRO_FORMAT_ARGB32; /*or CAIRO_FORMAT_RGB16_565 who knows??*/
|
||||
|
||||
stride = cairo_format_stride_for_width (cairo_format, rectangle->width);
|
||||
length = stride * rectangle->height;
|
||||
stride = stride_for_shm_surface (rectangle, scale);
|
||||
length = data_length_for_shm_surface(rectangle, scale);
|
||||
data->pool = NULL;
|
||||
map = shm_pool_allocate(pool, length, &offset);
|
||||
|
||||
@ -989,8 +1057,8 @@ create_shm_surface_from_pool(void *none,
|
||||
|
||||
surface = cairo_image_surface_create_for_data (static_cast<unsigned char*>(map),
|
||||
cairo_format,
|
||||
rectangle->width,
|
||||
rectangle->height,
|
||||
rectangle->width * scale,
|
||||
rectangle->height * scale,
|
||||
stride);
|
||||
|
||||
cairo_surface_set_user_data(surface, &shm_surface_data_key,
|
||||
@ -999,8 +1067,8 @@ create_shm_surface_from_pool(void *none,
|
||||
format = WL_SHM_FORMAT_ARGB8888; /*or WL_SHM_FORMAT_RGB565*/
|
||||
|
||||
data->buffer = wl_shm_pool_create_buffer(pool->pool, offset,
|
||||
rectangle->width,
|
||||
rectangle->height,
|
||||
rectangle->width * scale,
|
||||
rectangle->height * scale,
|
||||
stride, format);
|
||||
|
||||
return surface;
|
||||
@ -1011,14 +1079,15 @@ window_allocate_buffer(struct window *window) {
|
||||
assert(window->shm != nullptr);
|
||||
struct shm_pool *pool;
|
||||
pool = shm_pool_create(window->shm,
|
||||
data_length_for_shm_surface(&window->rectangle));
|
||||
data_length_for_shm_surface(&window->rectangle, window->scale));
|
||||
if (!pool) {
|
||||
fprintf(stderr, "could not allocate shm pool\n");
|
||||
return;
|
||||
}
|
||||
|
||||
window->cairo_surface =
|
||||
create_shm_surface_from_pool(window->shm, &window->rectangle, pool);
|
||||
create_shm_surface_from_pool(window->shm, &window->rectangle, pool, window->scale);
|
||||
cairo_surface_set_device_scale(window->cairo_surface, window->scale, window->scale);
|
||||
|
||||
if (!window->cairo_surface) {
|
||||
shm_pool_destroy(pool);
|
||||
@ -1044,11 +1113,15 @@ window_create(struct wl_surface* surface, struct wl_shm* shm, int width, int hei
|
||||
window->rectangle.y = 0;
|
||||
window->rectangle.width = width;
|
||||
window->rectangle.height = height;
|
||||
window->scale = 1;
|
||||
|
||||
window->surface = surface;
|
||||
window->shm = shm;
|
||||
|
||||
window_allocate_buffer(window);
|
||||
window->cairo_surface = nullptr;
|
||||
window->cr = nullptr;
|
||||
window->layout = nullptr;
|
||||
window->pango_context = nullptr;
|
||||
|
||||
return window;
|
||||
}
|
||||
@ -1084,6 +1157,7 @@ window_resize(struct window *window, int width, int height) {
|
||||
void
|
||||
window_commit_buffer(struct window *window) {
|
||||
assert(window->cairo_surface != nullptr);
|
||||
wl_surface_set_buffer_scale(global_window->surface, global_window->scale);
|
||||
wl_surface_attach(window->surface, get_buffer_from_cairo_surface(window->cairo_surface), 0, 0);
|
||||
/* repaint all the pixels in the surface, change size to only repaint changed area*/
|
||||
wl_surface_damage(window->surface, window->rectangle.x,
|
||||
|
Loading…
x
Reference in New Issue
Block a user