Tssss... I am playing with libwayland-client
This commit is contained in:
parent
71cb47a22d
commit
78c33325d4
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,4 +10,5 @@ vgcore.*
|
||||
*.a8
|
||||
*.xcf
|
||||
*_NORMAL.png
|
||||
*_TEMPLATE.png
|
||||
*_TEMPLATE.png
|
||||
/out
|
||||
@ -19,6 +19,9 @@ target_link_libraries(0_render_test -lvulkan -lX11 -lm)
|
||||
add_executable(0_render_test_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c)
|
||||
target_link_libraries(0_render_test_tex_init_prep -lm)
|
||||
|
||||
add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon)
|
||||
|
||||
add_executable(0_play_test src/l3/tests/p0.c)
|
||||
target_link_libraries(0_play_test -lncurses)
|
||||
|
||||
|
||||
46
Makefile
46
Makefile
@ -1,12 +1,44 @@
|
||||
HEADERS := $(shell find src -type f -name '*.h')
|
||||
#HEADERS := $(shell find src -type f -name '*.h')
|
||||
|
||||
all: prototype1
|
||||
cflags := -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type --std=c99 -g -ggdb -O0 \
|
||||
-fno-trapping-math -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE
|
||||
cc := 'gcc'
|
||||
|
||||
prototype1: src/l1/main.c $(HEADERS)
|
||||
@gcc --std c99 -o $@ src/l1/main.c
|
||||
wl_protocols := $(shell pkg-config --variable=pkgdatadir wayland-protocols)
|
||||
|
||||
gen/l_wl_protocols/xdg-shell-client.h: $(wl_protocols)/stable/xdg-shell/xdg-shell.xml
|
||||
mkdir -p gen/l_wl_protocols
|
||||
wayland-scanner client-header $< $@
|
||||
|
||||
gen/l_wl_protocols/xdg-shell-private.c: $(wl_protocols)/stable/xdg-shell/xdg-shell.xml
|
||||
mkdir -p gen/l_wl_protocols
|
||||
wayland-scanner private-code $< $@
|
||||
|
||||
out/l1/t0: src/l1/tests/t0.c $(HEADERS)
|
||||
mkdir -p out/l1
|
||||
$(cc) $(cflags) -o $@ $<
|
||||
|
||||
out/l1/t1: src/l1/tests/t1.c $(HEADERS)
|
||||
mkdir -p out/l1
|
||||
$(cc) $(cflags) -o $@ $<
|
||||
|
||||
out/l2/codegen_l: src/l2/codegen.c $(HEADERS)
|
||||
mkdir -p out/l2
|
||||
$(cc) $(cflags) -o $@ $<
|
||||
|
||||
out/l2/r0: src/l2/tests/r0/r0.c $(HEADERS)
|
||||
mkdir -p out/l2
|
||||
$(cc) $(cflags) -o $@ $< -lvulkan -lX11 -lm
|
||||
|
||||
out/l2/r0: src/l2/tests/r0/r0_tex_init_prep.c $(HEADERS)
|
||||
mkdir -p out/l2
|
||||
$(cc) $(cflags) -o $@ $< -lm
|
||||
|
||||
out/l2/r1: src/l2/tests/r1/r1.c $(HEADERS)
|
||||
mkdir -p out/l2
|
||||
$(cc) $(cflags) -o $@ $< gen/l_wl_protocols/xdg-shell-private.c -lwayland-client -lrt -lxkbcommon
|
||||
|
||||
clean:
|
||||
@rm -f prototype1
|
||||
|
||||
.PHONY: all clean
|
||||
rm -rf gen out
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
@ -13,6 +13,14 @@ mat4 marie_translation_mat4(vec3 vec) {
|
||||
);
|
||||
}
|
||||
|
||||
mat2 marie_2d_rot_mat2(float a) {
|
||||
float cosa = cosf(a);
|
||||
float sina = sinf(a);
|
||||
return mat2_new(
|
||||
cosa, -sina,
|
||||
sina, cosa);
|
||||
}
|
||||
|
||||
mat3 marie_3d_rot_mat3(vec3 r, float a) {
|
||||
float cosa = cosf(a);
|
||||
float sina = sinf(a);
|
||||
|
||||
@ -0,0 +1,550 @@
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <wayland-client.h>
|
||||
#include "../../../../gen/l_wl_protocols/xdg-shell-client.h"
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include "../../../l1/core/util.h"
|
||||
#include "../../marie/graphics_geom.h"
|
||||
#include "../../marie/rasterization.h"
|
||||
|
||||
// todo: remove
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
#define MAX_BUFFER_WIDTH 1000
|
||||
#define MAX_BUFFER_HEIGHT 800
|
||||
#define SWAPCHAIN_SLOTS 2
|
||||
|
||||
_Static_assert(INT32_MAX / MAX_BUFFER_WIDTH / MAX_BUFFER_HEIGHT / 4 / SWAPCHAIN_SLOTS > 1, "Swapchain is too big");
|
||||
|
||||
/* Shared memory support code */
|
||||
static void randname(char *buf) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
long r = ts.tv_nsec;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
buf[i] = 'A'+(r&15)+(r&16)*2;
|
||||
r >>= 5;
|
||||
}
|
||||
}
|
||||
|
||||
static int create_shm_file(void){
|
||||
int retries = 100;
|
||||
do {
|
||||
char name[] = "/wl_shm-XXXXXX";
|
||||
randname(name + sizeof(name) - 7);
|
||||
--retries;
|
||||
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
if (fd >= 0) {
|
||||
shm_unlink(name);
|
||||
return fd;
|
||||
}
|
||||
} while (retries > 0 && errno == EEXIST);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int allocate_shm_file(size_t size) {
|
||||
int fd = create_shm_file();
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
int ret;
|
||||
do {
|
||||
ret = ftruncate(fd, size);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
uint32_t* data;
|
||||
struct wl_shm_pool* pool;
|
||||
bool want_to_draw;
|
||||
struct wl_buffer* used_buffers[SWAPCHAIN_SLOTS];
|
||||
} swapchain_t;
|
||||
|
||||
typedef struct {
|
||||
vec2 pos;
|
||||
vec2 speed;
|
||||
} durackaya_tochka;
|
||||
|
||||
typedef struct {
|
||||
/* Globals */
|
||||
struct wl_display *wl_display;
|
||||
struct wl_registry *wl_registry;
|
||||
struct wl_shm *wl_shm;
|
||||
struct wl_compositor *wl_compositor;
|
||||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct wl_seat *wl_seat;
|
||||
/* Objects */
|
||||
swapchain_t swapchain;
|
||||
struct wl_surface *wl_surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
/* inputs */
|
||||
struct wl_pointer* pointer;
|
||||
struct wl_keyboard* keyboard;
|
||||
/* xkb */
|
||||
struct xkb_state* xkb_state;
|
||||
struct xkb_context* xkb_context;
|
||||
struct xkb_keymap* xkb_keymap;
|
||||
/* app state */
|
||||
vec2 pointer_pos;
|
||||
bool first_0x80_keys[0x80];
|
||||
durackaya_tochka v0;
|
||||
durackaya_tochka v1;
|
||||
durackaya_tochka v2;
|
||||
uint32_t last_frame_time;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
bool closed;
|
||||
} my_state;
|
||||
|
||||
typedef struct {
|
||||
uint32_t* data;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
} WhereToDrawTriangle;
|
||||
|
||||
U32 color_vec4_to_color_u32(vec4 color) {
|
||||
return (((U32)roundf(color.w * 255)) << 24) + (((U32)roundf(color.x * color.w * 255)) << 16) +
|
||||
(((U32)roundf(color.y * color.w * 255)) << 8) + (((U32)roundf(color.z * color.w * 255)) << 0);
|
||||
}
|
||||
|
||||
void draw_frame_h_rasterizer_cb(void* ug, S32 x, S32 y, vec4 attr) {
|
||||
WhereToDrawTriangle* g = ug;
|
||||
if (0 <= x && x < g->width && 0 <= y && y < g->height)
|
||||
g->data[y * g->width + x] = color_vec4_to_color_u32(attr);
|
||||
}
|
||||
|
||||
void draw_frame(my_state* state, uint32_t* data, int32_t width, int32_t height) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
data[y * width + x] = 0xFF00FFFF;
|
||||
}
|
||||
}
|
||||
WhereToDrawTriangle aboba = {data, width, height};
|
||||
marie_rasterize_triangle_with_attr(
|
||||
(MariePlaneVertAttr){.pos = state->v0.pos, .attr = {1, 0, 0, 1}},
|
||||
(MariePlaneVertAttr){.pos = state->v1.pos, .attr = {0, 1, 0, .5f}},
|
||||
(MariePlaneVertAttr){.pos = state->v2.pos, .attr = {0, 0, 1, .0f}},
|
||||
(FnMarieRasterizerCallback){.fn = draw_frame_h_rasterizer_cb, .guest = &aboba});
|
||||
vec2 points[3] = {state->v0.pos, state->v1.pos, state->v2.pos};
|
||||
for (int t = 0; t < 3; t++) {
|
||||
int x = (int)roundf(points[t].x - .5f);
|
||||
int y = (int)roundf(points[t].y - .5f);
|
||||
for (int i = -5; i <= 5; i++)
|
||||
for (int j = -5; j <= 5; j++)
|
||||
if (0 <= x+i && x+i < width && 0 <= y+j && y+j < height)
|
||||
data[(y+j) * width + x + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void durackaya_tochka_update(durackaya_tochka* dot, float dur, float width, float height, bool turning_left, bool turning_right) {
|
||||
vec2 *pos = &dot->pos;
|
||||
vec2 *speed = &dot->speed;
|
||||
float a = 0.9f * dur * ((turning_left ? -1.f : 0) + (turning_right ? 1.f : 0));
|
||||
*speed = mat2_mul_vec2(marie_2d_rot_mat2(a), *speed);
|
||||
*pos = vec2_add_vec2(*pos, vec2_mul_scal(*speed, dur));
|
||||
if (pos->x < 0) {
|
||||
speed->x = -speed->x;
|
||||
pos->x = 0;
|
||||
}
|
||||
if (pos->y < 0) {
|
||||
speed->y = -speed->y;
|
||||
pos->y = 0;
|
||||
}
|
||||
if (pos->x > width) {
|
||||
speed->x = -speed->x;
|
||||
pos->x = width;
|
||||
}
|
||||
if (pos->y > height) {
|
||||
speed->y = -speed->y;
|
||||
pos->y = height;
|
||||
}
|
||||
}
|
||||
|
||||
void update_state(my_state* state, uint32_t fl) {
|
||||
const float width = (float)(state->width < MAX_BUFFER_WIDTH ? state->width : MAX_BUFFER_WIDTH);
|
||||
const float height = (float)(state->height < MAX_BUFFER_HEIGHT ? state->height : MAX_BUFFER_HEIGHT);
|
||||
float dur = (float)fl / 1000;
|
||||
durackaya_tochka_update(&state->v0, dur, width, height, state->first_0x80_keys[XKB_KEY_u], state->first_0x80_keys[XKB_KEY_i]);
|
||||
durackaya_tochka_update(&state->v1, dur, width, height, state->first_0x80_keys[XKB_KEY_j], state->first_0x80_keys[XKB_KEY_k]);
|
||||
durackaya_tochka_update(&state->v2, dur, width, height, state->first_0x80_keys[XKB_KEY_m], state->first_0x80_keys[XKB_KEY_less]);
|
||||
}
|
||||
|
||||
static void main_h_wl_buffer_release(void *data, struct wl_buffer *buffer) {
|
||||
my_state* state = data;
|
||||
for (int ij = 0; ij < SWAPCHAIN_SLOTS; ij++) {
|
||||
if (state->swapchain.used_buffers[ij] == buffer) {
|
||||
// printf("Buffer %p was released and destroyed\n", buffer);
|
||||
wl_buffer_destroy(buffer);
|
||||
state->swapchain.used_buffers[ij] = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
abortf("HUH??!!!\n");
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener main_h_wl_buffer_listener = {
|
||||
.release = main_h_wl_buffer_release,
|
||||
};
|
||||
|
||||
int swapchain_take_slot(my_state *state) {
|
||||
for (int ij = 0; ij < SWAPCHAIN_SLOTS; ij++) {
|
||||
if (!state->swapchain.used_buffers[ij]) {
|
||||
const int32_t width = state->width < MAX_BUFFER_WIDTH ? state->width : MAX_BUFFER_WIDTH;
|
||||
const int32_t height = state->height < MAX_BUFFER_HEIGHT ? state->height : MAX_BUFFER_HEIGHT;
|
||||
struct wl_buffer* s = wl_shm_pool_create_buffer(
|
||||
state->swapchain.pool, ij * 4 * MAX_BUFFER_WIDTH * MAX_BUFFER_HEIGHT,
|
||||
width, height, 4 * width, WL_SHM_FORMAT_ARGB8888);
|
||||
state->swapchain.used_buffers[ij] = s;
|
||||
wl_buffer_add_listener(s, &main_h_wl_buffer_listener, state);
|
||||
|
||||
return ij;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void try_drawing_frame(my_state *state){
|
||||
if (!state->swapchain.want_to_draw)
|
||||
return;
|
||||
int ij = swapchain_take_slot(state);
|
||||
// printf("Got slot %d", ij);
|
||||
if (ij < 0)
|
||||
return;
|
||||
assert(ij < SWAPCHAIN_SLOTS);
|
||||
state->swapchain.want_to_draw = false;
|
||||
const int32_t width = state->width < MAX_BUFFER_WIDTH ? state->width : MAX_BUFFER_WIDTH;
|
||||
const int32_t height = state->height < MAX_BUFFER_HEIGHT ? state->height : MAX_BUFFER_HEIGHT;
|
||||
|
||||
/* Draw checkerboxed background */
|
||||
uint32_t* data = state->swapchain.data + ij * MAX_BUFFER_WIDTH * MAX_BUFFER_HEIGHT;
|
||||
draw_frame(state, data, width, height);
|
||||
wl_surface_attach(state->wl_surface, state->swapchain.used_buffers[ij], 0, 0);
|
||||
wl_surface_damage_buffer(state->wl_surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
wl_surface_commit(state->wl_surface);
|
||||
}
|
||||
|
||||
static void main_h_xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial){
|
||||
my_state *state = data;
|
||||
printf("XDG surface configured!\n");
|
||||
xdg_surface_ack_configure(xdg_surface, serial);
|
||||
// todo: synchronize with frame event
|
||||
state->swapchain.want_to_draw = true;
|
||||
try_drawing_frame(state);
|
||||
}
|
||||
|
||||
static void main_h_xdg_toplevel_configure(
|
||||
void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states
|
||||
){
|
||||
my_state *state = data;
|
||||
printf("XDG toplevel configured to (%d %d)\n", width, height);
|
||||
if (width <= 0 || height < 0)
|
||||
return;
|
||||
state->width = width;
|
||||
state->height = height;
|
||||
}
|
||||
|
||||
static void main_h_xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel){
|
||||
my_state *state = data;
|
||||
state->closed = true;
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_listener main_h_xdg_toplevel_listener = {
|
||||
.configure = main_h_xdg_toplevel_configure,
|
||||
.close = main_h_xdg_toplevel_close,
|
||||
};
|
||||
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
.configure = main_h_xdg_surface_configure,
|
||||
};
|
||||
|
||||
static void main_h_xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial){
|
||||
xdg_wm_base_pong(xdg_wm_base, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_wm_base_listener main_h_xdg_wm_base_listener = {
|
||||
.ping = main_h_xdg_wm_base_ping,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void main_h_wl_keyboard_keymap(
|
||||
void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size
|
||||
) {
|
||||
my_state* state = data;
|
||||
// todo: replace asserts with abortf
|
||||
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
|
||||
char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
assert(map_shm != MAP_FAILED);
|
||||
|
||||
xkb_keymap_unref(state->xkb_keymap);
|
||||
xkb_state_unref(state->xkb_state);
|
||||
state->xkb_keymap = xkb_keymap_new_from_string(
|
||||
state->xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
munmap(map_shm, size);
|
||||
close(fd);
|
||||
state->xkb_state = xkb_state_new(state->xkb_keymap);
|
||||
printf("Keymap changed!\n");
|
||||
memset(&state->first_0x80_keys, 0, sizeof(state->first_0x80_keys));
|
||||
}
|
||||
|
||||
static void main_h_wl_keyboard_enter(
|
||||
void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys
|
||||
) {
|
||||
my_state* state = data;
|
||||
printf("keyboard enter; keys pressed are:\n");
|
||||
uint32_t *key;
|
||||
wl_array_for_each(key, keys) {
|
||||
char buf1[128];
|
||||
char buf2[128];
|
||||
uint32_t actual_key = *key + 8;
|
||||
xkb_keysym_t sym = xkb_state_key_get_one_sym(state->xkb_state, actual_key);
|
||||
// xkb_keysym_get_name(sym, buf1, sizeof(buf1));
|
||||
// xkb_state_key_get_utf8(state->xkb_state, actual_key, buf2, sizeof(buf2));
|
||||
// printf("sym: %-12s (%d), utf8: '%s'\n", buf1, sym, buf2);
|
||||
if (sym < 0x80)
|
||||
state->first_0x80_keys[sym] = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void main_h_wl_keyboard_leave(
|
||||
void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface
|
||||
) {
|
||||
my_state* state = data;
|
||||
memset(&state->first_0x80_keys, 0, sizeof(state->first_0x80_keys));
|
||||
}
|
||||
|
||||
static void main_h_wl_keyboard_key(
|
||||
void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t key_action
|
||||
) {
|
||||
my_state* state = data;
|
||||
char buf1[128];
|
||||
char buf2[128];
|
||||
uint32_t actual_key = key + 8;
|
||||
/* It actually could be nokey keysym. You never know without checking */
|
||||
xkb_keysym_t keysym = xkb_state_key_get_one_sym(state->xkb_state, actual_key);
|
||||
xkb_keysym_get_name(keysym, buf1, sizeof(buf1));
|
||||
xkb_state_key_get_utf8(state->xkb_state, actual_key, buf2, sizeof(buf2));
|
||||
printf("Key %s (%d) %s, utf8: '%s'\n",
|
||||
buf1, keysym, key_action == WL_KEYBOARD_KEY_STATE_PRESSED ? "pressed" : "released", buf2);
|
||||
if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
state->first_0x80_keys[keysym] = false;
|
||||
} else if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
state->first_0x80_keys[keysym] = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void main_h_wl_keyboard_modifiers(
|
||||
void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||
uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group
|
||||
) {
|
||||
my_state* state = data;
|
||||
xkb_state_update_mask(state->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
}
|
||||
|
||||
static void main_h_wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay){
|
||||
printf("Repeat timings changed: rate = %d, delay = %d", rate, delay);
|
||||
}
|
||||
|
||||
static const struct wl_keyboard_listener main_h_wl_keyboard_listener = {
|
||||
.keymap = main_h_wl_keyboard_keymap,
|
||||
.enter = main_h_wl_keyboard_enter,
|
||||
.leave = main_h_wl_keyboard_leave,
|
||||
.key = main_h_wl_keyboard_key,
|
||||
.modifiers = main_h_wl_keyboard_modifiers,
|
||||
.repeat_info = main_h_wl_keyboard_repeat_info,
|
||||
};
|
||||
|
||||
|
||||
static void main_h_wl_pointer_enter(
|
||||
void *data, struct wl_pointer *wl_pointer, uint32_t serial,
|
||||
struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y
|
||||
) {
|
||||
my_state *state = data;
|
||||
state->pointer_pos = (vec2){(float)surface_x / 256.f, (float)surface_y / 256.f};
|
||||
}
|
||||
|
||||
static void main_h_wl_pointer_leave(
|
||||
void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface
|
||||
) {
|
||||
my_state *state = data;
|
||||
}
|
||||
|
||||
static void main_h_wl_pointer_motion(
|
||||
void *data,struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y
|
||||
) {
|
||||
my_state *state = data;
|
||||
state->pointer_pos = (vec2){(float)surface_x / 256.f, (float)surface_y / 256.f};
|
||||
}
|
||||
|
||||
static void main_h_wl_pointer_button(
|
||||
void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t btn_action
|
||||
) {
|
||||
my_state *state = data;
|
||||
if (btn_action == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||
printf("button = %u\n", button);
|
||||
if (button == 0x110) {
|
||||
state->v0.pos = state->pointer_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void main_h_wl_pointer_axis(
|
||||
void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value
|
||||
) {
|
||||
my_state *state = data;
|
||||
}
|
||||
|
||||
static void main_h_wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) {
|
||||
my_state *state = data;
|
||||
}
|
||||
|
||||
const struct wl_pointer_listener main_h_wl_pointer_listener = {
|
||||
.enter = main_h_wl_pointer_enter,
|
||||
.leave = main_h_wl_pointer_leave,
|
||||
.motion = main_h_wl_pointer_motion,
|
||||
.button = main_h_wl_pointer_button,
|
||||
.axis = main_h_wl_pointer_axis,
|
||||
.frame = main_h_wl_pointer_frame
|
||||
};
|
||||
|
||||
static void main_h_wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) {
|
||||
my_state* state = data;
|
||||
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
|
||||
state->pointer = wl_seat_get_pointer(wl_seat);
|
||||
assert(state->pointer);
|
||||
wl_pointer_add_listener(state->pointer, &main_h_wl_pointer_listener, state);
|
||||
}
|
||||
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||
state->keyboard = wl_seat_get_keyboard(wl_seat);
|
||||
assert(state->keyboard);
|
||||
wl_keyboard_add_listener(state->keyboard, &main_h_wl_keyboard_listener, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void main_h_wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {
|
||||
printf("Our seat name: %s\n", name);
|
||||
}
|
||||
|
||||
static const struct wl_seat_listener main_h_wl_seat_listener = {
|
||||
.capabilities = main_h_wl_seat_capabilities,
|
||||
.name = main_h_wl_seat_name,
|
||||
};
|
||||
|
||||
static void main_h_wl_registry_global(
|
||||
void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version
|
||||
) {
|
||||
my_state *state = data;
|
||||
if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||
state->wl_shm = wl_registry_bind(wl_registry, name, &wl_shm_interface, 1);
|
||||
} else if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||
state->wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4);
|
||||
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
|
||||
state->xdg_wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1);
|
||||
xdg_wm_base_add_listener(state->xdg_wm_base, &main_h_xdg_wm_base_listener, state);
|
||||
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
||||
if (state->wl_seat) {
|
||||
printf("We got second seat, but we only need one\n");
|
||||
return;
|
||||
}
|
||||
state->wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 4);
|
||||
wl_seat_add_listener(state->wl_seat, &main_h_wl_seat_listener, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void main_h_wl_registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name){
|
||||
// todo: delete seats
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener main_h_wl_registry_listener = {
|
||||
.global = main_h_wl_registry_global,
|
||||
.global_remove = main_h_wl_registry_global_remove,
|
||||
};
|
||||
|
||||
static const struct wl_callback_listener main_h_wl_surface_frame_listener;
|
||||
|
||||
static void main_h_wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time){
|
||||
my_state *state = data;
|
||||
wl_callback_destroy(cb);
|
||||
cb = wl_surface_frame(state->wl_surface);
|
||||
wl_callback_add_listener(cb, &main_h_wl_surface_frame_listener, state);
|
||||
|
||||
if (state->last_frame_time != 0) {
|
||||
update_state(state, time - state->last_frame_time);
|
||||
}
|
||||
|
||||
state->swapchain.want_to_draw = true;
|
||||
try_drawing_frame(state);
|
||||
|
||||
state->last_frame_time = time;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener main_h_wl_surface_frame_listener = {
|
||||
.done = main_h_wl_surface_frame_done,
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
my_state state = { .width = 800, .height = 480 };
|
||||
state.v0 = (durackaya_tochka){.pos = {10, 10}, .speed = {100, 100}};
|
||||
state.v1 = (durackaya_tochka){.pos = {100, 10}, .speed = {100, -50}};
|
||||
state.v2 = (durackaya_tochka){.pos = {5, 330}, .speed = {-20, 170}};
|
||||
state.wl_display = wl_display_connect(NULL);
|
||||
state.wl_registry = wl_display_get_registry(state.wl_display);
|
||||
wl_registry_add_listener(state.wl_registry, &main_h_wl_registry_listener, &state);
|
||||
wl_display_roundtrip(state.wl_display);
|
||||
assert(state.wl_shm);
|
||||
assert(state.wl_compositor);
|
||||
assert(state.xdg_wm_base);
|
||||
{
|
||||
size_t size = SWAPCHAIN_SLOTS * MAX_BUFFER_WIDTH * MAX_BUFFER_HEIGHT * 4;
|
||||
assert(size < INT32_MAX);
|
||||
state.swapchain.fd = allocate_shm_file(size);
|
||||
if (state.swapchain.fd == -1) {
|
||||
abortf("AAA");
|
||||
}
|
||||
|
||||
state.swapchain.data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, state.swapchain.fd, 0);
|
||||
if (state.swapchain.data == MAP_FAILED) {
|
||||
close(state.swapchain.fd);
|
||||
abortf("what the dog doing");
|
||||
}
|
||||
|
||||
state.swapchain.pool = wl_shm_create_pool(state.wl_shm, state.swapchain.fd, size);
|
||||
assert(state.swapchain.pool);
|
||||
close(state.swapchain.fd);
|
||||
}
|
||||
state.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
printf("I am gonna create surfaces\n");
|
||||
state.wl_surface = wl_compositor_create_surface(state.wl_compositor);
|
||||
state.xdg_surface = xdg_wm_base_get_xdg_surface(
|
||||
state.xdg_wm_base, state.wl_surface);
|
||||
xdg_surface_add_listener(state.xdg_surface, &xdg_surface_listener, &state);
|
||||
state.xdg_toplevel = xdg_surface_get_toplevel(state.xdg_surface);
|
||||
xdg_toplevel_add_listener(state.xdg_toplevel, &main_h_xdg_toplevel_listener, &state);
|
||||
xdg_toplevel_set_title(state.xdg_toplevel, "r1");
|
||||
wl_surface_commit(state.wl_surface);
|
||||
|
||||
struct wl_callback* cb = wl_surface_frame(state.wl_surface);
|
||||
wl_callback_add_listener(cb, &main_h_wl_surface_frame_listener, &state);
|
||||
|
||||
while (wl_display_dispatch(state.wl_display)) {
|
||||
if (state.closed)
|
||||
break;
|
||||
}
|
||||
// todo: clean up this mess
|
||||
munmap(state.swapchain.data, SWAPCHAIN_SLOTS * MAX_BUFFER_WIDTH * MAX_BUFFER_HEIGHT * 2);
|
||||
wl_display_disconnect(state.wl_display);
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user