Update Files
This commit is contained in:
@ -0,0 +1,52 @@
|
||||
#include "wayland.h"
|
||||
|
||||
void kinc_wayland_display_init(void) {
|
||||
// This is a no-op because displays are already registered in kinc_wayland_init,
|
||||
// which should be called before this function is ever invoked
|
||||
}
|
||||
|
||||
int kinc_wayland_display_primary(void) {
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
int kinc_wayland_count_displays(void) {
|
||||
return wl_ctx.num_displays;
|
||||
}
|
||||
|
||||
bool kinc_wayland_display_available(int display_index) {
|
||||
if (display_index >= MAXIMUM_DISPLAYS) {
|
||||
return false;
|
||||
}
|
||||
struct kinc_wl_display *display = &wl_ctx.displays[display_index];
|
||||
return display->output != NULL;
|
||||
}
|
||||
|
||||
const char *kinc_wayland_display_name(int display_index) {
|
||||
if (display_index >= MAXIMUM_DISPLAYS)
|
||||
display_index = 0;
|
||||
struct kinc_wl_display *display = &wl_ctx.displays[display_index];
|
||||
return display->name;
|
||||
}
|
||||
|
||||
kinc_display_mode_t kinc_wayland_display_current_mode(int display_index) {
|
||||
if (display_index >= MAXIMUM_DISPLAYS)
|
||||
display_index = 0;
|
||||
struct kinc_wl_display *display = &wl_ctx.displays[display_index];
|
||||
return display->modes[display->current_mode];
|
||||
}
|
||||
|
||||
int kinc_wayland_display_count_available_modes(int display_index) {
|
||||
if (display_index >= MAXIMUM_DISPLAYS)
|
||||
display_index = 0;
|
||||
struct kinc_wl_display *display = &wl_ctx.displays[display_index];
|
||||
return display->num_modes;
|
||||
}
|
||||
|
||||
kinc_display_mode_t kinc_wayland_display_available_mode(int display_index, int mode_index) {
|
||||
if (display_index >= MAXIMUM_DISPLAYS)
|
||||
display_index = 0;
|
||||
struct kinc_wl_display *display = &wl_ctx.displays[display_index];
|
||||
if (mode_index >= display->num_modes)
|
||||
mode_index = 0;
|
||||
return display->modes[mode_index];
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,54 @@
|
||||
#ifndef KINC_WL_FN
|
||||
#define KINC_WL_FN(ret, name, args)
|
||||
#endif
|
||||
|
||||
KINC_WL_FUN(void, wl_event_queue_destroy, (struct wl_event_queue * queue))
|
||||
#if KINC_WL_CHECK_VERSION(1, 20, 0)
|
||||
KINC_WL_FUN(struct wl_proxy *, wl_proxy_marshal_flags,
|
||||
(struct wl_proxy * proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, uint32_t flags, ...))
|
||||
KINC_WL_FUN(struct wl_proxy *, wl_proxy_marshal_array_flags,
|
||||
(struct wl_proxy * proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, uint32_t flags, union wl_argument *args))
|
||||
#endif
|
||||
KINC_WL_FUN(void, wl_proxy_marshal, (struct wl_proxy * p, uint32_t opcode, ...))
|
||||
KINC_WL_FUN(void, wl_proxy_marshal_array, (struct wl_proxy * p, uint32_t opcode, union wl_argument *args))
|
||||
KINC_WL_FUN(struct wl_proxy *, wl_proxy_create, (struct wl_proxy * factory, const struct wl_interface *interface))
|
||||
KINC_WL_FUN(void *, wl_proxy_create_wrapper, (void *proxy))
|
||||
KINC_WL_FUN(void, wl_proxy_wrapper_destroy, (void *proxy_wrapper))
|
||||
KINC_WL_FUN(struct wl_proxy *, wl_proxy_marshal_constructor, (struct wl_proxy * proxy, uint32_t opcode, const struct wl_interface *interface, ...))
|
||||
KINC_WL_FUN(struct wl_proxy *, wl_proxy_marshal_constructor_versioned,
|
||||
(struct wl_proxy * proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...))
|
||||
KINC_WL_FUN(struct wl_proxy *, wl_proxy_marshal_array_constructor,
|
||||
(struct wl_proxy * proxy, uint32_t opcode, union wl_argument *args, const struct wl_interface *interface))
|
||||
KINC_WL_FUN(struct wl_proxy *, wl_proxy_marshal_array_constructor_versioned,
|
||||
(struct wl_proxy * proxy, uint32_t opcode, union wl_argument *args, const struct wl_interface *interface, uint32_t version))
|
||||
KINC_WL_FUN(void, wl_proxy_destroy, (struct wl_proxy * proxy))
|
||||
KINC_WL_FUN(int, wl_proxy_add_listener, (struct wl_proxy * proxy, void (**implementation)(void), void *data))
|
||||
KINC_WL_FUN(const void *, wl_proxy_get_listener, (struct wl_proxy * proxy))
|
||||
KINC_WL_FUN(int, wl_proxy_add_dispatcher, (struct wl_proxy * proxy, wl_dispatcher_func_t dispatcher_func, const void *dispatcher_data, void *data))
|
||||
KINC_WL_FUN(void, wl_proxy_set_user_data, (struct wl_proxy * proxy, void *user_data))
|
||||
KINC_WL_FUN(void *, wl_proxy_get_user_data, (struct wl_proxy * proxy))
|
||||
KINC_WL_FUN(uint32_t, wl_proxy_get_version, (struct wl_proxy * proxy))
|
||||
KINC_WL_FUN(uint32_t, wl_proxy_get_id, (struct wl_proxy * proxy))
|
||||
KINC_WL_FUN(void, wl_proxy_set_tag, (struct wl_proxy * proxy, const char *const *tag))
|
||||
KINC_WL_FUN(const char *const *, wl_proxy_get_tag, (struct wl_proxy * proxy))
|
||||
KINC_WL_FUN(const char *, wl_proxy_get_class, (struct wl_proxy * proxy))
|
||||
KINC_WL_FUN(void, wl_proxy_set_queue, (struct wl_proxy * proxy, struct wl_event_queue *queue))
|
||||
KINC_WL_FUN(struct wl_display *, wl_display_connect, (const char *name))
|
||||
KINC_WL_FUN(struct wl_display *, wl_display_connect_to_fd, (int fd))
|
||||
KINC_WL_FUN(void, wl_display_disconnect, (struct wl_display * display))
|
||||
KINC_WL_FUN(int, wl_display_get_fd, (struct wl_display * display))
|
||||
KINC_WL_FUN(int, wl_display_dispatch, (struct wl_display * display))
|
||||
KINC_WL_FUN(int, wl_display_dispatch_queue, (struct wl_display * display, struct wl_event_queue *queue))
|
||||
KINC_WL_FUN(int, wl_display_dispatch_queue_pending, (struct wl_display * display, struct wl_event_queue *queue))
|
||||
KINC_WL_FUN(int, wl_display_dispatch_pending, (struct wl_display * display))
|
||||
KINC_WL_FUN(int, wl_display_get_error, (struct wl_display * display))
|
||||
KINC_WL_FUN(uint32_t, wl_display_get_protocol_error, (struct wl_display * display, const struct wl_interface **interface, uint32_t *id))
|
||||
KINC_WL_FUN(int, wl_display_flush, (struct wl_display * display))
|
||||
KINC_WL_FUN(int, wl_display_roundtrip_queue, (struct wl_display * display, struct wl_event_queue *queue))
|
||||
KINC_WL_FUN(int, wl_display_roundtrip, (struct wl_display * display))
|
||||
KINC_WL_FUN(struct wl_event_queue *, wl_display_create_queue, (struct wl_display * display))
|
||||
KINC_WL_FUN(int, wl_display_prepare_read_queue, (struct wl_display * display, struct wl_event_queue *queue))
|
||||
KINC_WL_FUN(int, wl_display_prepare_read, (struct wl_display * display))
|
||||
KINC_WL_FUN(void, wl_display_cancel_read, (struct wl_display * display))
|
||||
KINC_WL_FUN(int, wl_display_read_events, (struct wl_display * display))
|
||||
KINC_WL_FUN(void, wl_log_set_handler_client, (wl_log_func_t handler))
|
@ -0,0 +1,367 @@
|
||||
#pragma once
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE // put this here too, to make clangd happy
|
||||
#endif
|
||||
#include <kinc/display.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
|
||||
#include <wayland-client-core.h>
|
||||
#include <wayland-cursor.h>
|
||||
|
||||
#define KINC_WL_CHECK_VERSION(x, y, z) \
|
||||
(WAYLAND_VERSION_MAJOR > x || (WAYLAND_VERSION_MAJOR == x && WAYLAND_VERSION_MINOR > y) || \
|
||||
(WAYLAND_VERSION_MAJOR == x && WAYLAND_VERSION_MINOR == y && WAYLAND_VERSION_MICRO >= z))
|
||||
|
||||
struct wl_surface;
|
||||
|
||||
struct kinc_wl_procs {
|
||||
#define KINC_WL_FUN(ret, name, args) ret(*_##name) args;
|
||||
#include "wayland-funs.h"
|
||||
#undef KINC_WL_FUN
|
||||
|
||||
struct wl_cursor_theme *(*_wl_cursor_theme_load)(const char *name, int size, struct wl_shm *shm);
|
||||
void (*_wl_cursor_theme_destroy)(struct wl_cursor_theme *theme);
|
||||
struct wl_cursor *(*_wl_cursor_theme_get_cursor)(struct wl_cursor_theme *theme, const char *name);
|
||||
struct wl_buffer *(*_wl_cursor_image_get_buffer)(struct wl_cursor_image *image);
|
||||
int (*_wl_cursor_frame)(struct wl_cursor *cursor, uint32_t time);
|
||||
int (*_wl_cursor_frame_and_duration)(struct wl_cursor *cursor, uint32_t time, uint32_t *duration);
|
||||
|
||||
#ifdef KINC_EGL
|
||||
struct wl_egl_window *(*_wl_egl_window_create)(struct wl_surface *surface, int width, int height);
|
||||
void (*_wl_egl_window_destroy)(struct wl_egl_window *egl_window);
|
||||
void (*_wl_egl_window_resize)(struct wl_egl_window *egl_window, int width, int height, int dx, int dy);
|
||||
void (*_wl_egl_window_get_attached_size)(struct wl_egl_window *egl_window, int *width, int *height);
|
||||
#endif
|
||||
};
|
||||
|
||||
#define wl_event_queue_destroy wl._wl_event_queue_destroy
|
||||
#define wl_proxy_marshal_flags wl._wl_proxy_marshal_flags
|
||||
#define wl_proxy_marshal_array_flags wl._wl_proxy_marshal_array_flags
|
||||
#define wl_proxy_marshal wl._wl_proxy_marshal
|
||||
#define wl_proxy_marshal_array wl._wl_proxy_marshal_array
|
||||
#define wl_proxy_create wl._wl_proxy_create
|
||||
#define wl_proxy_create_wrapper wl._wl_proxy_create_wrapper
|
||||
#define wl_proxy_wrapper_destroy wl._wl_proxy_wrapper_destroy
|
||||
#define wl_proxy_marshal_constructor wl._wl_proxy_marshal_constructor
|
||||
#define wl_proxy_marshal_constructor_versioned wl._wl_proxy_marshal_constructor_versioned
|
||||
#define wl_proxy_marshal_array_constructor wl._wl_proxy_marshal_array_constructor
|
||||
#define wl_proxy_marshal_array_constructor_versioned wl._wl_proxy_marshal_array_constructor_versioned
|
||||
#define wl_proxy_destroy wl._wl_proxy_destroy
|
||||
#define wl_proxy_add_listener wl._wl_proxy_add_listener
|
||||
#define wl_proxy_get_listener wl._wl_proxy_get_listener
|
||||
#define wl_proxy_add_dispatcher wl._wl_proxy_add_dispatcher
|
||||
#define wl_proxy_set_user_data wl._wl_proxy_set_user_data
|
||||
#define wl_proxy_get_user_data wl._wl_proxy_get_user_data
|
||||
#define wl_proxy_get_version wl._wl_proxy_get_version
|
||||
#define wl_proxy_get_id wl._wl_proxy_get_id
|
||||
#define wl_proxy_set_tag wl._wl_proxy_set_tag
|
||||
#define wl_proxy_get_tag wl._wl_proxy_get_tag
|
||||
#define wl_proxy_get_class wl._wl_proxy_get_class
|
||||
#define wl_proxy_set_queue wl._wl_proxy_set_queue
|
||||
#define wl_display_connect wl._wl_display_connect
|
||||
#define wl_display_connect_to_fd wl._wl_display_connect_to_fd
|
||||
#define wl_display_disconnect wl._wl_display_disconnect
|
||||
#define wl_display_get_fd wl._wl_display_get_fd
|
||||
#define wl_display_dispatch wl._wl_display_dispatch
|
||||
#define wl_display_dispatch_queue wl._wl_display_dispatch_queue
|
||||
#define wl_display_dispatch_queue_pending wl._wl_display_dispatch_queue_pending
|
||||
#define wl_display_dispatch_pending wl._wl_display_dispatch_pending
|
||||
#define wl_display_get_error wl._wl_display_get_error
|
||||
#define wl_display_get_protocol_error wl._wl_display_get_protocol_error
|
||||
#define wl_display_flush wl._wl_display_flush
|
||||
#define wl_display_roundtrip_queue wl._wl_display_roundtrip_queue
|
||||
#define wl_display_roundtrip wl._wl_display_roundtrip
|
||||
#define wl_display_create_queue wl._wl_display_create_queue
|
||||
#define wl_display_prepare_read_queue wl._wl_display_prepare_read_queue
|
||||
#define wl_display_prepare_read wl._wl_display_prepare_read
|
||||
#define wl_display_cancel_read wl._wl_display_cancel_read
|
||||
#define wl_display_read_events wl._wl_display_read_events
|
||||
#define wl_log_set_handler_client wl._wl_log_set_handler_client
|
||||
|
||||
#define wl_cursor_theme_load wl._wl_cursor_theme_load
|
||||
#define wl_cursor_theme_destroy wl._wl_cursor_theme_destroy
|
||||
#define wl_cursor_theme_get_cursor wl._wl_cursor_theme_get_cursor
|
||||
#define wl_cursor_image_get_buffer wl._wl_cursor_image_get_buffer
|
||||
#define wl_cursor_frame wl._wl_cursor_frame
|
||||
#define wl_cursor_frame_and_duration wl._wl_cursor_frame_and_duration
|
||||
|
||||
#define wl_egl_window_create wl._wl_egl_window_create
|
||||
#define wl_egl_window_destroy wl._wl_egl_window_destroy
|
||||
#define wl_egl_window_resize wl._wl_egl_window_resize
|
||||
|
||||
extern struct kinc_wl_procs wl;
|
||||
|
||||
#include <wayland-client-protocol.h>
|
||||
#include <wayland-generated/wayland-pointer-constraint.h>
|
||||
#include <wayland-generated/wayland-relative-pointer.h>
|
||||
#include <wayland-generated/wayland-tablet.h>
|
||||
#include <wayland-generated/wayland-viewporter.h>
|
||||
#include <wayland-generated/xdg-decoration.h>
|
||||
#include <wayland-generated/xdg-shell.h>
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
struct kinc_xkb_procs {
|
||||
struct xkb_context *(*xkb_context_new)(enum xkb_context_flags flags);
|
||||
void (*xkb_context_unref)(struct xkb_context *context);
|
||||
struct xkb_keymap *(*xkb_keymap_new_from_string)(struct xkb_context *context, const char *string, enum xkb_keymap_format format,
|
||||
enum xkb_keymap_compile_flags flags);
|
||||
struct xkb_state *(*xkb_state_new)(struct xkb_keymap *keymap);
|
||||
xkb_keysym_t (*xkb_state_key_get_one_sym)(struct xkb_state *state, xkb_keycode_t key);
|
||||
uint32_t (*xkb_state_key_get_utf32)(struct xkb_state *state, xkb_keycode_t key);
|
||||
xkb_mod_mask_t (*xkb_state_serialize_mods)(struct xkb_state *state, enum xkb_state_component components);
|
||||
enum xkb_state_component (*xkb_state_update_mask)(struct xkb_state *state, xkb_mod_mask_t depressed_mods, xkb_mod_mask_t latched_mods,
|
||||
xkb_mod_mask_t locked_mods, xkb_layout_index_t depressed_layout, xkb_layout_index_t latched_layout,
|
||||
xkb_layout_index_t locked_layout);
|
||||
int (*xkb_state_mod_name_is_active)(struct xkb_state *state, const char *name, enum xkb_state_component type);
|
||||
int (*xkb_keymap_key_repeats)(struct xkb_keymap *keymap, xkb_keycode_t key);
|
||||
};
|
||||
|
||||
extern struct kinc_xkb_procs wl_xkb;
|
||||
|
||||
#include <kinc/display.h>
|
||||
#include <kinc/global.h>
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#define MAXIMUM_WINDOWS 16
|
||||
#define MAXIMUM_DISPLAYS 16
|
||||
#define MAXIMUM_DISPLAY_MODES 16
|
||||
|
||||
struct kinc_wl_decoration {
|
||||
struct wl_surface *surface;
|
||||
struct wl_subsurface *subsurface;
|
||||
struct wp_viewport *viewport;
|
||||
};
|
||||
|
||||
enum kinc_wl_decoration_focus {
|
||||
KINC_WL_DECORATION_FOCUS_MAIN,
|
||||
KINC_WL_DECORATION_FOCUS_TOP,
|
||||
KINC_WL_DECORATION_FOCUS_LEFT,
|
||||
KINC_WL_DECORATION_FOCUS_RIGHT,
|
||||
KINC_WL_DECORATION_FOCUS_BOTTOM,
|
||||
KINC_WL_DECORATION_FOCUS_CLOSE_BUTTON,
|
||||
KINC_WL_DECORATION_FOCUS_MAX_BUTTON,
|
||||
KINC_WL_DECORATION_FOCUS_MIN_BUTTON
|
||||
};
|
||||
|
||||
#define KINC_WL_DECORATION_WIDTH 10
|
||||
|
||||
#define KINC_WL_DECORATION_TOP_X 0
|
||||
#define KINC_WL_DECORATION_TOP_Y -(KINC_WL_DECORATION_TOP_HEIGHT)
|
||||
#define KINC_WL_DECORATION_TOP_WIDTH window->width
|
||||
#define KINC_WL_DECORATION_TOP_HEIGHT KINC_WL_DECORATION_WIDTH * 3
|
||||
|
||||
#define KINC_WL_DECORATION_LEFT_X -10
|
||||
#define KINC_WL_DECORATION_LEFT_Y -(KINC_WL_DECORATION_TOP_HEIGHT)
|
||||
#define KINC_WL_DECORATION_LEFT_WIDTH KINC_WL_DECORATION_WIDTH
|
||||
#define KINC_WL_DECORATION_LEFT_HEIGHT window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT
|
||||
|
||||
#define KINC_WL_DECORATION_RIGHT_X window->width
|
||||
#define KINC_WL_DECORATION_RIGHT_Y -(KINC_WL_DECORATION_TOP_HEIGHT)
|
||||
#define KINC_WL_DECORATION_RIGHT_WIDTH 10
|
||||
#define KINC_WL_DECORATION_RIGHT_HEIGHT window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT
|
||||
|
||||
#define KINC_WL_DECORATION_BOTTOM_X 0
|
||||
#define KINC_WL_DECORATION_BOTTOM_Y window->height
|
||||
#define KINC_WL_DECORATION_BOTTOM_WIDTH window->width
|
||||
#define KINC_WL_DECORATION_BOTTOM_HEIGHT KINC_WL_DECORATION_WIDTH
|
||||
|
||||
#define KINC_WL_DECORATION_CLOSE_X window->width - 10
|
||||
#define KINC_WL_DECORATION_CLOSE_Y -20
|
||||
#define KINC_WL_DECORATION_CLOSE_WIDTH 9
|
||||
#define KINC_WL_DECORATION_CLOSE_HEIGHT 9
|
||||
|
||||
struct kinc_wl_window {
|
||||
int display_index;
|
||||
int window_id;
|
||||
int width;
|
||||
int height;
|
||||
kinc_window_mode_t mode;
|
||||
struct wl_surface *surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *toplevel;
|
||||
struct zxdg_toplevel_decoration_v1 *xdg_decoration;
|
||||
|
||||
bool configured;
|
||||
|
||||
struct {
|
||||
bool server_side;
|
||||
enum kinc_wl_decoration_focus focus;
|
||||
struct kinc_wl_decoration top;
|
||||
struct kinc_wl_decoration left;
|
||||
struct kinc_wl_decoration right;
|
||||
struct kinc_wl_decoration bottom;
|
||||
|
||||
struct kinc_wl_decoration close;
|
||||
struct kinc_wl_decoration max;
|
||||
struct kinc_wl_decoration min;
|
||||
|
||||
struct wl_buffer *dec_buffer;
|
||||
struct wl_buffer *close_buffer;
|
||||
struct wl_buffer *max_buffer;
|
||||
struct wl_buffer *min_buffer;
|
||||
} decorations;
|
||||
#ifdef KINC_EGL
|
||||
struct wl_egl_window *egl_window;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct kinc_wl_display {
|
||||
struct wl_output *output;
|
||||
int index;
|
||||
int current_mode;
|
||||
int num_modes;
|
||||
char name[64];
|
||||
int x;
|
||||
int y;
|
||||
int physical_width;
|
||||
int physical_height;
|
||||
int subpixel;
|
||||
enum wl_output_transform transform;
|
||||
enum wl_output_subpixel scale;
|
||||
kinc_display_mode_t modes[MAXIMUM_DISPLAY_MODES];
|
||||
};
|
||||
|
||||
struct kinc_wl_mouse {
|
||||
struct kinc_wl_seat *seat;
|
||||
int current_window;
|
||||
int x;
|
||||
int y;
|
||||
int enter_serial;
|
||||
const char *previous_cursor_name;
|
||||
struct wl_pointer *pointer;
|
||||
struct wl_surface *surface;
|
||||
bool hidden;
|
||||
bool locked;
|
||||
struct zwp_locked_pointer_v1 *lock;
|
||||
struct zwp_relative_pointer_v1 *relative;
|
||||
int serial;
|
||||
};
|
||||
|
||||
struct kinc_wl_keyboard {
|
||||
struct kinc_wl_seat *seat;
|
||||
struct wl_keyboard *keyboard;
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *state;
|
||||
bool ctrlDown;
|
||||
|
||||
int repeat_delay;
|
||||
int repeat_rate;
|
||||
|
||||
int timerfd;
|
||||
|
||||
int last_key_code;
|
||||
int last_character;
|
||||
};
|
||||
|
||||
struct kinc_wl_data_offer {
|
||||
struct wl_data_offer *id;
|
||||
|
||||
int mime_type_count;
|
||||
char **mime_types;
|
||||
|
||||
uint32_t source_actions;
|
||||
uint32_t dnd_action;
|
||||
|
||||
void (*callback)(void *data, size_t data_size, void *user_data);
|
||||
void *user_data;
|
||||
int read_fd;
|
||||
|
||||
void *buffer;
|
||||
size_t buf_size;
|
||||
size_t buf_pos;
|
||||
|
||||
struct kinc_wl_data_offer *next;
|
||||
};
|
||||
|
||||
struct kinc_wl_data_source {
|
||||
struct wl_data_source *source;
|
||||
const char **mime_types;
|
||||
int num_mime_types;
|
||||
void *data;
|
||||
size_t data_size;
|
||||
};
|
||||
|
||||
struct kinc_wl_tablet_tool {
|
||||
struct zwp_tablet_tool_v2 *id;
|
||||
enum zwp_tablet_tool_v2_type type;
|
||||
uint32_t capabilities;
|
||||
uint64_t hardware_serial;
|
||||
uint64_t hardware_id_wacom;
|
||||
|
||||
int current_window;
|
||||
int x;
|
||||
int y;
|
||||
float current_pressure;
|
||||
float current_distance;
|
||||
|
||||
void (*press)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/);
|
||||
void (*move)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/);
|
||||
void (*release)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/);
|
||||
|
||||
struct kinc_wl_tablet_seat *seat;
|
||||
struct kinc_wl_tablet_tool *next;
|
||||
};
|
||||
|
||||
struct kinc_wl_tablet {
|
||||
struct zwp_tablet_v2 *id;
|
||||
struct kinc_wl_tablet_seat *seat;
|
||||
struct kinc_wl_tablet *next;
|
||||
};
|
||||
|
||||
struct kinc_wl_tablet_seat {
|
||||
struct zwp_tablet_seat_v2 *seat;
|
||||
struct kinc_wl_tablet *tablets;
|
||||
struct kinc_wl_tablet_tool *tablet_tools;
|
||||
};
|
||||
|
||||
struct kinc_wl_seat {
|
||||
struct wl_seat *seat;
|
||||
struct kinc_wl_keyboard keyboard;
|
||||
struct kinc_wl_mouse mouse;
|
||||
struct wl_touch *touch;
|
||||
struct kinc_wl_tablet_seat tablet_seat;
|
||||
struct wl_data_device *data_device;
|
||||
struct kinc_wl_data_offer *current_selection_offer;
|
||||
struct kinc_wl_data_offer *current_dnd_offer;
|
||||
int current_serial;
|
||||
uint32_t capabilities;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct wayland_context {
|
||||
struct xkb_context *xkb_context;
|
||||
|
||||
struct wl_display *display;
|
||||
struct wl_shm *shm;
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
struct wp_viewporter *viewporter;
|
||||
struct kinc_wl_seat seat;
|
||||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct zxdg_decoration_manager_v1 *decoration_manager;
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||
struct wl_cursor_theme *cursor_theme;
|
||||
int cursor_size;
|
||||
int num_windows;
|
||||
struct kinc_wl_window windows[MAXIMUM_WINDOWS];
|
||||
int num_displays;
|
||||
struct kinc_wl_display displays[MAXIMUM_DISPLAYS];
|
||||
|
||||
struct kinc_wl_data_offer *data_offer_queue;
|
||||
};
|
||||
|
||||
extern struct wayland_context wl_ctx;
|
||||
|
||||
struct kinc_wl_data_source *kinc_wl_create_data_source(struct kinc_wl_seat *seat, const char *mime_types[], int num_mime_types, void *data, size_t data_size);
|
||||
void kinc_wl_data_source_destroy(struct kinc_wl_data_source *data_source);
|
||||
void kinc_wl_data_offer_accept(struct kinc_wl_data_offer *offer, void (*callback)(void *data, size_t data_size, void *user_data), void *user_data);
|
||||
void kinc_wl_destroy_data_offer(struct kinc_wl_data_offer *offer);
|
||||
void kinc_wayland_set_selection(struct kinc_wl_seat *seat, const char *text, int serial);
|
||||
void kinc_wayland_window_destroy(int window_index);
|
@ -0,0 +1,469 @@
|
||||
#include "wayland.h"
|
||||
|
||||
#include <kinc/image.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
// for all that shared memory stuff later on
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef KINC_EGL
|
||||
#define EGL_NO_PLATFORM_SPECIFIC_TYPES
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
|
||||
static void xdg_surface_handle_configure(void *data, struct xdg_surface *surface, uint32_t serial) {
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
struct kinc_wl_window *window = data;
|
||||
window->configured = true;
|
||||
}
|
||||
|
||||
void kinc_internal_resize(int, int, int);
|
||||
void kinc_wayland_destroy_decoration(struct kinc_wl_decoration *);
|
||||
void kinc_wayland_resize_decoration(struct kinc_wl_decoration *, int x, int y, int width, int height);
|
||||
static void xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *toplevel, int32_t width, int32_t height, struct wl_array *states) {
|
||||
struct kinc_wl_window *window = data;
|
||||
if ((width <= 0 || height <= 0) || (width == window->width + (KINC_WL_DECORATION_WIDTH * 2) &&
|
||||
height == window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT)) {
|
||||
return;
|
||||
}
|
||||
if (window->decorations.server_side) {
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
}
|
||||
else {
|
||||
window->width = width - (KINC_WL_DECORATION_WIDTH * 2);
|
||||
window->height = height - KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT;
|
||||
}
|
||||
|
||||
enum xdg_toplevel_state *state;
|
||||
wl_array_for_each(state, states) {
|
||||
switch (*state) {
|
||||
case XDG_TOPLEVEL_STATE_ACTIVATED:
|
||||
kinc_internal_foreground_callback();
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_RESIZING:
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
kinc_internal_resize(window->window_id, window->width, window->height);
|
||||
kinc_internal_call_resize_callback(window->window_id, window->width, window->height);
|
||||
if (window->decorations.server_side) {
|
||||
xdg_surface_set_window_geometry(window->xdg_surface, 0, 0, window->width, window->height);
|
||||
}
|
||||
else {
|
||||
xdg_surface_set_window_geometry(window->xdg_surface, KINC_WL_DECORATION_LEFT_X, KINC_WL_DECORATION_TOP_Y,
|
||||
window->width + (KINC_WL_DECORATION_WIDTH * 2),
|
||||
window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT);
|
||||
}
|
||||
#ifdef KINC_EGL
|
||||
wl_egl_window_resize(window->egl_window, window->width, window->height, 0, 0);
|
||||
#endif
|
||||
|
||||
kinc_wayland_resize_decoration(&window->decorations.top, KINC_WL_DECORATION_TOP_X, KINC_WL_DECORATION_TOP_Y, KINC_WL_DECORATION_TOP_WIDTH,
|
||||
KINC_WL_DECORATION_TOP_HEIGHT);
|
||||
kinc_wayland_resize_decoration(&window->decorations.left, KINC_WL_DECORATION_LEFT_X, KINC_WL_DECORATION_LEFT_Y, KINC_WL_DECORATION_LEFT_WIDTH,
|
||||
KINC_WL_DECORATION_LEFT_HEIGHT);
|
||||
kinc_wayland_resize_decoration(&window->decorations.right, KINC_WL_DECORATION_RIGHT_X, KINC_WL_DECORATION_RIGHT_Y, KINC_WL_DECORATION_RIGHT_WIDTH,
|
||||
KINC_WL_DECORATION_RIGHT_HEIGHT);
|
||||
kinc_wayland_resize_decoration(&window->decorations.bottom, KINC_WL_DECORATION_BOTTOM_X, KINC_WL_DECORATION_BOTTOM_Y, KINC_WL_DECORATION_BOTTOM_WIDTH,
|
||||
KINC_WL_DECORATION_BOTTOM_HEIGHT);
|
||||
kinc_wayland_resize_decoration(&window->decorations.close, KINC_WL_DECORATION_CLOSE_X, KINC_WL_DECORATION_CLOSE_Y, KINC_WL_DECORATION_CLOSE_WIDTH,
|
||||
KINC_WL_DECORATION_CLOSE_HEIGHT);
|
||||
}
|
||||
|
||||
void kinc_wayland_window_destroy(int window_index);
|
||||
|
||||
static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel) {
|
||||
struct kinc_wl_window *window = data;
|
||||
if (kinc_internal_call_close_callback(window->window_id)) {
|
||||
kinc_window_destroy(window->window_id);
|
||||
if (wl_ctx.num_windows <= 0) {
|
||||
// no windows left, stop
|
||||
kinc_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int create_shm_fd(off_t size) {
|
||||
int fd = -1;
|
||||
#if defined(__linux__)
|
||||
#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 27)
|
||||
#else
|
||||
// memfd_create is available since glibc 2.27 and musl 1.1.20
|
||||
// the syscall is available since linux 3.17
|
||||
// at the time of writing (04/02/2022) these requirements are fullfilled for the "LTS" versions of the following distributions
|
||||
// Ubuntu 18.04
|
||||
// Debian Stretch
|
||||
// Alpine 3.12
|
||||
// Fedora 34
|
||||
|
||||
fd = memfd_create("kinc-wayland-shm", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
if (fd >= 0) {
|
||||
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
|
||||
int ret = posix_fallocate(fd, 0, size);
|
||||
if (ret != 0) {
|
||||
close(fd);
|
||||
errno = ret;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else // fall back to a temp file
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
|
||||
static const char template[] = "/kinc-shared-XXXXXX";
|
||||
|
||||
const char *path = getenv("XDG_RUNTIME_DIR");
|
||||
if (!path) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *name = malloc(strlen(path) + sizeof(template));
|
||||
strcpy(name, path);
|
||||
strcat(name, template);
|
||||
|
||||
fd = mkostemp(name, O_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
unlink(name);
|
||||
|
||||
free(name);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
int ret = ftruncate(fd, size);
|
||||
if (ret != 0) {
|
||||
close(fd);
|
||||
errno = ret;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
struct wl_buffer *kinc_wayland_create_shm_buffer(const kinc_image_t *image) {
|
||||
int stride = image->width * 4;
|
||||
int length = image->width * image->height * 4;
|
||||
|
||||
const int fd = create_shm_fd(length);
|
||||
if (fd < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Wayland: Creating a buffer file for %d B failed: %s", length, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Wayland: mmap failed: %s", strerror(errno));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_shm_pool *pool = wl_shm_create_pool(wl_ctx.shm, fd, length);
|
||||
|
||||
close(fd);
|
||||
memcpy(data, image->data, image->width * image->height * 4);
|
||||
|
||||
struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, image->width, image->height, stride, WL_SHM_FORMAT_ARGB8888);
|
||||
munmap(data, length);
|
||||
wl_shm_pool_destroy(pool);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int grey_data[] = {0xFF333333};
|
||||
|
||||
static int close_data[] = {
|
||||
0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000,
|
||||
0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
// image format is argb32, but kinc does not have that, so let's lie to it
|
||||
|
||||
static kinc_image_t grey_image = {
|
||||
1, 1, 0, KINC_IMAGE_FORMAT_RGBA32, 0, KINC_IMAGE_COMPRESSION_NONE, grey_data, sizeof(grey_data),
|
||||
};
|
||||
static kinc_image_t close_image = {
|
||||
9, 9, 0, KINC_IMAGE_FORMAT_RGBA32, 0, KINC_IMAGE_COMPRESSION_NONE, close_data, sizeof(close_data),
|
||||
};
|
||||
|
||||
void kinc_wayland_create_decoration(struct kinc_wl_decoration *decoration, struct wl_surface *parent, struct wl_buffer *buffer, bool opaque, int x, int y,
|
||||
int width, int height) {
|
||||
decoration->surface = wl_compositor_create_surface(wl_ctx.compositor);
|
||||
decoration->subsurface = wl_subcompositor_get_subsurface(wl_ctx.subcompositor, decoration->surface, parent);
|
||||
wl_subsurface_set_position(decoration->subsurface, x, y);
|
||||
decoration->viewport = wp_viewporter_get_viewport(wl_ctx.viewporter, decoration->surface);
|
||||
wp_viewport_set_destination(decoration->viewport, width, height);
|
||||
if (buffer)
|
||||
wl_surface_attach(decoration->surface, buffer, 0, 0);
|
||||
|
||||
if (opaque) {
|
||||
struct wl_region *region = wl_compositor_create_region(wl_ctx.compositor);
|
||||
wl_region_add(region, 0, 0, width, height);
|
||||
wl_surface_set_opaque_region(decoration->surface, region);
|
||||
wl_surface_commit(decoration->surface);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
else
|
||||
wl_surface_commit(decoration->surface);
|
||||
}
|
||||
|
||||
void kinc_wayland_resize_decoration(struct kinc_wl_decoration *decoration, int x, int y, int width, int height) {
|
||||
if (decoration->surface) {
|
||||
wl_subsurface_set_position(decoration->subsurface, x, y);
|
||||
wp_viewport_set_destination(decoration->viewport, width, height);
|
||||
wl_surface_commit(decoration->surface);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_wayland_destroy_decoration(struct kinc_wl_decoration *decoration) {
|
||||
if (decoration->subsurface)
|
||||
wl_subsurface_destroy(decoration->subsurface);
|
||||
if (decoration->surface)
|
||||
wl_surface_destroy(decoration->surface);
|
||||
if (decoration->viewport)
|
||||
wp_viewport_destroy(decoration->viewport);
|
||||
decoration->surface = NULL;
|
||||
decoration->subsurface = NULL;
|
||||
decoration->viewport = NULL;
|
||||
}
|
||||
|
||||
void kinc_wayland_destroy_decorations(struct kinc_wl_window *window) {
|
||||
kinc_wayland_destroy_decoration(&window->decorations.top);
|
||||
kinc_wayland_destroy_decoration(&window->decorations.left);
|
||||
kinc_wayland_destroy_decoration(&window->decorations.right);
|
||||
kinc_wayland_destroy_decoration(&window->decorations.bottom);
|
||||
kinc_wayland_destroy_decoration(&window->decorations.close);
|
||||
}
|
||||
|
||||
void kinc_wayland_create_decorations(struct kinc_wl_window *window) {
|
||||
if (!window->decorations.dec_buffer) {
|
||||
window->decorations.dec_buffer = kinc_wayland_create_shm_buffer(&grey_image);
|
||||
window->decorations.close_buffer = kinc_wayland_create_shm_buffer(&close_image);
|
||||
window->decorations.max_buffer = kinc_wayland_create_shm_buffer(&grey_image);
|
||||
window->decorations.min_buffer = kinc_wayland_create_shm_buffer(&grey_image);
|
||||
}
|
||||
kinc_wayland_create_decoration(&window->decorations.top, window->surface, window->decorations.dec_buffer, true, KINC_WL_DECORATION_TOP_X,
|
||||
KINC_WL_DECORATION_TOP_Y, KINC_WL_DECORATION_TOP_WIDTH, KINC_WL_DECORATION_TOP_HEIGHT);
|
||||
kinc_wayland_create_decoration(&window->decorations.left, window->surface, window->decorations.dec_buffer, true, KINC_WL_DECORATION_LEFT_X,
|
||||
KINC_WL_DECORATION_LEFT_Y, KINC_WL_DECORATION_LEFT_WIDTH, KINC_WL_DECORATION_LEFT_HEIGHT);
|
||||
kinc_wayland_create_decoration(&window->decorations.right, window->surface, window->decorations.dec_buffer, true, KINC_WL_DECORATION_RIGHT_X,
|
||||
KINC_WL_DECORATION_RIGHT_Y, KINC_WL_DECORATION_RIGHT_WIDTH, KINC_WL_DECORATION_RIGHT_HEIGHT);
|
||||
kinc_wayland_create_decoration(&window->decorations.bottom, window->surface, window->decorations.dec_buffer, true, KINC_WL_DECORATION_BOTTOM_X,
|
||||
KINC_WL_DECORATION_BOTTOM_Y, KINC_WL_DECORATION_BOTTOM_WIDTH, KINC_WL_DECORATION_BOTTOM_HEIGHT);
|
||||
kinc_wayland_create_decoration(&window->decorations.close, window->surface, window->decorations.close_buffer, true, KINC_WL_DECORATION_CLOSE_X,
|
||||
KINC_WL_DECORATION_CLOSE_Y, KINC_WL_DECORATION_CLOSE_WIDTH, KINC_WL_DECORATION_CLOSE_HEIGHT);
|
||||
}
|
||||
|
||||
void xdg_toplevel_decoration_configure(void *data, struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode) {
|
||||
struct kinc_wl_window *window = data;
|
||||
|
||||
if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE) {
|
||||
window->decorations.server_side = false;
|
||||
if (window->decorations.top.surface) {
|
||||
kinc_wayland_destroy_decorations(window);
|
||||
}
|
||||
if (window->mode == KINC_WINDOW_MODE_WINDOW) {
|
||||
kinc_wayland_create_decorations(window);
|
||||
}
|
||||
}
|
||||
else if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) {
|
||||
window->decorations.server_side = true;
|
||||
if (window->decorations.top.surface) {
|
||||
kinc_wayland_destroy_decorations(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wl_surface_handle_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output) {
|
||||
struct kinc_wl_window *window = wl_surface_get_user_data(wl_surface);
|
||||
struct kinc_wl_display *display = wl_output_get_user_data(output);
|
||||
|
||||
if (display && window) {
|
||||
window->display_index = display->index;
|
||||
}
|
||||
}
|
||||
|
||||
void wl_surface_handle_leave(void *data, struct wl_surface *wl_surface, struct wl_output *output) {}
|
||||
|
||||
static const struct wl_surface_listener wl_surface_listener = {
|
||||
wl_surface_handle_enter,
|
||||
wl_surface_handle_leave,
|
||||
};
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
xdg_surface_handle_configure,
|
||||
};
|
||||
|
||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||
xdg_toplevel_handle_configure,
|
||||
xdg_toplevel_handle_close,
|
||||
};
|
||||
|
||||
static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_listener = {
|
||||
xdg_toplevel_decoration_configure,
|
||||
};
|
||||
|
||||
void kinc_wayland_window_set_title(int window_index, const char *title);
|
||||
void kinc_wayland_window_change_mode(int window_index, kinc_window_mode_t mode);
|
||||
|
||||
int kinc_wayland_window_create(kinc_window_options_t *win, kinc_framebuffer_options_t *frame) {
|
||||
int window_index = -1;
|
||||
for (int i = 0; i < MAXIMUM_WINDOWS; i++) {
|
||||
if (wl_ctx.windows[i].surface == NULL) {
|
||||
window_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (window_index == -1) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Too much windows (maximum is %i)", MAXIMUM_WINDOWS);
|
||||
exit(1);
|
||||
}
|
||||
struct kinc_wl_window *window = &wl_ctx.windows[window_index];
|
||||
window->window_id = window_index;
|
||||
window->width = win->width;
|
||||
window->height = win->height;
|
||||
window->mode = KINC_WINDOW_MODE_WINDOW;
|
||||
window->surface = wl_compositor_create_surface(wl_ctx.compositor);
|
||||
wl_surface_set_user_data(window->surface, window);
|
||||
wl_surface_add_listener(window->surface, &wl_surface_listener, NULL);
|
||||
|
||||
window->xdg_surface = xdg_wm_base_get_xdg_surface(wl_ctx.xdg_wm_base, window->surface);
|
||||
xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window);
|
||||
|
||||
window->toplevel = xdg_surface_get_toplevel(window->xdg_surface);
|
||||
xdg_toplevel_add_listener(window->toplevel, &xdg_toplevel_listener, window);
|
||||
|
||||
kinc_wayland_window_set_title(window_index, win->title);
|
||||
|
||||
if (wl_ctx.decoration_manager) {
|
||||
window->xdg_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(wl_ctx.decoration_manager, window->toplevel);
|
||||
#ifdef KINC_WAYLAND_FORCE_CSD
|
||||
zxdg_toplevel_decoration_v1_set_mode(window->xdg_decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
|
||||
#endif
|
||||
zxdg_toplevel_decoration_v1_add_listener(window->xdg_decoration, &xdg_toplevel_decoration_listener, window);
|
||||
}
|
||||
else {
|
||||
window->decorations.server_side = false;
|
||||
kinc_wayland_create_decorations(window);
|
||||
}
|
||||
|
||||
#ifdef KINC_EGL
|
||||
window->egl_window = wl_egl_window_create(window->surface, window->width, window->height);
|
||||
#endif
|
||||
wl_surface_commit(window->surface);
|
||||
kinc_wayland_window_change_mode(window_index, win->mode);
|
||||
wl_ctx.num_windows++;
|
||||
|
||||
while (!window->configured) {
|
||||
wl_display_roundtrip(wl_ctx.display);
|
||||
}
|
||||
|
||||
return window_index;
|
||||
}
|
||||
|
||||
void kinc_wayland_window_destroy(int window_index) {
|
||||
struct kinc_wl_window *window = &wl_ctx.windows[window_index];
|
||||
#ifdef KINC_EGL
|
||||
wl_egl_window_destroy(window->egl_window);
|
||||
#endif
|
||||
if (window->xdg_decoration) {
|
||||
zxdg_toplevel_decoration_v1_destroy(window->xdg_decoration);
|
||||
}
|
||||
|
||||
xdg_toplevel_destroy(window->toplevel);
|
||||
xdg_surface_destroy(window->xdg_surface);
|
||||
wl_surface_destroy(window->surface);
|
||||
*window = (struct kinc_wl_window){0};
|
||||
wl_ctx.num_windows--;
|
||||
}
|
||||
|
||||
void kinc_wayland_window_set_title(int window_index, const char *title) {
|
||||
struct kinc_wl_window *window = &wl_ctx.windows[window_index];
|
||||
xdg_toplevel_set_title(window->toplevel, title == NULL ? "" : title);
|
||||
}
|
||||
|
||||
int kinc_wayland_window_x(int window_index) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Wayland does not support getting the window position.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kinc_wayland_window_y(int window_index) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Wayland does not support getting the window position.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kinc_wayland_window_move(int window_index, int x, int y) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Wayland does not support setting the window position.");
|
||||
}
|
||||
|
||||
int kinc_wayland_window_width(int window_index) {
|
||||
return wl_ctx.windows[window_index].width;
|
||||
}
|
||||
|
||||
int kinc_wayland_window_height(int window_index) {
|
||||
return wl_ctx.windows[window_index].height;
|
||||
}
|
||||
|
||||
void kinc_wayland_window_resize(int window_index, int width, int height) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "TODO: resizing windows");
|
||||
}
|
||||
|
||||
void kinc_wayland_window_show(int window_index) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Wayland does not support unhiding windows.");
|
||||
}
|
||||
|
||||
void kinc_wayland_window_hide(int window_index) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Wayland does not support hiding windows.");
|
||||
}
|
||||
|
||||
kinc_window_mode_t kinc_wayland_window_get_mode(int window_index) {
|
||||
return wl_ctx.windows[window_index].mode;
|
||||
}
|
||||
|
||||
void kinc_wayland_window_change_mode(int window_index, kinc_window_mode_t mode) {
|
||||
struct kinc_wl_window *window = &wl_ctx.windows[window_index];
|
||||
if (mode == window->mode) {
|
||||
return;
|
||||
}
|
||||
switch (mode) {
|
||||
case KINC_WINDOW_MODE_WINDOW:
|
||||
if (window->mode == KINC_WINDOW_MODE_FULLSCREEN || window->mode == KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
|
||||
window->mode = KINC_WINDOW_MODE_WINDOW;
|
||||
xdg_toplevel_unset_fullscreen(window->toplevel);
|
||||
}
|
||||
break;
|
||||
case KINC_WINDOW_MODE_FULLSCREEN:
|
||||
case KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
|
||||
if (window->mode == KINC_WINDOW_MODE_WINDOW) {
|
||||
window->mode = mode;
|
||||
struct kinc_wl_display *display = &wl_ctx.displays[window->display_index];
|
||||
xdg_toplevel_set_fullscreen(window->toplevel, display->output);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_wayland_window_display(int window_index) {
|
||||
struct kinc_wl_window *window = &wl_ctx.windows[window_index];
|
||||
return window->display_index;
|
||||
}
|
||||
|
||||
int kinc_wayland_count_windows() {
|
||||
return wl_ctx.num_windows;
|
||||
}
|
Reference in New Issue
Block a user