Я не знаю, как установить положение окна wayland
на экране.
Похоже, это как-то настраивается, потому что на моем ПК окно находится в повторяющемся месте.
Я попробовал решение в Как установить положение поверхности клиента Wayland на фоне Weston?
Но это приводит к сбою моего Ubuntu 18.04 (выходит из системы).
Я написал пример отображения изображения в окне. Изображение отображается, но я хочу иметь возможность программно установить его положение на экране. Необработанное изображение находится здесь.
скомпилировать с gcc wayland_example.cpp -lwayland-client -o wayland_example
беги с ./wayland_example <path_to_image>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <memory.h>
#include <wayland-client.h>
static struct wl_display *display = nullptr;
static struct wl_compositor *compositor = nullptr;
static struct wl_surface *surface;
static struct wl_shell *shell;
static struct wl_shell_surface *shell_surface;
static struct wl_shm *shm;
static struct wl_buffer *buffer;
static struct wl_callback *frame_callback;
static struct wl_registry *registry;
void *shm_data;
uint32_t *im_ptr;
static int w = 0;
static int h = 0;
static void handle_ping(__attribute__((unused)) void *data,
struct wl_shell_surface *in_shell_surface, uint32_t serial) {
wl_shell_surface_pong(in_shell_surface, serial);
}
static void handle_configure(__attribute__((unused)) void *data,
__attribute__((unused)) struct wl_shell_surface *in_shell_surface,
__attribute__((unused)) uint32_t edges,
__attribute__((unused)) int width,
__attribute__((unused)) int height) {}
static void handle_popup_done(__attribute__((unused)) void *data,
__attribute__((unused)) struct wl_shell_surface *in_shell_surface) {}
static const struct wl_shell_surface_listener kShellSurfaceListener = {
handle_ping, handle_configure, handle_popup_done};
static int set_cloexec_or_close(int fd) {
int flags;
if (fd == -1) {
return -1;
}
flags = fcntl(fd, F_GETFD);
if (flags == -1) {
goto err;
}
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
goto err;
}
return fd;
err:
close(fd);
return -1;
}
static int create_tmpfile_cloexec(char *tmpname) {
int fd;
#ifdef HAVE_MKOSTEMP
fd = mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0) {
unlink(tmpname);
}
#else /* HAVE_MKOSTEMP */
fd = mkstemp(tmpname);
if (fd >= 0) {
fd = set_cloexec_or_close(fd);
unlink(tmpname);
}
#endif /* WAYLAND */
return fd;
}
/*
* Create a new, unique, anonymous file of the given size, and
* return the file descriptor for it. The file descriptor is set
* CLOEXEC. The file is immediately suitable for mmap()'ing
* the given size at offset zero.
*
* The file should not have a permanent backing store like a disk,
* but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
*
* The file name is deleted from the file system.
*
* The file is suitable for buffer sharing between processes by
* transmitting the file descriptor over Unix sockets using the
* SCM_RIGHTS methods.
*/
static int os_create_anonymous_file(off_t size) {
static const char kTemplate1[] = "/weston-shared-XXXXXX";
const char *path = getenv("XDG_RUNTIME_DIR");
if (!path) {
errno = ENOENT;
return -1;
}
size_t total_len = strlen(path) + sizeof(kTemplate1);
char *name = reinterpret_cast<char *>(malloc(total_len));
if (!name) {
return -1;
}
snprintf(name, total_len, "%s%s", path, kTemplate1);
int fd = create_tmpfile_cloexec(name);
free(name);
if (fd < 0) {
return -1;
}
if (ftruncate(fd, size) < 0) {
close(fd);
return -1;
}
return fd;
}
static void paint_pixels() {
uint32_t *pixel = reinterpret_cast<uint32_t *>(shm_data);
memcpy(pixel, im_ptr, w * h * 4);
}
static void redraw(__attribute__((unused)) void *data,
__attribute__((unused)) struct wl_callback *callback,
__attribute__((unused)) uint32_t time);
static const struct wl_callback_listener kFrameListener = {redraw};
static void redraw(__attribute__((unused)) void *data,
__attribute__((unused)) struct wl_callback *callback,
__attribute__((unused)) uint32_t time) {
wl_callback_destroy(frame_callback);
wl_surface_damage(surface, 0, 0, w, h);
paint_pixels();
frame_callback = wl_surface_frame(surface);
wl_surface_attach(surface, buffer, 0, 0);
wl_callback_add_listener(frame_callback, &kFrameListener, nullptr);
wl_surface_commit(surface);
}
static struct wl_buffer *create_buffer() {
struct wl_shm_pool *pool;
int stride = w * 4; // 4 bytes per pixel
int size = stride * h;
int fd;
struct wl_buffer *buff;
fd = os_create_anonymous_file(size);
if (fd < 0) {
printf("creating a buffer file for %d B failed\n", size);
exit(1);
}
shm_data = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED) {
printf("mmap failed\n");
close(fd);
exit(1);
}
pool = wl_shm_create_pool(shm, fd, size);
buff = wl_shm_pool_create_buffer(pool, 0, w, h, stride, WL_SHM_FORMAT_XRGB8888);
wl_shm_pool_destroy(pool);
return buff;
}
static void create_window() {
buffer = create_buffer();
wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_damage(surface, 0, 0, WIDTH, HEIGHT);
wl_surface_commit(surface);
}
static void shm_format(__attribute__((unused)) void *data,
__attribute__((unused)) struct wl_shm *wl_shm,
__attribute__((unused)) uint32_t format) {}
struct wl_shm_listener shm_listener = {shm_format};
static void global_registry_handler(__attribute__((unused)) void *data,
struct wl_registry *in_registry, uint32_t id,
const char *interface,
__attribute__((unused)) uint32_t version) {
if (strcmp(interface, "wl_compositor") == 0) {
compositor =
(struct wl_compositor *)wl_registry_bind(in_registry, id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "wl_shell") == 0) {
shell = (struct wl_shell *)wl_registry_bind(in_registry, id, &wl_shell_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
shm = (struct wl_shm *)wl_registry_bind(in_registry, id, &wl_shm_interface, 1);
wl_shm_add_listener(shm, &shm_listener, nullptr);
}
}
static void global_registry_remover(__attribute__((unused)) void *data,
__attribute__((unused)) struct wl_registry *in_registry,
__attribute__((unused)) uint32_t id) {}
static const struct wl_registry_listener registry_listener = {global_registry_handler,
global_registry_remover};
int main(int argc, char **argv) {
w = 640;
h = 480;
im_ptr = (uint32_t *)malloc(w * h * 4);
FILE *f = fopen(argv[1], "rb");
fread(im_ptr, w * h * 4, 1, f);
fclose(f);
display = wl_display_connect(nullptr);
if (nullptr == display) {
printf("Can't connect to display\n");
exit(1);
}
printf("connected to display\n");
registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, ®istry_listener, nullptr);
wl_display_dispatch(display);
wl_display_roundtrip(display);
if (nullptr == compositor) {
printf("Can't find compositor\n");
exit(1);
} else {
printf("Found compositor\n");
}
surface = wl_compositor_create_surface(compositor);
if (nullptr == surface) {
printf("Can't create surface\n");
exit(1);
} else {
printf("Created surface\n");
}
shell_surface = wl_shell_get_shell_surface(shell, surface);
if (nullptr == shell_surface) {
printf("Can't create shell surface\n");
exit(1);
} else {
printf("Created shell surface\n");
}
wl_shell_surface_set_toplevel(shell_surface);
wl_shell_surface_add_listener(shell_surface, &kShellSurfaceListener, nullptr);
frame_callback = wl_surface_frame(surface);
wl_callback_add_listener(frame_callback, &kFrameListener, nullptr);
create_window();
redraw(nullptr, nullptr, 0);
if (wl_display_dispatch(display) == -1) {
return 1;
}
getchar();
wl_display_disconnect(display);
free(registry);
registry = nullptr;
free(im_ptr);
return 0;
}
Can't connect to display
?! - person Programmer   schedule 01.05.2021wl_surface_attach(surface, buffer, 0, 0);
:The x and y arguments specify the location of the new pending buffer's upper left corner, relative to the current buffer's upper left corner, in surface-local coordinates
. Пожалуйста, посмотрите, поможет ли это (я не нашел способа проверить это на своей машине), если да, я сделаю это официальным ответом. - person Programmer   schedule 02.05.2021redraw
. Я просто хочу, чтобы вы изменилиwl_surface_attach(surface, buffer, 0, 0);
наwl_surface_attach(surface, buffer, 100, 100);
и посмотрели, будет ли это иметь какой-либо эффект. Если нет, попробуйте сделать то же самое в своей функцииcreate_window
. - person Programmer   schedule 02.05.2021wl_subsurface_set_position
- person Programmer   schedule 02.05.2021