commit e847a24
uint
·
2026-10-03 17:40:28 +0000 UTC
parent 09ec6ba
remove vendored libmaus
26 files changed,
+0,
-4161
+0,
-16
1@@ -1,16 +0,0 @@
2-*.o
3-*.swp
4-*.a
5-*.exe
6-*.obj
7-*.lib
8-
9-build/
10-compile_flags.txt
11-
12-fenster/
13-
14-examples/basic-window/basic-window
15-
16-config.mk
17-
+0,
-16
1@@ -1,16 +0,0 @@
2-ISC License
3-
4-Copyright 2026 uint
5-
6-Permission to use, copy, modify, and/or distribute this software for any
7-purpose with or without fee is hereby granted, provided that the above
8-copyright notice and this permission notice appear in all copies.
9-
10-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
12-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16-PERFORMANCE OF THIS SOFTWARE.
17-
+0,
-83
1@@ -1,83 +0,0 @@
2-.POSIX:
3-
4-include config.mk
5-
6-CC = cc
7-AR = ar
8-ARFLAGS = -r -c
9-CFLAGS = -ansi -pedantic-errors -Wall -Wextra -O2
10-WL_CFLAGS = -std=c99 -Wall -Wextra -O2
11-CPPFLAGS = ${CONF_CPPFLAGS} -Iinclude -Ibuild
12-LDFLAGS = ${CONF_LDFLAGS}
13-
14-LIB_NAME = build/${CONF_LIB_NAME}
15-LIB_SRCS = source/maus.c \
16- source/maus_font.c \
17- source/utils.c \
18- ${CONF_SRC}
19-LIB_OBJS = build/maus.o \
20- build/maus_font.o \
21- build/utils.o \
22- ${CONF_OBJS}
23-
24-all: ${LIB_NAME}
25-
26-${LIB_NAME}: ${LIB_OBJS}
27- ${AR} ${ARFLAGS} $@ ${LIB_OBJS}
28-
29-build/maus.o: source/maus.c include/maus.h config.mk
30- mkdir -p build
31- ${CC} ${CFLAGS} ${CPPFLAGS} -c source/maus.c -o $@
32-build/maus_font.o: source/maus_font.c include/maus.h include/maus_font.h config.mk
33- mkdir -p build
34- ${CC} ${CFLAGS} ${CPPFLAGS} -c source/maus_font.c -o $@
35-build/utils.o: source/utils.c include/utils.h
36- mkdir -p build
37- ${CC} ${CFLAGS} ${CPPFLAGS} -c source/utils.c -o $@
38-
39-# X11
40-build/maus_x11.o: source/maus_x11.c include/maus.h include/maus_x11.h config.mk
41- mkdir -p build
42- ${CC} ${CFLAGS} ${CPPFLAGS} -c source/maus_x11.c -o $@
43-
44-# Wayland
45-build/maus_wayland.o: source/maus_wayland.c include/maus.h include/maus_wayland.h build/xdg-shell-client-protocol.h build/pointer-constraints-unstable-v1-client-protocol.h build/relative-pointer-unstable-v1-client-protocol.h config.mk
46- mkdir -p build
47- ${CC} ${WL_CFLAGS} ${CPPFLAGS} -c source/maus_wayland.c -o $@
48-build/xdg-shell-client-protocol.h:
49- mkdir -p build
50- wayland-scanner client-header ${PROTOS}/stable/xdg-shell/xdg-shell.xml $@
51-build/xdg-shell-protocol.c:
52- mkdir -p build
53- wayland-scanner private-code ${PROTOS}/stable/xdg-shell/xdg-shell.xml $@
54-build/xdg-shell-protocol.o: build/xdg-shell-protocol.c build/xdg-shell-client-protocol.h
55- mkdir -p build
56- ${CC} ${WL_CFLAGS} ${CPPFLAGS} -c build/xdg-shell-protocol.c -o $@
57-build/pointer-constraints-unstable-v1-client-protocol.h:
58- mkdir -p build
59- wayland-scanner client-header ${PROTOS}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@
60-build/pointer-constraints-unstable-v1-protocol.c:
61- mkdir -p build
62- wayland-scanner private-code ${PROTOS}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml $@
63-build/pointer-constraints-unstable-v1-protocol.o: build/pointer-constraints-unstable-v1-protocol.c build/pointer-constraints-unstable-v1-client-protocol.h
64- mkdir -p build
65- ${CC} ${WL_CFLAGS} ${CPPFLAGS} -c build/pointer-constraints-unstable-v1-protocol.c -o $@
66-build/relative-pointer-unstable-v1-client-protocol.h:
67- mkdir -p build
68- wayland-scanner client-header ${PROTOS}/unstable/relative-pointer/relative-pointer-unstable-v1.xml $@
69-build/relative-pointer-unstable-v1-protocol.c:
70- mkdir -p build
71- wayland-scanner private-code ${PROTOS}/unstable/relative-pointer/relative-pointer-unstable-v1.xml $@
72-build/relative-pointer-unstable-v1-protocol.o: build/relative-pointer-unstable-v1-protocol.c build/relative-pointer-unstable-v1-client-protocol.h
73- mkdir -p build
74- ${CC} ${WL_CFLAGS} ${CPPFLAGS} -c build/relative-pointer-unstable-v1-protocol.c -o $@
75-
76-clean:
77- rm -rf build ${LIB_NAME} config.mk compile_flags.txt
78-
79-compile_flags:
80- rm -f compile_flags.txt
81- for f in ${CFLAGS} ${CPPFLAGS}; do echo $$f >> compile_flags.txt; done
82-
83-.PHONY: all clean compile_flags
84-
+0,
-84
1@@ -1,84 +0,0 @@
2-
3-is a small, cross-platform, software windowing library **now in ANSI C**
4-
5-### Building
6-Unix:
7-```sh
8-./configure [x11|wayland|mac]
9-make # That's it!
10-```
11-
12-Windows:
13-```
14-.\build.bat [msvc|gcc|clang]
15-```
16-> If anyone is on Windows, please try to compile past the ANSI conversion.
17-> I pretty much converted it without checking so there may still be C99
18-> artefacts left behind.
19-
20-After building, you have a library which you link _your_ sources with. It is
21-located in `build/`.
22-
23-### Usage
24-#### libmaus
25-Here is an annoted (C99) example for a basic window program which counts the
26-number of frames that have elapsed, draw the text and displays if you've
27-pressed a key (specifically 'A').
28-
29-For the full list of functions and what they do, look at
30-[the header](include/maus.h).
31-
32-```c
33-#include "maus.h"
34-#include "maus_font.h"
35-
36-int main(void)
37-{
38- int x=50, y=50, width=640, height=480;
39- Maus* ctx = maus_init("example!", x, y, width, height);
40- maus_create_window(ctx);
41- MausFont* font = maus_font_load("assets/fonts/font1.bdf");
42-
43- int running = true;
44- long long frames = 0;
45- int a_pressed = false;
46-
47- while (running) {
48- MausEvent ev;
49- while (maus_event_poll(ctx, &ev)) {
50- // to see the full list of event types, look at
51- // the enum `MausEventType` in `maus.h`
52- if (ev.type == MAUS_EV_CLOSE) {
53- running = false;
54- continue;
55- }
56-
57- if (ev.type == MAUS_EV_KEY && ev.key.pressed) {
58- if (ctx->key_syms[MAUS_KEY_A])
59- a_pressed = 1;
60- }
61- }
62-
63- // clear framebuffer with color white
64- // colors are in format ARGB
65- maus_clear(ctx, (MausColor){255, 255, 255, 255});
66-
67- if (a_pressed) {
68- const char* msg = "how dare you press a!!";
69- maus_draw_text(ctx, font, 10, 50, msg, (MausColor){255, 255, 0, 0});
70- }
71-
72- char frames_text[256];
73- snprintf(frames_text, sizeof(frames_text), "%lld", frames++);
74- maus_draw_text(ctx, font, 10, 20, frames_text, (MausColor){255, 255, 0, 0});
75-
76- maus_target_fps(ctx, 512);
77- maus_present(ctx);
78- }
79-
80- // free resources
81- maus_font_free(font);
82- maus_close(ctx);
83-}
84-```
85-
+0,
-16
1@@ -1,16 +0,0 @@
2-Maus:
3-[ ] Relative cursor
4- [ ] Fill deltas
5-[ ] Rename mw->ctx internally
6-[ ] Move framebuffer creation out
7- of maus_init on platforms
8-[?] Cursor warping
9-[?] Custom cursor
10-
11-MausFont:
12-
13-X11:
14-Wayland:
15-Windows:
16-macOS:
17-
+0,
-0
+0,
-0
+0,
-38
1@@ -1,38 +0,0 @@
2-@echo off
3-
4-if not exist build mkdir build
5-
6-set "COMPILER=%~1"
7-if "%COMPILER%"=="" set "COMPILER=gcc"
8-
9-if /I "%COMPILER%"=="msvc" goto msvc
10-if /I "%COMPILER%"=="gcc" goto gcc
11-if /I "%COMPILER%"=="clang" goto clang
12-
13-echo Usage: build.bat [msvc^|gcc^|clang]
14-exit /b 1
15-
16-:: MSVC
17-:msvc
18-cl /diagnostics:color /nologo /W3 /O2 /Iinclude /DBACKEND_WIN /c ^
19- source/maus.c source/maus_win.c source/maus_font.c source/utils.c
20-lib /nologo /OUT:build\libmaus_win.lib *.obj
21-move /Y *.obj build\
22-goto :eof
23-
24-:: GCC
25-:gcc
26-cc -std=c99 -Wall -Wextra -O2 -Iinclude -DBACKEND_WIN -c ^
27- source/maus.c source/maus_win.c source/maus_font.c source/utils.c
28-move *.o build\
29-ar rcs build\libmaus_win.a build\maus.o build\maus_win.o build\maus_font.o build\utils.o
30-goto :eof
31-
32-:: GCC
33-:clang
34-clang -std=c99 -Wall -Wextra -O2 -Iinclude -DBACKEND_WIN -c ^
35- source/maus.c source/maus_win.c source/maus_font.c source/utils.c
36-move *.o build\
37-ar rcs build\libmaus_win.a build\maus.o build\maus_win.o build\maus_font.o build\utils.o
38-goto :eof
39-
+0,
-50
1@@ -1,50 +0,0 @@
2-#!/bin/sh
3-
4-for arg do
5- case "$arg" in
6- --help)
7- echo "Usage: ./configure [x11|wayland|mac]"
8- exit 0
9- ;;
10- *)
11- if [ -n "$backend" ]; then
12- echo "Usage: ./configure [x11|wayland|mac]"
13- exit 1
14- fi
15- backend="$arg"
16- ;;
17- esac
18-done
19-
20-cat > config.mk << EOF
21-# Generated by configure script
22-BACKEND = $backend
23-EOF
24-
25-case "$backend" in
26- x11)
27- echo "CONF_CPPFLAGS = -DBACKEND_X11" >> config.mk
28- echo "CONF_LDFLAGS = -lX11 -lXext" >> config.mk
29- echo "CONF_SRC = source/maus_x11.c" >> config.mk
30- echo "CONF_OBJS = build/maus_x11.o" >> config.mk
31- echo "CONF_LIB_NAME = libmaus_x11.a" >> config.mk
32- ;;
33- wayland)
34- echo "CONF_CPPFLAGS = -DBACKEND_WAY $(pkg-config --cflags wayland-client wayland-cursor xkbcommon)" >> config.mk
35- echo "CONF_LDFLAGS = $(pkg-config --libs wayland-client wayland-cursor xkbcommon)" >> config.mk
36- echo "CONF_SRC = source/maus_wayland.c build/xdg-shell-protocol.c build/pointer-constraints-unstable-v1-protocol.c build/relative-pointer-unstable-v1-protocol.c" >> config.mk
37- echo "CONF_OBJS = build/maus_wayland.o build/xdg-shell-protocol.o build/pointer-constraints-unstable-v1-protocol.o build/relative-pointer-unstable-v1-protocol.o" >> config.mk
38- echo "CONF_LIB_NAME = libmaus_wayland.a" >> config.mk
39- echo "PROTOS = $(pkg-config --variable=pkgdatadir wayland-protocols)" >> config.mk
40- ;;
41- mac)
42- # TODO
43- ;;
44- *)
45- echo "Unsupported backend '$backend'"
46- rm -f config.mk
47- exit 1
48- ;;
49-esac
50-echo "Configuration done"
51-
+0,
-12
1@@ -1,12 +0,0 @@
2-include ../../config.mk
3-
4-CC = cc
5-CFLAGS = -std=c99 -Wall -Wextra -g
6-CPPFLAGS = ${CONF_CPPFLAGS} -I../../include -I../../build
7-LIBS = ${CONF_LDFLAGS}
8-MAUS_LIB = ../../build/${CONF_LIB_NAME}
9-
10-SRC = main.c
11-
12-all:
13- ${CC} ${CFLAGS} ${CPPFLAGS} ${SRC} ${MAUS_LIB} ${LIBS} -o basic-window
+0,
-27
1@@ -1,27 +0,0 @@
2-@echo off
3-
4-set "COMPILER=%~1"
5-if "%COMPILER%"=="" set "COMPILER=gcc"
6-
7-if /I "%COMPILER%"=="msvc" goto msvc
8-if /I "%COMPILER%"=="gcc" goto gcc
9-if /I "%COMPILER%"=="clang" goto clang
10-
11-echo Usage: build.bat [msvc^|gcc^|clang]
12-exit /b 1
13-
14-:msvc
15-cl /diagnostics:color /nologo /W3 /O2 /I..\..\include main.c ..\..\build\libmaus_win.lib user32.lib gdi32.lib /link /OUT:basic-window.exe
16-echo Build complete
17-goto :eof
18-
19-:gcc
20-cc -std=c99 -Wall -Wextra -g -I../../include main.c ../../build/libmaus_win.a -lgdi32 -luser32 -o basic-window.exe
21-echo Build complete
22-goto :eof
23-
24-:clang
25-clang -std=c99 -Wall -Wextra -g -I../../include main.c ../../build/libmaus_win.a -lgdi32 -luser32 -o basic-window.exe
26-echo Build complete
27-goto :eof
28-
+0,
-155
1@@ -1,155 +0,0 @@
2-#include <stdbool.h>
3-#include <stdint.h>
4-#include <stdlib.h>
5-
6-#include "maus.h"
7-#include "maus_font.h"
8-
9-int mx, my;
10-bool cur_visible = true;
11-bool cur_locked = false;
12-bool cur_relative = false;
13-bool mb1_pressed = false;
14-char txtbuf[4096] = {'\0'};
15-int current_char = 0;
16-bool resize = false;
17-int rszw;
18-int rszh;
19-MausColor white = {255, 255, 255, 255};
20-
21-void handle_ev(Maus* mw, MausEvent* ev)
22-{
23- switch (ev->type) {
24- case MAUS_EV_CLOSE:
25- maus_close(mw);
26- exit(EXIT_SUCCESS);
27- break;
28- case MAUS_EV_KEY: {
29- (void)0;
30-
31- int8_t* keys = mw->key_syms;
32- if (keys[MAUS_KEY_CONTROL_L] && keys[MAUS_KEY_Q]) {
33- maus_close(mw);
34- exit(EXIT_SUCCESS);
35- };
36- if (keys[MAUS_KEY_CONTROL_L] && keys[MAUS_KEY_P]) {
37- cur_visible ?
38- maus_cur_set_mode(mw, MAUS_CURSOR_STATE_HIDDEN) :
39- maus_cur_set_mode(mw, MAUS_CURSOR_STATE_VISIBLE);
40-
41- cur_visible = !cur_visible;
42- }
43- if (keys[MAUS_KEY_CONTROL_L] && keys[MAUS_KEY_L]) {
44- cur_locked ?
45- maus_cur_set_mode(mw, MAUS_CURSOR_STATE_FREE) :
46- maus_cur_set_mode(mw, MAUS_CURSOR_STATE_LOCKED);
47-
48- cur_locked = !cur_locked;
49- }
50- if (keys[MAUS_KEY_CONTROL_L] && keys[MAUS_KEY_R]) {
51- cur_relative ?
52- maus_cur_set_mode(mw, MAUS_CURSOR_STATE_ABSOLUTE) :
53- maus_cur_set_mode(mw, MAUS_CURSOR_STATE_RELATIVE);
54-
55- cur_relative = !cur_relative;
56- }
57-
58- if (ev->key.pressed == false)
59- break;
60-
61- if (!((ev->key.key >= 32 && ev->key.key <= 126) || ev->key.key == '\n'))
62- break;
63-
64- if (current_char + 1 < 4095 && current_char >= 0)
65- txtbuf[current_char++] = ev->key.text;
66- else
67- maus_log(stderr, "txtbuf full");
68-
69- break;
70- }
71- case MAUS_EV_MOUSE_BUTTON: {
72- if (ev->mouse.button.button == MAUS_MOUSE_BUTTON_SCROLL_UP) {
73- white.r += 5;
74- white.g += 5;
75- white.b += 5;
76- }
77- else if (ev->mouse.button.button == MAUS_MOUSE_BUTTON_SCROLL_DOWN) {
78- white.r -= 5;
79- white.g -= 5;
80- white.b -= 5;
81- }
82- mb1_pressed =
83- mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] ?
84- true : false;
85- break;
86- }
87- case MAUS_EV_MOUSE_MOTION: {
88- mx = ev->mouse.motion.x;
89- my = ev->mouse.motion.y;
90-
91- } break;
92- case MAUS_EV_RESIZE: {
93- resize = true;
94- rszw = ev->resize.width;
95- rszh = ev->resize.height;
96- } break;
97- case MAUS_EV_REDRAW:
98- break;
99- case MAUS_EV_NONE:
100- break;
101- }
102-}
103-
104-int main(void)
105-{
106- Maus* mw = maus_init("basic window", 0, 0, 800, 600);
107- if (!mw)
108- return EXIT_FAILURE;
109- maus_create_window(mw);
110- MausFont* font = maus_font_load("assets/fonts/font1.bdf");
111- if (!font)
112- return EXIT_FAILURE;
113-
114- MausEvent ev;
115- MausColor red = { 255, 255, 0, 0 };
116- /* unsigned long long ticks = 0; */
117- for (;;) {
118- while (maus_event_poll(mw, &ev))
119- (void) handle_ev(mw, &ev);
120-
121- /* only resize window once per fram */
122- if (resize) {
123- maus_resize(mw, rszw, rszh);
124- resize = false;
125- }
126-
127- maus_clear(mw, white);
128-
129- uint32_t red_unpacked = MAUS_UNPACK_COL(red);
130- if (mx >= 0 && my >= 0 &&
131- mx < (int32_t)mw->width &&
132- my < (int32_t)mw->height && mb1_pressed) {
133- MAUS_PIXEL_AT(mw, mx, my) = red_unpacked;
134- }
135-
136- for (uint32_t y = 0; y < mw->height/2; y++) {
137- for (uint32_t x = 0; x < mw->width/2; x++) {
138- MAUS_PIXEL_AT(mw, x, y) = red_unpacked;
139- }
140- }
141- red.b++;
142-
143- /* maus_draw_text(mw, font, 700, 50, "maus font\nloading example", red); */
144-
145- /* char buf[512] = {0}; */
146- /* snprintf(buf, 512, "maus' basic-window has been running for %lld ticks!", ticks); */
147- /* maus_clipboard_set_text(mw, buf); */
148-
149- maus_draw_text(mw, font, 700, 50, txtbuf, red);
150-
151- maus_target_fps(mw, 60);
152- maus_present(mw);
153- }
154- maus_font_free(font);
155- maus_close(mw);
156-}
+0,
-181
1@@ -1,181 +0,0 @@
2-#ifndef MAUSWIN_H
3-#define MAUSWIN_H
4-
5-#include <stdio.h>
6-#include <stdint.h>
7-
8-#include "maus_input.h"
9-
10-/* auto selection */
11-#if (!defined(BACKEND_WIN) && !defined(BACKEND_MAC) && \
12- !defined(BACKEND_X11) && !defined(BACKEND_WAY)) || \
13- defined(BACKEND_AUTO)
14-
15-#ifdef BACKEND_AUTO
16-#define MAUS_WARN_BACKEND_AUTO_SEL 0
17-#else
18-#define MAUS_WARN_BACKEND_AUTO_SEL 1
19-#endif /* BACKEND_AUTO */
20-
21- #if defined(_WIN32)
22- #define BACKEND_WIN
23-
24- #elif defined(__APPLE__)
25- #define BACKEND_MAC
26-
27- #else /* default to X */
28- #define BACKEND_X11
29-
30- #endif
31-#else
32-#define MAUS_WARN_BACKEND_AUTO_SEL 0
33-#endif /* auto selection */
34-
35-#if defined(BACKEND_X11)
36- #include "maus_x11.h"
37-
38-#elif defined(BACKEND_WAY)
39- #include "maus_wayland.h"
40-
41-#elif defined(BACKEND_WIN)
42- #include "maus_win.h"
43-
44-#elif defined(BACKEND_MAC)
45- /* ... */
46-#endif
47-
48-#define MAUS_KEYCODE_LAST (256)
49-#define MAUS_COL_ARGB(a, r, g, b) (MausColor){a, r, g, b}
50-#define MAUS_COL_RGBA(r, g, b, a) (MausColor){a, r, g, b}
51-#define MAUS_UNPACK_COL(c) \
52- (((uint32_t)(c).a << 24) | \
53- ((uint32_t)(c).r << 16) | \
54- ((uint32_t)(c).g << 8) | \
55- ((uint32_t)(c).b))
56-
57-#define MAUS_PIXEL_AT(mw, x, y) ((mw)->bfb[(y) * (mw)->stride + (x)])
58-
59-typedef enum {
60- MAUS_EV_NONE,
61- MAUS_EV_CLOSE,
62- MAUS_EV_KEY,
63- MAUS_EV_MOUSE_BUTTON,
64- MAUS_EV_MOUSE_MOTION,
65- MAUS_EV_RESIZE,
66- MAUS_EV_REDRAW /* TODO: MAUS_EV_REDRAW for windows */
67-} MausEventType;
68-
69-typedef struct {
70- uint8_t a;
71- uint8_t r;
72- uint8_t g;
73- uint8_t b;
74-} MausColor;
75-
76-typedef struct {
77- MausEventType type;
78-
79- struct {
80- uint32_t code; /* raw, backend keycode */
81- MausKey key; /* logical, mapped key */
82- char text; /* translated text from key */
83- int8_t pressed;
84- } key;
85-
86- struct {
87- struct {
88- MausMouseButton button;
89- int8_t pressed;
90- } button;
91-
92- struct {
93- int32_t x;
94- int32_t y;
95- int32_t dx;
96- int32_t dy;
97- } motion;
98- } mouse;
99-
100- struct {
101- uint32_t width;
102- uint32_t height;
103- } resize;
104-} MausEvent;
105-
106-typedef struct {
107- MausBackend backend;
108- uint64_t frame_time_last;
109- char* clipboard;
110-
111- uint32_t* fb; /* front frame buffer */
112- uint32_t* bfb; /* back frame buffer */
113- uint32_t stride;
114-
115- const char* title;
116- uint32_t width;
117- uint32_t height;
118- int32_t x;
119- int32_t y;
120-
121- int8_t key_codes[MAUS_KEYCODE_LAST]; /* physical keys */
122- int8_t key_syms[MAUS_KEY_LAST]; /* logical keys */
123-
124- MausCursor cursor;
125- int8_t mouse_buttons[MAUS_MOUSE_BUTTON_LAST];
126-} Maus;
127-
128-/* clear screen with color: `col` */
129-void maus_clear(Maus* mw, MausColor col);
130-
131-/* set text to system clipboard */
132-void maus_clipboard_set_text(Maus* mw, const char* text);
133-
134-/* get text from system clipboard */
135-char* maus_clipboard_get_text(Maus* mw);
136-
137-/* close a Maus. returns 0 on fail
138- TODO also free mw */
139-void maus_close(Maus* mw);
140-
141-/* close a window without the whole Maus. returns 0 on fail */
142-int8_t maus_close_window(Maus* mw);
143-
144-/* create window from Maus. returns 0 on fail */
145-int8_t maus_create_window(Maus* mw);
146-
147-/* log message to output `fd` and die */
148-void maus_die(const char* fmt, ...);
149-
150-/* get time since arbitrary start point (ns) */
151-uint64_t maus_get_time_ns(void);
152-
153-/* initialise and fills the Maus. returns NULL on fail */
154-Maus* maus_init(const char* title, int x, int y, int width, int height);
155-
156-/* log message to output `fd` */
157-void maus_log(FILE* fd, const char* fmt, ...);
158-
159-/* poll for events then fill `ev` with retrieved events.
160- returns 1 if event polled, else 0.
161- note: can burn cpu cycles */
162-int8_t maus_event_poll(Maus* mw, MausEvent* ev);
163-
164-/* poll for events then fill `ev` with retrieved events. returns 1 if event
165- polled, else 0. note, thread goes to sleep until an event arrives */
166-void maus_event_wait(Maus* mw, MausEvent* ev);
167-
168-/* present the pixelbuffer to the screen */
169-void maus_present(Maus* mw);
170-
171-/* resize window to specified width and height. returns 1 on resize success,
172- else 0 */
173-int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height);
174-
175-/* cap framerate to targetted fps */
176-void maus_target_fps(Maus* mw, uint32_t fps);
177-
178-/* change behavior of mouse based on state passed */
179-void maus_cur_set_mode(Maus* mw, MausCursorState state);
180-
181-#endif /* MAUSWIN_H */
182-
+0,
-40
1@@ -1,40 +0,0 @@
2-#ifndef MAUS_FONT_H
3-#define MAUS_FONT_H
4-
5-#include <stdint.h>
6-
7-#include "maus.h"
8-
9-#define MAUS_BDF_GLYPHS_MAX 256
10-
11-typedef struct {
12- uint8_t* bmp;
13- uint16_t w;
14- uint16_t h;
15- int16_t xoff;
16- int16_t yoff;
17- uint16_t adv;
18- int8_t valid;
19-} MausGlyph;
20-
21-typedef struct {
22- MausGlyph glyphs[MAUS_BDF_GLYPHS_MAX];
23-
24- int32_t asc;
25- int32_t dsc;
26- int32_t cellh;
27- int32_t cellw;
28-} MausFont;
29-
30-/* Loops through text passing parameters to glyph drawer */
31-void maus_draw_text(Maus* mw, MausFont* font, int32_t x, int32_t y,
32- const char* text, MausColor col);
33-
34-/* load a bdf font into MausFont. returns NULL on fail */
35-MausFont* maus_font_load(const char* path);
36-
37-/* release all allocations made with a MausFont */
38-void maus_font_free(MausFont* font);
39-
40-#endif /* MAUS_FONT_H */
41-
+0,
-92
1@@ -1,92 +0,0 @@
2-#ifndef MAUS_INPUT_H
3-#define MAUS_INPUT_H
4-
5-#include <stdint.h>
6-
7-typedef enum {
8- MAUS_KEY_NONE = 0,
9-
10- MAUS_KEY_TAB = '\t', MAUS_KEY_ENTER = '\n', MAUS_KEY_SPACE = ' ',
11- MAUS_KEY_APOSTROPHE = '\'', MAUS_KEY_COMMA = ',', MAUS_KEY_MINUS = '-',
12- MAUS_KEY_PERIOD = '.', MAUS_KEY_SLASH = '/', MAUS_KEY_SEMICOLON = ';',
13- MAUS_KEY_EQUAL = '=', MAUS_KEY_LEFT_BRACKET = '[', MAUS_KEY_BACKSLASH = '\\',
14- MAUS_KEY_RIGHT_BRACKET = ']', MAUS_KEY_GRAVE = '`',
15-
16- /* numbers */
17- MAUS_KEY_0 = '0', MAUS_KEY_1, MAUS_KEY_2, MAUS_KEY_3, MAUS_KEY_4,
18- MAUS_KEY_5, MAUS_KEY_6, MAUS_KEY_7, MAUS_KEY_8, MAUS_KEY_9,
19-
20- /* uppercase */
21- MAUS_KEY_A_UP = 'A', MAUS_KEY_B_UP, MAUS_KEY_C_UP, MAUS_KEY_D_UP, MAUS_KEY_E_UP,
22- MAUS_KEY_F_UP, MAUS_KEY_G_UP, MAUS_KEY_H_UP, MAUS_KEY_I_UP, MAUS_KEY_J_UP,
23- MAUS_KEY_K_UP, MAUS_KEY_L_UP, MAUS_KEY_M_UP, MAUS_KEY_N_UP, MAUS_KEY_O_UP,
24- MAUS_KEY_P_UP, MAUS_KEY_Q_UP, MAUS_KEY_R_UP, MAUS_KEY_S_UP, MAUS_KEY_T_UP,
25- MAUS_KEY_U_UP, MAUS_KEY_V_UP, MAUS_KEY_W_UP, MAUS_KEY_X_UP, MAUS_KEY_Y_UP,
26- MAUS_KEY_Z_UP,
27-
28- /* lowercase */
29- MAUS_KEY_A = 'a', MAUS_KEY_B, MAUS_KEY_C, MAUS_KEY_D, MAUS_KEY_E,
30- MAUS_KEY_F, MAUS_KEY_G, MAUS_KEY_H, MAUS_KEY_I, MAUS_KEY_J,
31- MAUS_KEY_K, MAUS_KEY_L, MAUS_KEY_M, MAUS_KEY_N, MAUS_KEY_O,
32- MAUS_KEY_P, MAUS_KEY_Q, MAUS_KEY_R, MAUS_KEY_S, MAUS_KEY_T,
33- MAUS_KEY_U, MAUS_KEY_V, MAUS_KEY_W, MAUS_KEY_X, MAUS_KEY_Y,
34- MAUS_KEY_Z,
35-
36- MAUS_KEY_BACKSPACE = 128, MAUS_KEY_ESCAPE, MAUS_KEY_DELETE,
37-
38- /* navigation */
39- MAUS_KEY_LEFT, MAUS_KEY_RIGHT, MAUS_KEY_UP, MAUS_KEY_DOWN,
40- MAUS_KEY_HOME, MAUS_KEY_END, MAUS_KEY_PAGE_UP, MAUS_KEY_PAGE_DOWN,
41- MAUS_KEY_INSERT,
42-
43- /* modifiers */
44- MAUS_KEY_SHIFT_L, MAUS_KEY_SHIFT_R, MAUS_KEY_CONTROL_L, MAUS_KEY_CONTROL_R,
45- MAUS_KEY_ALT_L, MAUS_KEY_ALT_R, MAUS_KEY_SUPER_L, MAUS_KEY_SUPER_R,
46- MAUS_KEY_CAPS_LOCK, MAUS_KEY_NUM_LOCK, MAUS_KEY_SCROLL_LOCK,
47-
48- /* function */
49- MAUS_KEY_F1, MAUS_KEY_F2, MAUS_KEY_F3, MAUS_KEY_F4,
50- MAUS_KEY_F5, MAUS_KEY_F6, MAUS_KEY_F7, MAUS_KEY_F8,
51- MAUS_KEY_F9, MAUS_KEY_F10, MAUS_KEY_F11, MAUS_KEY_F12,
52-
53- MAUS_KEY_PRINT_SCREEN, MAUS_KEY_PAUSE, MAUS_KEY_MENU,
54-
55- /* keypad */
56- MAUS_KEY_KP_0, MAUS_KEY_KP_1, MAUS_KEY_KP_2, MAUS_KEY_KP_3,
57- MAUS_KEY_KP_4, MAUS_KEY_KP_5, MAUS_KEY_KP_6, MAUS_KEY_KP_7,
58- MAUS_KEY_KP_8, MAUS_KEY_KP_9,
59-
60- MAUS_KEY_KP_DECIMAL, MAUS_KEY_KP_DIVIDE, MAUS_KEY_KP_MULTIPLY,
61- MAUS_KEY_KP_SUBTRACT, MAUS_KEY_KP_ADD, MAUS_KEY_KP_ENTER, MAUS_KEY_KP_EQUAL,
62-
63- MAUS_KEY_LAST
64-} MausKey;
65-
66-typedef struct {
67- int32_t x;
68- int32_t y;
69-} MausCursor;
70-
71-typedef enum {
72- MAUS_CURSOR_STATE_VISIBLE,
73- MAUS_CURSOR_STATE_HIDDEN,
74-
75- MAUS_CURSOR_STATE_FREE,
76- MAUS_CURSOR_STATE_LOCKED,
77-
78- MAUS_CURSOR_STATE_ABSOLUTE,
79- MAUS_CURSOR_STATE_RELATIVE
80-} MausCursorState;
81-
82-typedef enum {
83- MAUS_MOUSE_BUTTON_NONE = 0,
84- MAUS_MOUSE_BUTTON_LEFT,
85- MAUS_MOUSE_BUTTON_MIDDLE,
86- MAUS_MOUSE_BUTTON_RIGHT,
87- MAUS_MOUSE_BUTTON_SCROLL_UP,
88- MAUS_MOUSE_BUTTON_SCROLL_DOWN,
89- MAUS_MOUSE_BUTTON_LAST
90-} MausMouseButton;
91-
92-#endif /* MAUS_KEYS_H */
93-
+0,
-116
1@@ -1,116 +0,0 @@
2-#ifndef MAUS_WAYLAND_H
3-#define MAUS_WAYLAND_H
4-
5-#include <stddef.h>
6-#include <stdint.h>
7-
8-#define MAUS_EVQ_MAX 64
9-
10-/* must forward declare so that other
11- ANSI abiding files arent affected */
12-struct wl_display;
13-struct wl_buffer;
14-struct wl_registry;
15-struct wl_compositor;
16-struct wl_surface;
17-struct wl_shm;
18-struct wl_seat;
19-struct wl_pointer;
20-struct wl_keyboard;
21-struct wl_cursor_theme;
22-struct wl_cursor;
23-
24-struct xdg_wm_base;
25-struct xdg_surface;
26-struct xdg_toplevel;
27-
28-struct zwp_pointer_constraints_v1;
29-struct zwp_confined_pointer_v1;
30-struct zwp_relative_pointer_manager_v1;
31-struct zwp_relative_pointer_v1;
32-
33-struct xkb_context;
34-struct xkb_keymap;
35-struct xkb_state;
36-
37-typedef struct {
38- int8_t pending;
39- int32_t type;
40-
41- uint32_t width;
42- uint32_t height;
43-
44- int32_t mouse_x;
45- int32_t mouse_y;
46- int32_t mouse_dx;
47- int32_t mouse_dy;
48- uint32_t mouse_button;
49- uint8_t mouse_pressed;
50-
51- uint32_t key_code;
52- uint32_t key_sym;
53- char key_text;
54- uint8_t key_pressed;
55-} MausEventPending;
56-
57-typedef struct {
58- struct wl_buffer* buffer;
59- void* data;
60- size_t size;
61- int8_t busy;
62-} MausWLBuffer;
63-
64-typedef struct {
65- struct wl_display* display;
66- struct wl_compositor* compositor;
67- struct wl_surface* surface;
68-
69- struct wl_shm* shm;
70- MausWLBuffer buffers[2];
71-
72- struct wl_seat* seat;
73- struct wl_pointer* pointer;
74- struct wl_keyboard* keyboard;
75-
76- struct wl_cursor_theme* cursor_theme;
77- struct wl_cursor* cursor;
78- struct wl_surface* cursor_surface;
79- uint32_t pointer_enter_serial;
80- int32_t mouse_x;
81- int32_t mouse_y;
82- int8_t mouse_pos_set;
83- int8_t cursor_state;
84-
85- struct zwp_pointer_constraints_v1* pointer_constraints;
86- struct zwp_confined_pointer_v1* locked_pointer;
87- struct zwp_relative_pointer_manager_v1* relative_pointer_manager;
88- struct zwp_relative_pointer_v1* relative_pointer;
89-
90- struct xkb_context* xkb_context;
91- struct xkb_keymap* xkb_keymap;
92- struct xkb_state* xkb_state;
93-
94-
95- MausEventPending pending;
96- MausEventPending evq[MAUS_EVQ_MAX];
97- uint32_t evq_head;
98- uint32_t evq_tail;
99- uint32_t evq_count;
100-
101- int32_t repeat_rate;
102- int32_t repeat_delay;
103- uint32_t repeat_key_code;
104- uint32_t repeat_key_sym;
105- char repeat_key_text;
106- uint64_t repeat_next_ns;
107-
108- struct xdg_wm_base* wm_base;
109- struct xdg_surface* xdg_surface;
110- struct xdg_toplevel* xdg_toplevel;
111- int8_t configured;
112-
113- struct wl_registry* registry;
114-} MausBackend;
115-
116-#endif /* MAUS_WAYLAND_H */
117-
+0,
-20
1@@ -1,20 +0,0 @@
2-#ifndef MAUS_WIN_H
3-#define MAUS_WIN_H
4-
5-#include <stdint.h>
6-
7-#include <windows.h>
8-
9-typedef struct {
10- HWND hwnd;
11- HINSTANCE hInst;
12- HDC hdc;
13- HBITMAP hbm;
14- HDC memdc;
15- int8_t resized;
16- uint32_t rw;
17- uint32_t rh;
18-} MausBackend;
19-
20-#endif /* MAUS_WIN_H */
21-
+0,
-33
1@@ -1,33 +0,0 @@
2-#ifndef MAUS_X11_H
3-#define MAUS_X11_H
4-
5-#include <stdint.h>
6-
7-#include <X11/Xlib.h>
8-#include <X11/extensions/XShm.h>
9-
10-typedef enum {
11- MAUS_ATOM_WM_DELETE_WINDOW,
12- MAUS_ATOM_LAST
13-} MausX11Atoms;
14-
15-typedef struct {
16- Display* display;
17- Window root;
18- Window win;
19- Atom atoms[MAUS_ATOM_LAST];
20- GC gc;
21-
22- int8_t cur_rel; /* relative cursor */
23- int8_t ignore_warp;
24- int32_t mouse_x;
25- int32_t mouse_y;
26- int8_t mouse_pos_set;
27-
28- XShmSegmentInfo shm;
29- int8_t shmat;
30- XImage* image; /* TODO: XImage path */
31-} MausBackend;
32-
33-#endif /* MAUS_X11_H */
34-
+0,
-11
1@@ -1,11 +0,0 @@
2-#ifndef UTIL_H
3-#define UTIL_H
4-
5-/* duplicate a string. returns pointer to address of
6- newly allocated string buffer. if NULL, allocation
7- failed or src is NULL
8- note: you must free this newly allocated string */
9-char* maus_strdup(const char* src);
10-
11-#endif /* UTIL_H */
12-
+0,
-99
1@@ -1,99 +0,0 @@
2-#if !defined(BACKEND_WIN)
3-#define _POSIX_C_SOURCE 199309L
4-#else
5-#include <windows.h>
6-#endif
7-
8-#include <stdarg.h>
9-#include <stdio.h>
10-#include <stdlib.h>
11-#include <time.h>
12-
13-#include "maus.h"
14-
15-static void vlog(FILE* fd, const char* fmt, va_list ap);
16-
17-static void vlog(FILE* fd, const char* fmt, va_list ap)
18-{
19- fprintf(fd, "maus: ");
20- vfprintf(fd, fmt, ap);
21-}
22-
23-void maus_die(const char* fmt, ...)
24-{
25- va_list ap;
26-
27- va_start(ap, fmt);
28- vlog(stderr, fmt, ap);
29- va_end(ap);
30-
31- exit(EXIT_FAILURE);
32-}
33-
34-uint64_t maus_get_time_ns(void)
35-{
36-#if !defined(_WIN32)
37- struct timespec ts;
38- clock_gettime(CLOCK_MONOTONIC, &ts);
39- return ts.tv_sec * 1000000000 + ts.tv_nsec;
40-#else
41- static LARGE_INTEGER frequency = {0};
42- LARGE_INTEGER counter;
43- uint64_t sec;
44- uint64_t rem;
45-
46- if (frequency.QuadPart == 0)
47- QueryPerformanceFrequency(&frequency);
48-
49- QueryPerformanceCounter(&counter);
50-
51- sec = counter.QuadPart / frequency.QuadPart;
52- rem = counter.QuadPart % frequency.QuadPart;
53-
54- return (sec * 1000000000) + ((rem * 1000000000) / frequency.QuadPart);
55-#endif
56-}
57-
58-void maus_log(FILE* fd, const char* fmt, ...)
59-{
60- va_list ap;
61-
62- va_start(ap, fmt);
63- vlog(fd, fmt, ap);
64- fputc('\n', fd);
65- va_end(ap);
66-}
67-
68-void maus_target_fps(Maus* mw, uint32_t fps)
69-{
70- uint64_t ns_frame;
71- uint64_t cur_time;
72- uint64_t elapsed;
73- uint64_t sleep;
74-
75- #if !defined(_WIN32)
76- struct timespec ts;
77- #endif
78-
79- if (fps == 0)
80- return;
81-
82- ns_frame = 1000000000 / fps; /* max ns a frame can take */
83- cur_time = maus_get_time_ns();
84- elapsed = cur_time - mw->frame_time_last;
85-
86- /* if early finish, sleep for the remaining time balance */
87- if (elapsed < ns_frame) {
88- sleep = ns_frame - elapsed;
89- #if !defined(_WIN32)
90- ts.tv_sec = sleep / 1000000000;
91- ts.tv_nsec = sleep % 1000000000;
92- nanosleep(&ts, NULL);
93- #else
94- Sleep((DWORD)((sleep + 999999) / 1000000));
95- #endif
96- }
97-
98- mw->frame_time_last = maus_get_time_ns();
99-}
100-
+0,
-296
1@@ -1,296 +0,0 @@
2-#include <stdio.h>
3-#include <stdlib.h>
4-#include <string.h>
5-
6-#include "maus.h"
7-#include "maus_font.h"
8-
9-static void glyph_to_buf(int32_t sgx, int32_t egx, int32_t sgy, int32_t egy,
10- int32_t gox, int32_t goy, MausGlyph* g, uint32_t col_up,
11- uint32_t* buf, uint32_t stride);
12-
13-/* "blit" a glpyh to some buffer */
14-static void glyph_to_buf(int32_t sgx, int32_t egx, int32_t sgy, int32_t egy,
15- int32_t gox, int32_t goy, MausGlyph* g, uint32_t col_up,
16- uint32_t* buf, uint32_t stride)
17-{
18- int gy;
19- int gx;
20- int32_t dstx;
21-
22- uint32_t* row;
23- int32_t offset;
24-
25- for (gy = sgy; gy < egy; gy++) {
26- int dsty = goy + gy;
27-
28- /* calculate row pointer once per scanline */
29- row = buf + (dsty * stride);
30- offset = gy * g->w;
31-
32- for (gx = sgx; gx < egx; gx++) {
33- if (g->bmp[offset + gx] > 0) {
34- dstx = gox + gx;
35- row[dstx] = col_up;
36- }
37- }
38- }
39-}
40-
41-static int8_t parse_glyphs(FILE* f, MausFont* font, char* line, size_t line_size,
42- int32_t* encoding, int32_t* advance, int32_t* bw, int32_t* bh,
43- int32_t* xoff, int32_t* yoff, int8_t* seen)
44-{
45- int32_t rowbits;
46-
47- int32_t x;
48- int32_t y;
49- uint64_t bits;
50-
51- MausGlyph* g;
52-
53- while (fgets(line, line_size, f)) {
54- if (sscanf(line, "ENCODING %d", encoding) == 1)
55- continue;
56- if (sscanf(line, "DWIDTH %d", advance) == 1)
57- continue;
58- if (sscanf(line, "BBX %d %d %d %d", bw, bh, xoff, yoff) == 4)
59- continue;
60-
61- if (strncmp(line, "BITMAP", 6) == 0) {
62- /* invalid character code
63- TODO: just skip it */
64- if (*encoding < 0 || *encoding >= MAUS_BDF_GLYPHS_MAX)
65- break;
66-
67- /* empty/invalid size */
68- if (*bw <= 0 || *bh <= 0)
69- break;
70-
71- g = &font->glyphs[*encoding];
72- free(g->bmp); /* prevent leak on hot reload */
73- memset(g, 0, sizeof(*g));
74-
75- g->w = *bw;
76- g->h = *bh;
77- g->xoff = *xoff;
78- g->yoff = *yoff;
79- g->adv = *advance;
80-
81- g->bmp = calloc((size_t)(*bw) * (*bh), 1);
82- if (!g->bmp) {
83- fclose(f);
84- maus_font_free(font);
85- return 0;
86- }
87-
88- /* each bmp row in BDF is padded as a multiple
89- of 8 bits. this rounds width up to the next
90- multiple of 8 */
91- rowbits = (*bw + 7) & ~7;
92-
93- for (y = 0; y < *bh; y++) {
94- /* missing row */
95- if (!fgets(line, line_size, f)) {
96- fclose(f);
97- maus_font_free(font);
98- return 0;
99- }
100-
101- bits = strtoull(line, NULL, 16); /* hex to bits */
102- for (x = 0; x < *bw; x++) {
103- int bit = rowbits - 1 - x;
104-
105- if ((bits >> bit) & 1)
106- g->bmp[y * (*bw) + x] = 255; /* solid */
107- }
108- }
109-
110- g->valid = 1;
111- if (*advance > font->cellw)
112- font->cellw = *advance;
113- *seen = 1;
114-
115- continue;
116- }
117-
118- if (strncmp(line, "ENDCHAR", 7) == 0)
119- break;
120- }
121-
122- return 1;
123-}
124-
125-void maus_draw_text(Maus* mw, MausFont* font, int32_t x, int32_t y,
126- const char* text, MausColor col)
127-{
128- uint32_t col_up = MAUS_UNPACK_COL(col);
129-
130- size_t i;
131-
132- /* current coordinates */
133- int32_t cx = x;
134- int32_t cy = y;
135-
136- /* origins to start drawing glyph from */
137- int32_t gox;
138- int32_t goy;
139-
140- /* starting glyph coordinates */
141- int32_t sgx;
142- int32_t sgy;
143-
144- /* ending glyph coordinates */
145- int32_t egx;
146- int32_t egy;
147-
148- /* current glyph pointer */
149- MausGlyph* g;
150-
151- if (!mw || !mw->bfb || !font || !text)
152- return;
153-
154- for (i = 0; text[i] != '\0'; i++) {
155- char c = text[i];
156-
157- if (c == '\n') {
158- cx = x;
159- cy += font->cellh;
160- continue;
161- }
162-
163- g = &font->glyphs[(uint8_t)c];
164- if (!g->valid) {
165- /* still advance cx if character invalid */
166- cx += (font->cellw > 0 ? font->cellw : 8);
167- continue;
168- }
169-
170- /* origins to start drawing glyph from */
171- gox = cx + g->xoff;
172- goy = cy + font->asc - g->h - g->yoff;
173-
174- /* starting coordinates */
175- sgx = (-gox > 0) ? -gox : 0;
176- sgy = (-goy > 0) ? -goy : 0;
177-
178- egx = (mw->width - gox < g->w) ? (mw->width - gox) : g->w;
179- egy = (mw->height - goy < g->h) ?(mw->height - goy) : g->h;
180-
181- /* cull glyphs which start off screen */
182- if (sgx >= egx || sgy >= egy) {
183- cx += g->adv;
184- continue;
185- }
186-
187- glyph_to_buf(sgx, egx, sgy, egy, gox, goy, g, col_up, mw->bfb, mw->stride);
188- cx += g->adv;
189- }
190-}
191-
192-MausFont* maus_font_load(const char* path)
193-{
194- FILE* f = fopen(path, "r");
195- MausFont* font = calloc(1, sizeof(MausFont));
196- char line[1024];
197-
198- int32_t asc = -1;
199- int32_t dsc = -1;
200- int32_t encoding = -1;
201- int32_t advance = 0;
202- int32_t bw = 0; /* bmp width */
203- int32_t bh = 0; /* bmp height */
204- int32_t xoff = 0;
205- int32_t yoff = 0;
206- int8_t seen = 0;
207-
208- int i;
209-
210- if (!f) {
211- maus_log(stderr, "failed to load font \"%s\"", path);
212- return NULL;
213- }
214-
215- if (!font) {
216- maus_log(stderr, "failed to calloc font");
217- fclose(f);
218- return NULL;
219- }
220-
221- while (fgets(line, sizeof(line), f)) {
222- if (sscanf(line, "FONT_ASCENT %d", &asc) == 1)
223- continue;
224- if (sscanf(line, "FONT_DESCENT %d", &dsc) == 1)
225- continue;
226-
227- /* ignore everything until glyphs start */
228- if (strncmp(line, "STARTCHAR", 9) != 0)
229- continue;
230-
231- /* reset vaules for new glyph */
232- encoding = -1;
233- advance = 0;
234- bw = 0;
235- bh = 0;
236- xoff = 0;
237- yoff = 0;
238-
239- if (!parse_glyphs(f, font, line, sizeof(line), &encoding, &advance, &bw, &bh, &xoff, &yoff, &seen))
240- return NULL;
241- }
242-
243-
244- fclose(f);
245-
246- if (!seen) {
247- free(font);
248- return NULL;
249- }
250-
251- /* estimate asc/dsc if they werent provided */
252- if (asc < 0 || dsc < 0) {
253- asc = 0;
254- dsc = 0;
255-
256- for (i = 0; i < MAUS_BDF_GLYPHS_MAX; i++) {
257- MausGlyph* g = &font->glyphs[i];
258-
259- /* unloaded glpyh */
260- if (!g->valid)
261- continue;
262-
263- /* highest point above baseline */
264- if (g->h + g->yoff > asc)
265- asc = g->h + g->yoff;
266-
267- /* lowest point below baseline */
268- if (-g->yoff > dsc)
269- dsc = -g->yoff;
270- }
271- }
272-
273- font->asc = asc;
274- font->dsc = -dsc;
275- font->cellh = asc + dsc;
276-
277- if (font->cellw <= 0 || font->cellh <= 0) {
278- maus_font_free(font);
279- return NULL;
280- }
281-
282- return font;
283-}
284-
285-void maus_font_free(MausFont* font)
286-{
287- int i;
288-
289- if (!font)
290- return;
291-
292- for (i = 0; i < MAUS_BDF_GLYPHS_MAX; i++)
293- free(font->glyphs[i].bmp);
294-
295- free(font);
296-}
297-
+0,
-1351
1@@ -1,1351 +0,0 @@
2-#define _POSIX_C_SOURCE 200809L
3-
4-#include <fcntl.h>
5-#include <poll.h>
6-#include <stdlib.h>
7-#include <string.h>
8-#include <sys/mman.h>
9-#include <unistd.h>
10-
11-#include <wayland-client.h>
12-#include <wayland-cursor.h>
13-#include <xdg-shell-client-protocol.h>
14-#include <pointer-constraints-unstable-v1-client-protocol.h>
15-#include <relative-pointer-unstable-v1-client-protocol.h>
16-#include <xkbcommon/xkbcommon.h>
17-
18-#include "maus.h"
19-#include "maus_wayland.h"
20-
21-static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name);
22-static void xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial);
23-static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, int32_t width, int32_t height, struct wl_array* states);
24-static void xdg_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel);
25-static void xdg_toplevel_configure_bounds(void* data, struct xdg_toplevel* xdg_toplevel, int32_t width, int32_t height);
26-static void xdg_toplevel_wm_capabilities(void* data, struct xdg_toplevel* xdg_toplevel, struct wl_array* capabilities);
27-static void wm_base_ping(void* data, struct xdg_wm_base* wm_base, uint32_t serial);
28-static void seat_capabilities(void* data, struct wl_seat* seat, uint32_t capabilities);
29-static void seat_name(void* data, struct wl_seat* seat, const char* name);
30-static void pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t sx, wl_fixed_t sy);
31-static void pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface);
32-static void pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy);
33-static void pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
34-static void pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value);
35-static void pointer_frame(void* data, struct wl_pointer* pointer);
36-static void pointer_axis_source(void* data, struct wl_pointer* pointer, uint32_t axis_source);
37-static void pointer_axis_stop(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis);
38-static void pointer_axis_discrete(void* data, struct wl_pointer* pointer, uint32_t axis, int32_t discrete);
39-static void pointer_axis_value120(void* data, struct wl_pointer* pointer, uint32_t axis, int32_t value120);
40-static void pointer_axis_relative_direction(void* data, struct wl_pointer* pointer, uint32_t axis, uint32_t direction);
41-static void relative_pointer_motion(void* data, struct zwp_relative_pointer_v1* relative_pointer, uint32_t utime_hi, uint32_t utime_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel);
42-static void keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int32_t fd, uint32_t size);
43-static void keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys);
44-static void keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface);
45-static void keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state);
46-static void keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group);
47-static void keyboard_repeat_info(void* data, struct wl_keyboard* keyboard, int32_t rate, int32_t delay);
48-static void registry_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
49-
50-static int8_t cursor_init(Maus* mw);
51-static void cursor_destroy(Maus* mw);
52-static void cursor_lock(Maus* mw);
53-static void cursor_unlock(Maus* mw);
54-static void cursor_show(Maus* mw);
55-static void cursor_hide(Maus* mw);
56-static void cursor_relative(Maus* mw);
57-static void cursor_absolute(Maus* mw);
58-static void event_push_pending(Maus* mw);
59-static int8_t event_pop(Maus* mw, MausEventPending* ev);
60-static void event_push_key(Maus* mw, uint32_t code, uint32_t sym, char text, uint8_t pressed);
61-static int8_t repeat_push_due(Maus* mw);
62-static int32_t repeat_timeout_ms(Maus* mw);
63-static int8_t display_read(Maus* mw, int timeout_ms);
64-static MausKey keysym_to_mauskey(xkb_keysym_t sym);
65-static MausMouseButton wl_button_to_maus(uint32_t button);
66-static void wl_buffer_release(void* data, struct wl_buffer* buffer);
67-
68-static struct wl_registry_listener registry_listener = { registry_global, registry_global_remove };
69-static struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure };
70-static struct xdg_toplevel_listener xdg_toplevel_listener = {
71- xdg_toplevel_configure, xdg_toplevel_close,
72- xdg_toplevel_configure_bounds, xdg_toplevel_wm_capabilities
73-};
74-static struct xdg_wm_base_listener xdg_wm_base_listener = { wm_base_ping };
75-static struct wl_seat_listener seat_listener = { seat_capabilities, seat_name };
76-static struct wl_pointer_listener pointer_listener = {
77- pointer_enter, pointer_leave, pointer_motion, pointer_button,
78- pointer_axis, pointer_frame, pointer_axis_source, pointer_axis_stop,
79- pointer_axis_discrete, pointer_axis_value120, pointer_axis_relative_direction
80-};
81-static struct wl_keyboard_listener keyboard_listener = {
82- keyboard_keymap, keyboard_enter, keyboard_leave, keyboard_key,
83- keyboard_modifiers, keyboard_repeat_info
84-};
85-static struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
86- relative_pointer_motion
87-};
88-static struct wl_buffer_listener wl_buffer_listener = { wl_buffer_release };
89-
90-static void wl_buffer_release(void* data, struct wl_buffer* buffer)
91-{
92- MausWLBuffer* wb = data;
93-
94- (void)buffer;
95-
96- wb->busy = 0;
97-}
98-
99-static void event_push_pending(Maus* mw)
100-{
101- MausBackend* be = &mw->backend;
102-
103- if (!be->pending.pending)
104- return;
105-
106- if (be->evq_count == MAUS_EVQ_MAX) {
107- be->evq_head = (be->evq_head + 1) % MAUS_EVQ_MAX;
108- be->evq_count--;
109- }
110-
111- be->evq[be->evq_tail] = be->pending;
112- be->evq_tail = (be->evq_tail + 1) % MAUS_EVQ_MAX;
113- be->evq_count++;
114- be->pending.pending = 0;
115-}
116-
117-static int8_t event_pop(Maus* mw, MausEventPending* ev)
118-{
119- MausBackend* be = &mw->backend;
120-
121- if (be->evq_count == 0)
122- return 0;
123-
124- *ev = be->evq[be->evq_head];
125- be->evq_head = (be->evq_head + 1) % MAUS_EVQ_MAX;
126- be->evq_count--;
127- return 1;
128-}
129-
130-static void event_push_key(Maus* mw, uint32_t code, uint32_t sym, char text, uint8_t pressed)
131-{
132- MausBackend* be = &mw->backend;
133-
134- be->pending.pending = 1;
135- be->pending.type = MAUS_EV_KEY;
136- be->pending.key_code = code;
137- be->pending.key_sym = sym;
138- be->pending.key_text = text;
139- be->pending.key_pressed = pressed;
140- event_push_pending(mw);
141-}
142-
143-static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name)
144-{
145- (void)data;
146- (void)wl_registry;
147- (void)name;
148-}
149-
150-static void xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial)
151-{
152- Maus* mw = data;
153- xdg_surface_ack_configure(xdg_surface, serial);
154- mw->backend.configured = 1;
155- if (!mw->backend.pending.pending) {
156- mw->backend.pending.pending = 1;
157- mw->backend.pending.type = MAUS_EV_REDRAW;
158- }
159- event_push_pending(mw);
160-}
161-
162-static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel,
163- int32_t width, int32_t height, struct wl_array* states)
164-{
165- Maus* mw = data;
166-
167- (void)xdg_toplevel;
168- (void)states;
169-
170- if (width <= 0 || height <= 0)
171- return;
172-
173- mw->backend.pending.pending = 1;
174- mw->backend.pending.type = MAUS_EV_RESIZE;
175- mw->backend.pending.width = width;
176- mw->backend.pending.height = height;
177- event_push_pending(mw);
178-}
179-
180-static void xdg_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel)
181-{
182- Maus* mw = data;
183-
184- (void)xdg_toplevel;
185-
186- mw->backend.pending.pending = 1;
187- mw->backend.pending.type = MAUS_EV_CLOSE;
188- event_push_pending(mw);
189-}
190-
191-static void xdg_toplevel_configure_bounds(void* data, struct xdg_toplevel* xdg_toplevel,
192- int32_t width, int32_t height)
193-{
194- (void)data;
195- (void)xdg_toplevel;
196- (void)width;
197- (void)height;
198-}
199-
200-static void xdg_toplevel_wm_capabilities(void* data, struct xdg_toplevel* xdg_toplevel,
201- struct wl_array* capabilities)
202-{
203- (void)data;
204- (void)xdg_toplevel;
205- (void)capabilities;
206-}
207-
208-static void wm_base_ping(void* data, struct xdg_wm_base* wm_base, uint32_t serial)
209-{
210- (void)data;
211- xdg_wm_base_pong(wm_base, serial);
212-}
213-
214-static void registry_global(void* data, struct wl_registry* registry,
215- uint32_t name, const char* interface,
216- uint32_t version)
217-{
218- Maus* mw = data;
219- MausBackend* be = &mw->backend;
220-
221- (void) version;
222-
223- if (strcmp(interface, wl_compositor_interface.name) == 0)
224- be->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4);
225- else if (strcmp(interface, wl_shm_interface.name) == 0)
226- be->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
227- else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
228- be->wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
229- xdg_wm_base_add_listener(be->wm_base, &xdg_wm_base_listener, mw);
230- }
231- else if (strcmp(interface, wl_seat_interface.name) == 0) {
232- be->seat = wl_registry_bind(registry, name, &wl_seat_interface, 5);
233- wl_seat_add_listener(be->seat, &seat_listener, mw);
234- }
235- else if (strcmp(interface, zwp_pointer_constraints_v1_interface.name) == 0)
236- be->pointer_constraints = wl_registry_bind(registry, name, &zwp_pointer_constraints_v1_interface, 1);
237- else if (strcmp(interface, zwp_relative_pointer_manager_v1_interface.name) == 0)
238- be->relative_pointer_manager = wl_registry_bind(registry, name, &zwp_relative_pointer_manager_v1_interface, 1);
239-}
240-
241-static void seat_capabilities(void* data, struct wl_seat* seat, uint32_t capabilities)
242-{
243- Maus* mw = data;
244- MausBackend* be = &mw->backend;
245-
246- if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !be->pointer) {
247- be->pointer = wl_seat_get_pointer(seat);
248- wl_pointer_add_listener(be->pointer, &pointer_listener, mw);
249- }
250- else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && be->pointer) {
251- cursor_absolute(mw);
252- wl_pointer_destroy(be->pointer);
253- be->pointer = NULL;
254- }
255-
256- if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && !be->keyboard) {
257- be->keyboard = wl_seat_get_keyboard(seat);
258- wl_keyboard_add_listener(be->keyboard, &keyboard_listener, mw);
259- }
260- else if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && be->keyboard) {
261- wl_keyboard_destroy(be->keyboard);
262- be->keyboard = NULL;
263- }
264-}
265-
266-static void seat_name(void* data, struct wl_seat* seat, const char* name)
267-{
268- (void)data;
269- (void)seat;
270- (void)name;
271-}
272-
273-static void pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial,
274- struct wl_surface* surface, wl_fixed_t sx, wl_fixed_t sy)
275-{
276- Maus* mw = data;
277-
278- (void)pointer;
279- (void)surface;
280- (void)sx;
281- (void)sy;
282-
283- mw->backend.pointer_enter_serial = serial;
284- if (mw->backend.cursor_state == MAUS_CURSOR_STATE_HIDDEN)
285- cursor_hide(mw);
286- else
287- cursor_show(mw);
288-}
289-
290-static void pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial,
291- struct wl_surface* surface)
292-{
293- (void)data;
294- (void)pointer;
295- (void)serial;
296- (void)surface;
297-}
298-
299-static void pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time,
300- wl_fixed_t sx, wl_fixed_t sy)
301-{
302- Maus* mw = data;
303- MausBackend* be = &mw->backend;
304- int32_t x;
305- int32_t y;
306-
307- (void)pointer;
308- (void)time;
309-
310- if (be->relative_pointer)
311- return;
312-
313- x = wl_fixed_to_int(sx);
314- y = wl_fixed_to_int(sy);
315-
316- be->pending.pending = 1;
317- be->pending.type = MAUS_EV_MOUSE_MOTION;
318- be->pending.mouse_x = x;
319- be->pending.mouse_y = y;
320- be->pending.mouse_dx = be->mouse_pos_set ? x - be->mouse_x : 0;
321- be->pending.mouse_dy = be->mouse_pos_set ? y - be->mouse_y : 0;
322- be->mouse_x = x;
323- be->mouse_y = y;
324- be->mouse_pos_set = 1;
325- event_push_pending(mw);
326-}
327-
328-static void pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial,
329- uint32_t time, uint32_t button, uint32_t state)
330-{
331- Maus* mw = data;
332- MausMouseButton mb;
333-
334- (void)pointer;
335- (void)serial;
336- (void)time;
337-
338- mb = wl_button_to_maus(button);
339- mw->backend.pending.pending = 1;
340- mw->backend.pending.type = MAUS_EV_MOUSE_BUTTON;
341- mw->backend.pending.mouse_button = mb;
342- mw->backend.pending.mouse_pressed = state == WL_POINTER_BUTTON_STATE_PRESSED;
343-
344- if (mb != MAUS_MOUSE_BUTTON_NONE)
345- mw->mouse_buttons[mb] = mw->backend.pending.mouse_pressed;
346- event_push_pending(mw);
347-}
348-
349-static void pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time,
350- uint32_t axis, wl_fixed_t value)
351-{
352- Maus* mw = data;
353-
354- (void)pointer;
355- (void)time;
356-
357- if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
358- return;
359-
360- mw->backend.pending.pending = 1;
361- mw->backend.pending.type = MAUS_EV_MOUSE_BUTTON;
362- mw->backend.pending.mouse_button = wl_fixed_to_int(value) > 0
363- ? MAUS_MOUSE_BUTTON_SCROLL_DOWN
364- : MAUS_MOUSE_BUTTON_SCROLL_UP;
365- mw->backend.pending.mouse_pressed = 1;
366- event_push_pending(mw);
367-}
368-
369-static void pointer_frame(void* data, struct wl_pointer* pointer)
370-{
371- (void)data;
372- (void)pointer;
373-}
374-
375-static void pointer_axis_source(void* data, struct wl_pointer* pointer, uint32_t axis_source)
376-{
377- (void)data;
378- (void)pointer;
379- (void)axis_source;
380-}
381-
382-static void pointer_axis_stop(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis) {
383- (void)data;
384- (void)pointer;
385- (void)time;
386- (void)axis;
387-}
388-
389-static void pointer_axis_discrete(void* data, struct wl_pointer* pointer, uint32_t axis,
390- int32_t discrete)
391-{
392- (void)data;
393- (void)pointer;
394- (void)axis;
395- (void)discrete;
396-}
397-
398-static void pointer_axis_value120(void* data, struct wl_pointer* pointer, uint32_t axis,
399- int32_t value120)
400-{
401- (void)data;
402- (void)pointer;
403- (void)axis;
404- (void)value120;
405-}
406-
407-static void pointer_axis_relative_direction(void* data, struct wl_pointer* pointer,
408- uint32_t axis, uint32_t direction)
409-{
410- (void)data;
411- (void)pointer;
412- (void)axis;
413- (void)direction;
414-}
415-
416-static void relative_pointer_motion(void* data, struct zwp_relative_pointer_v1* relative_pointer,
417- uint32_t utime_hi, uint32_t utime_lo,
418- wl_fixed_t dx, wl_fixed_t dy,
419- wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel)
420-{
421- Maus* mw = data;
422-
423- (void)relative_pointer;
424- (void)utime_hi;
425- (void)utime_lo;
426- (void)dx_unaccel;
427- (void)dy_unaccel;
428-
429- mw->backend.pending.pending = 1;
430- mw->backend.pending.type = MAUS_EV_MOUSE_MOTION;
431- mw->backend.pending.mouse_x = wl_fixed_to_int(dx);
432- mw->backend.pending.mouse_y = wl_fixed_to_int(dy);
433- mw->backend.pending.mouse_dx = wl_fixed_to_int(dx);
434- mw->backend.pending.mouse_dy = wl_fixed_to_int(dy);
435- event_push_pending(mw);
436-}
437-
438-static void keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format,
439- int32_t fd, uint32_t size)
440-{
441- Maus* mw = data;
442- MausBackend* be = &mw->backend;
443- char* map;
444-
445- (void)keyboard;
446-
447- if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
448- close(fd);
449- return;
450- }
451-
452- map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
453- if (map == MAP_FAILED) {
454- close(fd);
455- return;
456- }
457-
458- if (be->xkb_state)
459- xkb_state_unref(be->xkb_state);
460- if (be->xkb_keymap)
461- xkb_keymap_unref(be->xkb_keymap);
462-
463- be->xkb_keymap = xkb_keymap_new_from_string(
464- be->xkb_context, map,
465- XKB_KEYMAP_FORMAT_TEXT_V1,
466- XKB_KEYMAP_COMPILE_NO_FLAGS
467- );
468-
469- munmap(map, size);
470- close(fd);
471-
472- if (!be->xkb_keymap)
473- return;
474-
475- be->xkb_state = xkb_state_new(be->xkb_keymap);
476-}
477-
478-static void keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial,
479- struct wl_surface* surface, struct wl_array* keys)
480-{
481- (void)data;
482- (void)keyboard;
483- (void)serial;
484- (void)surface;
485- (void)keys;
486-}
487-
488-static void keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial,
489- struct wl_surface* surface)
490-{
491- Maus* mw = data;
492-
493- (void)keyboard;
494- (void)serial;
495- (void)surface;
496-
497- mw->backend.repeat_key_code = 0;
498-}
499-
500-static void keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial,
501- uint32_t time, uint32_t key, uint32_t state)
502-{
503- Maus* mw = data;
504- MausBackend* be = &mw->backend;
505- uint32_t code;
506- xkb_keysym_t sym;
507- MausKey maus_key;
508- char text[8];
509- int len;
510- uint8_t pressed;
511-
512- (void)keyboard;
513- (void)serial;
514- (void)time;
515-
516- code = key + 8;
517- sym = XKB_KEY_NoSymbol;
518- text[0] = 0;
519-
520- if (be->xkb_state) {
521- sym = xkb_state_key_get_one_sym(be->xkb_state, code);
522- if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
523- len = xkb_state_key_get_utf8(be->xkb_state, code, text, sizeof(text));
524- if (len <= 0)
525- text[0] = 0;
526- }
527- }
528-
529- maus_key = keysym_to_mauskey(sym);
530- if (maus_key == MAUS_KEY_ENTER)
531- text[0] = '\n';
532- pressed = state == WL_KEYBOARD_KEY_STATE_PRESSED;
533- event_push_key(mw, code, maus_key, text[0], pressed);
534-
535- if (code < MAUS_KEYCODE_LAST)
536- mw->key_codes[code] = pressed;
537- if (maus_key != MAUS_KEY_NONE)
538- mw->key_syms[maus_key] = pressed;
539-
540- if (!pressed) {
541- if (be->repeat_key_code == code)
542- be->repeat_key_code = 0;
543- return;
544- }
545-
546- if (be->repeat_rate > 0 && be->xkb_keymap &&
547- xkb_keymap_key_repeats(be->xkb_keymap, code)) {
548- be->repeat_key_code = code;
549- be->repeat_key_sym = maus_key;
550- be->repeat_key_text = text[0];
551- be->repeat_next_ns = maus_get_time_ns() + be->repeat_delay * 1000000;
552- }
553- else
554- be->repeat_key_code = 0;
555-}
556-
557-static void keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial,
558- uint32_t mods_depressed, uint32_t mods_latched,
559- uint32_t mods_locked, uint32_t group)
560-{
561- Maus* mw = data;
562-
563- (void)keyboard;
564- (void)serial;
565-
566- if (!mw->backend.xkb_state)
567- return;
568-
569- xkb_state_update_mask(
570- mw->backend.xkb_state, mods_depressed,
571- mods_latched, mods_locked,
572- 0, 0, group
573- );
574-}
575-
576-static void keyboard_repeat_info(void* data, struct wl_keyboard* keyboard,
577- int32_t rate, int32_t delay)
578-{
579- Maus* mw = data;
580-
581- (void)keyboard;
582-
583- mw->backend.repeat_rate = rate;
584- mw->backend.repeat_delay = delay;
585- if (rate <= 0)
586- mw->backend.repeat_key_code = 0;
587-}
588-
589-static int8_t repeat_push_due(Maus* mw)
590-{
591- MausBackend* be = &mw->backend;
592- uint64_t now;
593- uint64_t interval;
594-
595- if (be->repeat_key_code == 0 || be->repeat_rate <= 0)
596- return 0;
597-
598- now = maus_get_time_ns();
599- if (now < be->repeat_next_ns)
600- return 0;
601-
602- event_push_key(mw, be->repeat_key_code, be->repeat_key_sym, be->repeat_key_text, 1);
603- interval = 1000000000 / be->repeat_rate;
604- do {
605- be->repeat_next_ns += interval;
606- } while (be->repeat_next_ns <= now);
607-
608- return 1;
609-}
610-
611-static int32_t repeat_timeout_ms(Maus* mw)
612-{
613- MausBackend* be = &mw->backend;
614- uint64_t now;
615- uint64_t diff;
616-
617- if (be->repeat_key_code == 0 || be->repeat_rate <= 0)
618- return -1;
619-
620- now = maus_get_time_ns();
621- if (now >= be->repeat_next_ns)
622- return 0;
623-
624- diff = be->repeat_next_ns - now;
625- /* round xto nearest ms */
626- return (int32_t)((diff + 999999) / 1000000);
627-}
628-
629-static int8_t display_read(Maus* mw, int timeout_ms)
630-{
631- MausBackend* be = &mw->backend;
632- struct pollfd pfd;
633- int ret;
634-
635- if (wl_display_prepare_read(be->display) != 0) {
636- wl_display_dispatch_pending(be->display);
637- return 1;
638- }
639-
640- wl_display_flush(be->display);
641-
642- pfd.fd = wl_display_get_fd(be->display);
643- pfd.events = POLLIN;
644- pfd.revents = 0;
645-
646- ret = poll(&pfd, 1, timeout_ms);
647- if (ret > 0 && (pfd.revents & POLLIN)) {
648- if (wl_display_read_events(be->display) == -1) {
649- wl_display_cancel_read(be->display);
650- return -1;
651- }
652- wl_display_dispatch_pending(be->display);
653- return 1;
654- }
655-
656- wl_display_cancel_read(be->display);
657- return 0;
658-}
659-
660-
661-static int8_t cursor_init(Maus* mw)
662-{
663- MausBackend* be = &mw->backend;
664-
665- be->cursor_theme = wl_cursor_theme_load(NULL, 24, be->shm);
666- if (!be->cursor_theme)
667- return 0;
668-
669- be->cursor = wl_cursor_theme_get_cursor(be->cursor_theme, "left_ptr");
670- if (!be->cursor)
671- return 0;
672-
673- be->cursor_surface = wl_compositor_create_surface(be->compositor);
674- if (!be->cursor_surface)
675- return 0;
676-
677- return 1;
678-}
679-
680-static void cursor_destroy(Maus* mw)
681-{
682- MausBackend* be = &mw->backend;
683-
684- if (be->cursor_surface)
685- wl_surface_destroy(be->cursor_surface);
686- if (be->cursor_theme)
687- wl_cursor_theme_destroy(be->cursor_theme);
688-
689- be->cursor_surface = NULL;
690- be->cursor_theme = NULL;
691- be->cursor = NULL;
692-}
693-
694-static void cursor_hide(Maus* mw)
695-{
696- MausBackend* be = &mw->backend;
697-
698- if (!be->pointer)
699- return;
700-
701- wl_pointer_set_cursor(be->pointer, be->pointer_enter_serial, NULL, 0, 0);
702-}
703-
704-static void cursor_lock(Maus* mw)
705-{
706- MausBackend* be = &mw->backend;
707-
708- if (be->locked_pointer)
709- return;
710- if (!be->pointer_constraints || !be->surface || !be->pointer)
711- return;
712-
713- be->locked_pointer = zwp_pointer_constraints_v1_confine_pointer(
714- be->pointer_constraints, be->surface, be->pointer, NULL,
715- ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT
716- );
717-}
718-
719-static void cursor_unlock(Maus* mw)
720-{
721- MausBackend* be = &mw->backend;
722-
723- if (be->locked_pointer) {
724- zwp_confined_pointer_v1_destroy(be->locked_pointer);
725- be->locked_pointer = NULL;
726- }
727-
728- if (be->cursor_state == MAUS_CURSOR_STATE_VISIBLE)
729- cursor_show(mw);
730-}
731-
732-static void cursor_show(Maus* mw)
733-{
734- MausBackend* be = &mw->backend;
735- struct wl_cursor_image* image;
736- struct wl_buffer* buffer;
737-
738- if (!be->pointer || !be->cursor || !be->cursor_surface)
739- return;
740-
741- image = be->cursor->images[0];
742- buffer = wl_cursor_image_get_buffer(image);
743- if (!buffer)
744- return;
745-
746- wl_pointer_set_cursor(
747- be->pointer, be->pointer_enter_serial,
748- be->cursor_surface, image->hotspot_x, image->hotspot_y
749- );
750- wl_surface_attach(be->cursor_surface, buffer, 0, 0);
751- wl_surface_damage_buffer(be->cursor_surface, 0, 0, image->width, image->height);
752- wl_surface_commit(be->cursor_surface);
753-}
754-
755-static void cursor_relative(Maus* mw)
756-{
757- MausBackend* be = &mw->backend;
758- if (be->relative_pointer)
759- return;
760- if (!be->relative_pointer_manager || !be->pointer)
761- return;
762-
763- cursor_lock(mw);
764- be->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
765- be->relative_pointer_manager, be->pointer
766- );
767- zwp_relative_pointer_v1_add_listener(
768- be->relative_pointer, &relative_pointer_listener, mw
769- );
770-}
771-
772-static void cursor_absolute(Maus* mw)
773-{
774- MausBackend* be = &mw->backend;
775-
776- if (be->relative_pointer) {
777- zwp_relative_pointer_v1_destroy(be->relative_pointer);
778- be->relative_pointer = NULL;
779- }
780-
781- cursor_unlock(mw);
782-}
783-
784-static int8_t fb_create(Maus* mw);
785-static int8_t fb_create_buffer(Maus* mw, MausWLBuffer* wb);
786-static int8_t fb_create_shm(size_t size);
787-static void fb_destroy(Maus* mw);
788-static int8_t handle_event(Maus* mw, MausEvent* ev);
789-
790-static int8_t fb_create(Maus* mw)
791-{
792- MausBackend* be = &mw->backend;
793-
794- if (!fb_create_buffer(mw, &be->buffers[0])) {
795- fb_destroy(mw);
796- return 0;
797- }
798- if (!fb_create_buffer(mw, &be->buffers[1])) {
799- fb_destroy(mw);
800- return 0;
801- }
802-
803- mw->fb = be->buffers[0].data;
804- mw->stride = mw->width;
805- return 1;
806-}
807-
808-static int8_t fb_create_buffer(Maus* mw, MausWLBuffer* wb)
809-{
810- MausBackend* be = &mw->backend;
811- struct wl_shm_pool* pool;
812-
813- int fd;
814- int stride;
815- int size;
816-
817- stride = mw->width * 4;
818- size = stride * mw->height;
819-
820- fd = fb_create_shm(size);
821- if (fd < 0)
822- return 0;
823-
824- wb->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
825- if (wb->data == MAP_FAILED) {
826- wb->data = NULL;
827- close(fd);
828- return 0;
829- }
830-
831- pool = wl_shm_create_pool(be->shm, fd, size);
832- wb->buffer = wl_shm_pool_create_buffer(
833- pool, 0, mw->width, mw->height,
834- stride, WL_SHM_FORMAT_XRGB8888
835- );
836-
837- wl_shm_pool_destroy(pool);
838- close(fd);
839-
840- if (!wb->buffer) {
841- munmap(wb->data, size);
842- wb->data = NULL;
843- return 0;
844- }
845-
846- wl_buffer_add_listener(wb->buffer, &wl_buffer_listener, wb);
847- wb->size = size;
848- wb->busy = 0;
849-
850- return 1;
851-}
852-
853-static int8_t fb_create_shm(size_t size)
854-{
855- char name[64];
856- int fd;
857-
858- int i;
859-
860- for (i = 0; i < 100; i++) {
861- snprintf(name, sizeof(name), "/maus-%ld-%d", (long)getpid(), i);
862-
863- fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
864- if (fd >= 0) {
865- shm_unlink(name);
866-
867- if (ftruncate(fd, size) < 0) {
868- close(fd);
869- return -1;
870- }
871-
872- return fd;
873- }
874- }
875-
876- return -1;
877-}
878-
879-static void fb_destroy(Maus* mw)
880-{
881- MausBackend* be = &mw->backend;
882-
883- uint32_t i;
884-
885- for (i = 0; i < 2; i++) {
886- if (be->buffers[i].buffer)
887- wl_buffer_destroy(be->buffers[i].buffer);
888-
889- if (be->buffers[i].data && be->buffers[i].size > 0)
890- munmap(be->buffers[i].data, be->buffers[i].size);
891-
892- be->buffers[i].buffer = NULL;
893- be->buffers[i].data = NULL;
894- be->buffers[i].size = 0;
895- be->buffers[i].busy = 0;
896- }
897- mw->fb = NULL;
898-}
899-
900-static int8_t handle_event(Maus* mw, MausEvent* ev)
901-{
902- MausEventPending pending;
903-
904- if (!event_pop(mw, &pending))
905- return 0;
906-
907- ev->type = pending.type;
908-
909- switch (ev->type) {
910- case MAUS_EV_CLOSE:
911- return 1;
912-
913- case MAUS_EV_RESIZE:
914- ev->resize.width = pending.width;
915- ev->resize.height = pending.height;
916- return 1;
917-
918- case MAUS_EV_MOUSE_MOTION:
919- ev->mouse.motion.x = pending.mouse_x;
920- ev->mouse.motion.y = pending.mouse_y;
921- ev->mouse.motion.dx = pending.mouse_dx;
922- ev->mouse.motion.dy = pending.mouse_dy;
923- return 1;
924-
925- case MAUS_EV_MOUSE_BUTTON:
926- ev->mouse.button.button = pending.mouse_button;
927- ev->mouse.button.pressed = pending.mouse_pressed;
928- return 1;
929-
930- case MAUS_EV_KEY:
931- ev->key.code = pending.key_code;
932- ev->key.pressed = pending.key_pressed;
933- ev->key.key = pending.key_sym;
934- ev->key.text = pending.key_text;
935- return 1;
936-
937- default:
938- return 1;
939- }
940-}
941-
942-static MausMouseButton wl_button_to_maus(uint32_t button)
943-{
944- switch (button) {
945- case 0x110: return MAUS_MOUSE_BUTTON_LEFT;
946- case 0x111: return MAUS_MOUSE_BUTTON_RIGHT;
947- case 0x112: return MAUS_MOUSE_BUTTON_MIDDLE;
948- default: return MAUS_MOUSE_BUTTON_NONE;
949- }
950-}
951-
952-static MausKey keysym_to_mauskey(xkb_keysym_t sym)
953-{
954- if (sym >= 0x20 && sym <= 0x7E)
955- return (MausKey)sym;
956-
957- if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F12)
958- return MAUS_KEY_F1 + (sym - XKB_KEY_F1);
959- if (sym >= XKB_KEY_KP_0 && sym <= XKB_KEY_KP_9)
960- return MAUS_KEY_KP_0 + (sym - XKB_KEY_KP_0);
961-
962- switch (sym) {
963- case XKB_KEY_BackSpace: return MAUS_KEY_BACKSPACE;
964- case XKB_KEY_Tab: return MAUS_KEY_TAB;
965- case XKB_KEY_Return: return MAUS_KEY_ENTER;
966- case XKB_KEY_Escape: return MAUS_KEY_ESCAPE;
967- case XKB_KEY_Delete: return MAUS_KEY_DELETE;
968- case XKB_KEY_Left: return MAUS_KEY_LEFT;
969- case XKB_KEY_Right: return MAUS_KEY_RIGHT;
970- case XKB_KEY_Up: return MAUS_KEY_UP;
971- case XKB_KEY_Down: return MAUS_KEY_DOWN;
972- case XKB_KEY_Home: return MAUS_KEY_HOME;
973- case XKB_KEY_End: return MAUS_KEY_END;
974- case XKB_KEY_Page_Up: return MAUS_KEY_PAGE_UP;
975- case XKB_KEY_Page_Down: return MAUS_KEY_PAGE_DOWN;
976- case XKB_KEY_Insert: return MAUS_KEY_INSERT;
977- case XKB_KEY_Shift_L: return MAUS_KEY_SHIFT_L;
978- case XKB_KEY_Shift_R: return MAUS_KEY_SHIFT_R;
979- case XKB_KEY_Control_L: return MAUS_KEY_CONTROL_L;
980- case XKB_KEY_Control_R: return MAUS_KEY_CONTROL_R;
981- case XKB_KEY_Alt_L: return MAUS_KEY_ALT_L;
982- case XKB_KEY_Alt_R: return MAUS_KEY_ALT_R;
983- case XKB_KEY_Super_L: return MAUS_KEY_SUPER_L;
984- case XKB_KEY_Super_R: return MAUS_KEY_SUPER_R;
985- case XKB_KEY_Caps_Lock: return MAUS_KEY_CAPS_LOCK;
986- case XKB_KEY_Num_Lock: return MAUS_KEY_NUM_LOCK;
987- case XKB_KEY_Scroll_Lock: return MAUS_KEY_SCROLL_LOCK;
988- case XKB_KEY_Print: return MAUS_KEY_PRINT_SCREEN;
989- case XKB_KEY_Pause: return MAUS_KEY_PAUSE;
990- case XKB_KEY_Menu: return MAUS_KEY_MENU;
991- case XKB_KEY_KP_Decimal: return MAUS_KEY_KP_DECIMAL;
992- case XKB_KEY_KP_Divide: return MAUS_KEY_KP_DIVIDE;
993- case XKB_KEY_KP_Multiply: return MAUS_KEY_KP_MULTIPLY;
994- case XKB_KEY_KP_Subtract: return MAUS_KEY_KP_SUBTRACT;
995- case XKB_KEY_KP_Add: return MAUS_KEY_KP_ADD;
996- case XKB_KEY_KP_Enter: return MAUS_KEY_KP_ENTER;
997- case XKB_KEY_KP_Equal: return MAUS_KEY_KP_EQUAL;
998- default: return MAUS_KEY_NONE;
999- }
1000-}
1001-
1002-void maus_clear(Maus* mw, MausColor col)
1003-{
1004- uint32_t up = MAUS_UNPACK_COL(col);
1005- uint32_t pxs = mw->height * mw->width;
1006-
1007- uint32_t i;
1008-
1009- for (i = 0; i < pxs; i++)
1010- mw->bfb[i] = up;
1011-}
1012-
1013-/* TODO */
1014-void maus_clipboard_set_text(Maus* mw, const char* text)
1015-{
1016- (void)mw;
1017- (void)text;
1018-}
1019-
1020-/* TODO */
1021-char* maus_clipboard_get_text(Maus* mw)
1022-{
1023- (void)mw;
1024- return NULL;
1025-}
1026-
1027-void maus_close(Maus* mw)
1028-{
1029- MausBackend* be;
1030-
1031- if (!mw)
1032- return;
1033-
1034- be = &mw->backend;
1035-
1036- fb_destroy(mw);
1037- cursor_absolute(mw);
1038-
1039- if (be->xdg_toplevel)
1040- xdg_toplevel_destroy(be->xdg_toplevel);
1041-
1042- if (be->xdg_surface)
1043- xdg_surface_destroy(be->xdg_surface);
1044-
1045- if (be->surface)
1046- wl_surface_destroy(be->surface);
1047-
1048- if (be->keyboard)
1049- wl_keyboard_destroy(be->keyboard);
1050-
1051- if (be->pointer)
1052- wl_pointer_destroy(be->pointer);
1053-
1054- if (be->seat)
1055- wl_seat_destroy(be->seat);
1056-
1057- if (be->pointer_constraints)
1058- zwp_pointer_constraints_v1_destroy(be->pointer_constraints);
1059-
1060- if (be->relative_pointer_manager)
1061- zwp_relative_pointer_manager_v1_destroy(be->relative_pointer_manager);
1062-
1063- if (be->xkb_state)
1064- xkb_state_unref(be->xkb_state);
1065-
1066- if (be->xkb_keymap)
1067- xkb_keymap_unref(be->xkb_keymap);
1068-
1069- if (be->xkb_context)
1070- xkb_context_unref(be->xkb_context);
1071-
1072- cursor_destroy(mw);
1073-
1074- if (be->wm_base)
1075- xdg_wm_base_destroy(be->wm_base);
1076-
1077- if (be->shm)
1078- wl_shm_destroy(be->shm);
1079-
1080- if (be->compositor)
1081- wl_compositor_destroy(be->compositor);
1082-
1083- if (be->registry)
1084- wl_registry_destroy(be->registry);
1085-
1086- if (be->display) {
1087- wl_display_flush(be->display);
1088- wl_display_disconnect(be->display);
1089- }
1090-
1091- free(mw->bfb);
1092- free(mw);
1093-}
1094-
1095-int8_t maus_close_window(Maus* mw)
1096-{
1097- MausBackend* be = &mw->backend;
1098-
1099- cursor_unlock(mw);
1100- fb_destroy(mw);
1101-
1102- if (be->xdg_toplevel)
1103- xdg_toplevel_destroy(be->xdg_toplevel);
1104- if (be->xdg_surface)
1105- xdg_surface_destroy(be->xdg_surface);
1106- if (be->surface)
1107- wl_surface_destroy(be->surface);
1108-
1109- be->xdg_toplevel = NULL;
1110- be->xdg_surface = NULL;
1111- be->surface = NULL;
1112- be->configured = 0;
1113-
1114- return 1;
1115-}
1116-
1117-int8_t maus_create_window(Maus* mw)
1118-{
1119- MausBackend* be = &mw->backend;
1120-
1121- be->surface = wl_compositor_create_surface(be->compositor);
1122- if (!be->surface)
1123- return 0;
1124-
1125- be->xdg_surface = xdg_wm_base_get_xdg_surface(be->wm_base, be->surface);
1126- if (!be->xdg_surface)
1127- return 0;
1128-
1129- xdg_surface_add_listener(be->xdg_surface, &xdg_surface_listener, mw);
1130-
1131- be->xdg_toplevel = xdg_surface_get_toplevel(be->xdg_surface);
1132- if (!be->xdg_toplevel)
1133- return 0;
1134-
1135- xdg_toplevel_add_listener(be->xdg_toplevel, &xdg_toplevel_listener, mw);
1136- xdg_toplevel_set_title(be->xdg_toplevel, mw->title);
1137-
1138- if (!fb_create(mw))
1139- return 0;
1140-
1141- wl_surface_commit(be->surface);
1142-
1143- while (!be->configured) {
1144- if (wl_display_dispatch(be->display) == -1)
1145- return 0;
1146- }
1147-
1148- return 1;
1149-}
1150-
1151-Maus* maus_init(const char* title, int x, int y, int width, int height)
1152-{
1153- Maus* mw = calloc(1, sizeof(Maus));
1154- MausBackend* be = &mw->backend;
1155-
1156- if (!mw)
1157- return NULL;
1158-
1159- be->display = wl_display_connect(NULL);
1160- if (!be->display) {
1161- free(mw);
1162- return NULL;
1163- }
1164-
1165- be->registry = wl_display_get_registry(be->display);
1166- wl_registry_add_listener(be->registry, ®istry_listener, mw);
1167- wl_display_roundtrip(be->display);
1168-
1169- be->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
1170- if (!be->xkb_context)
1171- goto close;
1172-
1173- if (!be->compositor || !be->shm || !be->wm_base) {
1174- maus_close(mw);
1175- free(mw);
1176- return NULL;
1177- }
1178-
1179- if (!cursor_init(mw))
1180- goto close;
1181-
1182- mw->frame_time_last = maus_get_time_ns();
1183- mw->title = title;
1184- mw->x = x;
1185- mw->y = y;
1186- mw->width = width;
1187- mw->height = height;
1188- mw->stride = width;
1189- be->cursor_state = MAUS_CURSOR_STATE_VISIBLE;
1190-
1191- mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
1192- if (!mw->bfb)
1193- goto close;
1194-
1195- return mw;
1196-close:
1197- maus_close(mw);
1198- free(mw);
1199- return NULL;
1200-}
1201-
1202-int8_t maus_event_poll(Maus* mw, MausEvent* ev)
1203-{
1204- MausBackend* be = &mw->backend;
1205- int8_t read;
1206-
1207- ev->type = MAUS_EV_NONE;
1208-
1209- if (repeat_push_due(mw) && handle_event(mw, ev))
1210- return 1;
1211-
1212- if (handle_event(mw, ev))
1213- return 1;
1214-
1215- wl_display_dispatch_pending(be->display);
1216- if (handle_event(mw, ev))
1217- return 1;
1218-
1219- read = display_read(mw, 0);
1220- if (read == -1) {
1221- ev->type = MAUS_EV_CLOSE;
1222- return 1;
1223- }
1224- if (read == 0)
1225- return 0;
1226- if (repeat_push_due(mw) && handle_event(mw, ev))
1227- return 1;
1228-
1229- return handle_event(mw, ev);
1230-}
1231-
1232-void maus_event_wait(Maus* mw, MausEvent* ev)
1233-{
1234- MausBackend* be = &mw->backend;
1235- int32_t timeout;
1236- int8_t read;
1237-
1238- ev->type = MAUS_EV_NONE;
1239-
1240- for (;;) {
1241- if (repeat_push_due(mw) && handle_event(mw, ev))
1242- return;
1243-
1244- if (handle_event(mw, ev))
1245- return;
1246-
1247- timeout = repeat_timeout_ms(mw);
1248- if (timeout >= 0) {
1249- read = display_read(mw, timeout);
1250- if (read == -1) {
1251- ev->type = MAUS_EV_CLOSE;
1252- return;
1253- }
1254- continue;
1255- }
1256-
1257- if (wl_display_dispatch(be->display) == -1) {
1258- ev->type = MAUS_EV_CLOSE;
1259- return;
1260- }
1261- }
1262-}
1263-
1264-void maus_present(Maus* mw)
1265-{
1266- MausBackend* be = &mw->backend;
1267- MausWLBuffer* wb = NULL;
1268- size_t bytes;
1269-
1270- uint32_t i;
1271-
1272- for (i = 0; i < 2; i++) {
1273- if (be->buffers[i].buffer && !be->buffers[i].busy) {
1274- wb = &be->buffers[i];
1275- break;
1276- }
1277- }
1278-
1279- if (!wb)
1280- return;
1281-
1282- bytes = mw->stride * mw->height * sizeof(uint32_t);
1283- memcpy(wb->data, mw->bfb, bytes);
1284- mw->fb = wb->data;
1285- wb->busy = 1;
1286-
1287- wl_surface_attach(be->surface, wb->buffer, 0, 0);
1288- wl_surface_damage_buffer(be->surface, 0, 0, mw->width, mw->height);
1289- wl_surface_commit(be->surface);
1290- wl_display_flush(be->display);
1291-}
1292-
1293-int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height)
1294-{
1295- uint32_t* bfb;
1296-
1297- if (width == 0 || height == 0)
1298- return 0;
1299-
1300- bfb = calloc(width * height, sizeof(uint32_t));
1301- if (!bfb)
1302- return 0;
1303-
1304- fb_destroy(mw);
1305- free(mw->bfb);
1306-
1307- mw->width = width;
1308- mw->height = height;
1309- mw->stride = width;
1310- mw->bfb = bfb;
1311-
1312- if (!fb_create(mw)) {
1313- free(mw->bfb);
1314- mw->bfb = NULL;
1315- return 0;
1316- }
1317-
1318- return 1;
1319-}
1320-
1321-void maus_cur_set_mode(Maus* mw, MausCursorState state)
1322-{
1323- switch (state) {
1324- case MAUS_CURSOR_STATE_VISIBLE:
1325- cursor_show(mw);
1326- mw->backend.cursor_state = state;
1327- break;
1328- case MAUS_CURSOR_STATE_HIDDEN:
1329- cursor_hide(mw);
1330- mw->backend.cursor_state = state;
1331- break;
1332- case MAUS_CURSOR_STATE_LOCKED:
1333- mw->backend.cursor_state = state;
1334- cursor_lock(mw);
1335- break;
1336- case MAUS_CURSOR_STATE_FREE:
1337- cursor_unlock(mw);
1338- mw->backend.cursor_state = state;
1339- break;
1340- case MAUS_CURSOR_STATE_RELATIVE:
1341- cursor_relative(mw);
1342- mw->backend.cursor_state = state;
1343- break;
1344- case MAUS_CURSOR_STATE_ABSOLUTE:
1345- cursor_absolute(mw);
1346- mw->backend.cursor_state = state;
1347- break;
1348- default:
1349- break;
1350- }
1351-}
1352-
+0,
-587
1@@ -1,587 +0,0 @@
2-#include <windows.h>
3-#include <windowsx.h>
4-
5-#include "maus.h"
6-#include "maus_input.h"
7-#include "maus_win.h"
8-
9-typedef struct {
10- UINT vk;
11- MausKey maus;
12-} KeyMapEntry;
13-
14-static int8_t fb_create(Maus* mw);
15-static void fb_destroy(Maus* mw);
16-static int8_t handle_event(const MSG* msg, MausEvent* ev, Maus* mw);
17-static MausKey vk_to_mauskey(UINT vk);
18-static UINT resolve_lr(UINT vk, LPARAM lparam);
19-static char translate_text(UINT vk, UINT scan);
20-static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
21-
22-static const KeyMapEntry keymap[] = {
23- { VK_BACK, MAUS_KEY_BACKSPACE }, { VK_TAB, MAUS_KEY_TAB },
24- { VK_RETURN, MAUS_KEY_ENTER }, { VK_ESCAPE, MAUS_KEY_ESCAPE },
25- { VK_SPACE, MAUS_KEY_SPACE }, { VK_DELETE, MAUS_KEY_DELETE },
26- { VK_LEFT, MAUS_KEY_LEFT }, { VK_RIGHT, MAUS_KEY_RIGHT },
27- { VK_UP, MAUS_KEY_UP }, { VK_DOWN, MAUS_KEY_DOWN },
28- { VK_HOME, MAUS_KEY_HOME }, { VK_END, MAUS_KEY_END },
29- { VK_PRIOR, MAUS_KEY_PAGE_UP }, { VK_NEXT, MAUS_KEY_PAGE_DOWN },
30- { VK_INSERT, MAUS_KEY_INSERT }, { VK_CAPITAL, MAUS_KEY_CAPS_LOCK },
31- { VK_NUMLOCK, MAUS_KEY_NUM_LOCK }, { VK_SCROLL, MAUS_KEY_SCROLL_LOCK },
32- { VK_PAUSE, MAUS_KEY_PAUSE }, { VK_SNAPSHOT, MAUS_KEY_PRINT_SCREEN },
33- { VK_APPS, MAUS_KEY_MENU }, { VK_LSHIFT, MAUS_KEY_SHIFT_L },
34- { VK_RSHIFT, MAUS_KEY_SHIFT_R }, { VK_LCONTROL, MAUS_KEY_CONTROL_L },
35- { VK_RCONTROL, MAUS_KEY_CONTROL_R }, { VK_LMENU, MAUS_KEY_ALT_L },
36- { VK_RMENU, MAUS_KEY_ALT_R }, { VK_LWIN, MAUS_KEY_SUPER_L },
37- { VK_RWIN, MAUS_KEY_SUPER_R }, { VK_ADD, MAUS_KEY_KP_ADD },
38- { VK_SUBTRACT, MAUS_KEY_KP_SUBTRACT },{ VK_MULTIPLY, MAUS_KEY_KP_MULTIPLY },
39- { VK_DIVIDE, MAUS_KEY_KP_DIVIDE }, { VK_DECIMAL, MAUS_KEY_KP_DECIMAL },
40-};
41-
42-static int8_t fb_create(Maus* mw)
43-{
44- MausBackend* be = &mw->backend;
45- BITMAPINFO bmi = {0};
46- HDC dc = GetDC(NULL);
47-
48- be->hbm = NULL;
49- mw->fb = NULL;
50- mw->stride = 0;
51-
52- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
53- bmi.bmiHeader.biWidth = mw->width;
54- bmi.bmiHeader.biHeight = -mw->height;
55- bmi.bmiHeader.biPlanes = 1;
56- bmi.bmiHeader.biBitCount = 32;
57- bmi.bmiHeader.biCompression = BI_RGB;
58-
59- be->memdc = CreateCompatibleDC(dc);
60- be->hbm = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (void**)&mw->fb, NULL, 0);
61- ReleaseDC(NULL, dc);
62-
63- if (!be->hbm || !mw->fb) {
64- if (be->memdc)
65- DeleteDC(be->memdc);
66- maus_log(stderr, "CreateDIBSection failed");
67- return 0;
68- }
69-
70- SelectObject(be->memdc, be->hbm);
71-
72- mw->stride = mw->width;
73- return 1;
74-}
75-
76-static void fb_destroy(Maus* mw)
77-{
78- MausBackend* be = &mw->backend;
79-
80- if (be->memdc) {
81- DeleteDC(be->memdc);
82- be->memdc = NULL;
83- }
84- if (be->hbm) {
85- DeleteObject(be->hbm);
86- be->hbm = NULL;
87- }
88-
89- mw->fb = NULL;
90- mw->stride = 0;
91-}
92-
93-static int8_t handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
94-{
95- UINT scan;
96- UINT vk;
97- int delta;
98- MausMouseButton mbtype;
99-
100- switch (msg->message) {
101- case WM_QUIT:
102- ev->type = MAUS_EV_CLOSE;
103- return 1;
104-
105- case WM_MOUSEMOVE:
106- ev->type = MAUS_EV_MOUSE_MOTION;
107- ev->mouse.motion.x = GET_X_LPARAM(msg->lParam);
108- ev->mouse.motion.y = GET_Y_LPARAM(msg->lParam);
109- return 1;
110-
111- case WM_LBUTTONDOWN:
112- ev->type = MAUS_EV_MOUSE_BUTTON;
113- ev->mouse.button.button = MAUS_MOUSE_BUTTON_LEFT;
114- ev->mouse.button.pressed = 1;
115- mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = 1;
116- return 1;
117- case WM_LBUTTONUP:
118- ev->type = MAUS_EV_MOUSE_BUTTON;
119- ev->mouse.button.button = MAUS_MOUSE_BUTTON_LEFT;
120- ev->mouse.button.pressed = 0;
121- mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = 0;
122- return 1;
123-
124- case WM_RBUTTONDOWN:
125- ev->type = MAUS_EV_MOUSE_BUTTON;
126- ev->mouse.button.button = MAUS_MOUSE_BUTTON_RIGHT;
127- ev->mouse.button.pressed = 1;
128- mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = 1;
129- return 1;
130- case WM_RBUTTONUP:
131- ev->type = MAUS_EV_MOUSE_BUTTON;
132- ev->mouse.button.button = MAUS_MOUSE_BUTTON_RIGHT;
133- ev->mouse.button.pressed = 0;
134- mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = 0;
135- return 1;
136-
137- case WM_MBUTTONDOWN:
138- ev->type = MAUS_EV_MOUSE_BUTTON;
139- ev->mouse.button.button = MAUS_MOUSE_BUTTON_MIDDLE;
140- ev->mouse.button.pressed = 1;
141- mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = 1;
142- return 1;
143- case WM_MBUTTONUP:
144- ev->type = MAUS_EV_MOUSE_BUTTON;
145- ev->mouse.button.button = MAUS_MOUSE_BUTTON_MIDDLE;
146- ev->mouse.button.pressed = 0;
147- mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = 0;
148- return 1;
149-
150- case WM_MOUSEWHEEL:
151- delta = GET_WHEEL_DELTA_WPARAM(msg->wParam);
152- mbtype = (delta > 0) ? MAUS_MOUSE_BUTTON_SCROLL_UP
153- : MAUS_MOUSE_BUTTON_SCROLL_DOWN;
154- ev->type = MAUS_EV_MOUSE_BUTTON;
155- ev->mouse.button.button = mbtype;
156- ev->mouse.button.pressed = 1;
157- return 1;
158-
159- case WM_KEYDOWN:
160- case WM_SYSKEYDOWN:
161- scan = (UINT)((msg->lParam >> 16) & 0xFF);
162- vk = resolve_lr((UINT)msg->wParam, msg->lParam);
163-
164- ev->type = MAUS_EV_KEY;
165- ev->key.code = (uint32_t)msg->wParam;
166- ev->key.pressed = 1;
167- ev->key.key = vk_to_mauskey(vk);
168- ev->key.text = translate_text((UINT)msg->wParam, scan);
169-
170- if (ev->key.code < MAUS_KEYCODE_LAST)
171- mw->key_codes[ev->key.code] = 1;
172- if (ev->key.key != MAUS_KEY_NONE)
173- mw->key_syms[ev->key.key] = 1;
174- return 1;
175-
176- case WM_KEYUP:
177- case WM_SYSKEYUP:
178- vk = resolve_lr((UINT)msg->wParam, msg->lParam);
179-
180- ev->type = MAUS_EV_KEY;
181- ev->key.code = (uint32_t)msg->wParam;
182- ev->key.pressed = 0;
183- ev->key.key = vk_to_mauskey(vk);
184- ev->key.text = 0;
185-
186- if (ev->key.code < MAUS_KEYCODE_LAST)
187- mw->key_codes[ev->key.code] = 0;
188- if (ev->key.key != MAUS_KEY_NONE)
189- mw->key_syms[ev->key.key] = 0;
190- return 1;
191- }
192-
193- return 0;
194-}
195-
196-static MausKey vk_to_mauskey(UINT vk)
197-{
198- if (vk >= 'A' && vk <= 'Z')
199- return (MausKey)(MAUS_KEY_A + (vk - 'A'));
200- if (vk >= '0' && vk <= '9')
201- return (MausKey)(MAUS_KEY_0 + (vk - '0'));
202- if (vk >= VK_F1 && vk <= VK_F12)
203- return (MausKey)(MAUS_KEY_F1 + (vk - VK_F1));
204- if (vk >= VK_NUMPAD0 && vk <= VK_NUMPAD9)
205- return (MausKey)(MAUS_KEY_KP_0 + (vk - VK_NUMPAD0));
206-
207- for (size_t i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++) {
208- if (keymap[i].vk == vk)
209- return keymap[i].maus;
210- }
211-
212- return MAUS_KEY_NONE;
213-}
214-
215-static UINT resolve_lr(UINT vk, LPARAM lparam)
216-{
217- UINT scan = (UINT)((lparam >> 16) & 0xFF);
218- int ext = (lparam & (1 << 24)) != 0;
219-
220- if (vk == VK_SHIFT)
221- return MapVirtualKey(scan, MAPVK_VSC_TO_VK_EX);
222- if (vk == VK_CONTROL)
223- return ext ? VK_RCONTROL : VK_LCONTROL;
224- if (vk == VK_MENU)
225- return ext ? VK_RMENU : VK_LMENU;
226-
227- return vk;
228-}
229-
230-static char translate_text(UINT vk, UINT scan)
231-{
232- BYTE state[256];
233- WCHAR buf[4];
234- int n;
235-
236- n = ToUnicode(vk, scan, state, buf, 4, 0);
237-
238- if (!GetKeyboardState(state))
239- return 0;
240- if (n == 1 && buf[0] < 0x80)
241- return (buf[0] == '\r') ? '\n' : (char)buf[0];
242-
243- return 0;
244-}
245-
246-static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
247-{
248- Maus* mw;
249- MausBackend* be;
250-
251- if (msg == WM_DESTROY) {
252- PostQuitMessage(EXIT_SUCCESS);
253- return 0;
254- }
255-
256- if (msg == WM_SIZE) {
257- mw = (Maus*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
258- if (mw) {
259- be = &mw->backend;
260- be->resized = 1;
261- be->rw = LOWORD(lp);
262- be->rh = HIWORD(lp);
263- }
264- return 0;
265- }
266-
267- return DefWindowProc(hwnd, msg, wp, lp);
268-}
269-
270-void maus_clear(Maus* mw, MausColor col)
271-{
272- uint32_t col_up = MAUS_UNPACK_COL(col);
273- uint32_t pxs = mw->height * mw->width;
274- uint32_t i;
275-
276- for (i = 0; i < pxs; i++)
277- mw->bfb[i] = col_up;
278-}
279-
280-void maus_clipboard_set_text(Maus* mw, const char* text)
281-{
282- MausBackend* be = &mw->backend;
283- size_t len = strlen(text) + 1;
284- HGLOBAL hmem;
285-
286- void* ptr;
287-
288- if (!text || !OpenClipboard(be->hwnd))
289- return;
290-
291- EmptyClipboard();
292- hmem = GlobalAlloc(GMEM_MOVEABLE, len);
293- if (hmem) {
294- ptr = GlobalLock(hmem);
295- if (ptr) {
296- memcpy(ptr, text, len);
297- GlobalUnlock(hmem);
298-
299- if (!SetClipboardData(CF_TEXT, hmem))
300- GlobalFree(hmem); /* failed */
301- }
302- else {
303- GlobalFree(hmem);
304- }
305- }
306-
307- CloseClipboard();
308-}
309-
310-char* maus_clipboard_get_text(Maus* mw)
311-{
312- MausBackend* be = &mw->backend;
313- HANDLE hmem;
314-
315- const char* text;
316- size_t len;
317-
318- if (!OpenClipboard(be->hwnd))
319- return NULL;
320-
321- hmem = GetClipboardData(CF_TEXT);
322- if (!hmem) {
323- CloseClipboard();
324- return NULL;
325- }
326-
327- text = GlobalLock(hmem);
328- if (text) {
329- if (mw->clipboard) {
330- free(mw->clipboard);
331- mw->clipboard = NULL;
332- }
333-
334- len = strlen(text) + 1;
335- mw->clipboard = malloc(len);
336- if (mw->clipboard)
337- memcpy(mw->clipboard, text, len);
338-
339- GlobalUnlock(hmem);
340- }
341-
342- CloseClipboard();
343- return mw->clipboard;
344-}
345-
346-void maus_close(Maus* mw)
347-{
348- MausBackend* be = &mw->backend;
349-
350- fb_destroy(mw);
351- if (mw->bfb) {
352- free(mw->bfb);
353- mw->bfb = NULL;
354- }
355- if (mw->clipboard) {
356- free(mw->clipboard);
357- mw->clipboard = NULL;
358- }
359- if (be->hwnd)
360- (void) maus_close_window(mw);
361-}
362-
363-int8_t maus_close_window(Maus* mw)
364-{
365- MausBackend* be = &mw->backend;
366-
367- if (be->hwnd) {
368- DestroyWindow(be->hwnd);
369- be->hwnd = NULL;
370- return 1;
371- }
372-
373- return 0;
374-}
375-
376-
377-int8_t maus_create_window(Maus* mw)
378-{
379- MausBackend* be = &mw->backend;
380- be->hInst = GetModuleHandle(NULL);
381- WNDCLASS wc = {0};
382-
383- RECT r = { 0, 0, mw->width, mw->height };
384-
385- wc.lpfnWndProc = WndProc;
386- wc.hInstance = be->hInst;
387- wc.lpszClassName = "MausWindow";
388- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
389- if (!RegisterClass(&wc))
390- return 0;
391-
392- AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);
393-
394- be->hwnd = CreateWindowEx(
395- 0, "MausWindow", mw->title,
396- WS_OVERLAPPEDWINDOW, mw->x, mw->y,
397- r.right - r.left, r.bottom - r.top,
398- NULL, NULL, be->hInst, NULL
399- );
400-
401- if (!be->hwnd)
402- return 0;
403-
404- SetWindowLongPtr(be->hwnd, GWLP_USERDATA, (LONG_PTR)mw);
405- ShowWindow(be->hwnd, SW_SHOW);
406- UpdateWindow(be->hwnd);
407- return 1;
408-}
409-
410-Maus* maus_init(const char* title, int x, int y, int width, int height)
411-{
412- Maus* mw = calloc(1, sizeof(Maus));
413- MausBackend* be = &mw->backend;
414-
415- mw->frame_time_last = maus_get_time_ns();
416- mw->title = title;
417- mw->width = width;
418- mw->height = height;
419- mw->x = x;
420- mw->y = y;
421- be->hInst = GetModuleHandle(NULL);
422- be->hwnd = NULL;
423- be->hbm = NULL;
424-
425- if (!fb_create(mw)) {
426- maus_log(stderr, "failed to create framebuffer");
427- free(mw);
428- return NULL;
429- }
430-
431- mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
432- if (!mw->bfb) {
433- maus_log(stderr, "failed to allocate back buffer");
434- maus_close(mw);
435- free(mw);
436- return NULL;
437- }
438-
439- return mw;
440-}
441-
442-int8_t maus_event_poll(Maus* mw, MausEvent* ev)
443-{
444- MausBackend* be = &mw->backend;
445- MSG msg;
446-
447- while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
448- TranslateMessage(&msg);
449- DispatchMessage(&msg);
450- ev->type = MAUS_EV_NONE;
451-
452- if (handle_event(&msg, ev, mw))
453- return 1;
454- }
455-
456- /* WM_SIZE doesnt is handled separately */
457- if (be->resized) {
458- be->resized = 0;
459- ev->type = MAUS_EV_RESIZE;
460- ev->resize.width = be->rw;
461- ev->resize.height = be->rh;
462- return 1;
463- }
464-
465- return 0;
466-}
467-
468-void maus_event_wait(Maus* mw, MausEvent* ev)
469-{
470- MausBackend* be = &mw->backend;
471- MSG msg;
472-
473- int r;
474-
475- for (;;) {
476- r = GetMessage(&msg, NULL, 0, 0);
477- if (r <= 0) {
478- ev->type = MAUS_EV_CLOSE;
479- return;
480- }
481-
482- TranslateMessage(&msg);
483- DispatchMessage(&msg);
484- ev->type = MAUS_EV_NONE;
485-
486- /* WM_SIZE doesnt is handled separately */
487- if (be->resized) {
488- be->resized = 0;
489- ev->type = MAUS_EV_RESIZE;
490- ev->resize.width = be->rw;
491- ev->resize.height = be->rh;
492- return;
493- }
494-
495- if (handle_event(&msg, ev, mw))
496- return;
497- }
498-}
499-
500-void maus_present(Maus* mw)
501-{
502- MausBackend* be = &mw->backend;
503- HDC wdc;
504-
505- uint32_t bytes;
506-
507- if (!be->hwnd || !be->memdc)
508- return;
509-
510- wdc = GetDC(be->hwnd);
511-
512- bytes = mw->stride * mw->height * sizeof(uint32_t);
513- memcpy(mw->fb, mw->bfb, bytes);
514-
515- BitBlt(wdc, 0, 0, mw->width, mw->height, be->memdc, 0, 0, SRCCOPY);
516- ReleaseDC(be->hwnd, wdc);
517-}
518-
519-int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height)
520-{
521- if (width == 0 || height == 0 ||
522- (mw->width == width && mw->height == height))
523- return 0;
524-
525- fb_destroy(mw);
526- if (mw->bfb) {
527- free(mw->bfb);
528- mw->bfb = NULL;
529- }
530-
531- mw->width = width;
532- mw->height = height;
533-
534- if (!fb_create(mw))
535- return 0;
536-
537- mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
538- if (!mw->bfb)
539- return 0;
540-
541- return 1;
542-}
543-
544-void maus_cur_set_mode(Maus* mw, MausCursorState state)
545-{
546- MausBackend* be = &mw->backend;
547- HWND hwnd = be->hwnd;
548-
549- RECT r;
550-
551- if (!hwnd) {
552- maus_log(stderr, "hwnd is NULL");
553- return;
554- }
555-
556- /* show cursor */
557- if (state == MAUS_CURSOR_STATE_VISIBLE) {
558- while (ShowCursor(TRUE) < 0);
559- return;
560- }
561-
562- /* hide cursor */
563- if (state == MAUS_CURSOR_STATE_HIDDEN) {
564- while (ShowCursor(FALSE) >= 0);
565- return;
566- }
567-
568-
569- /* lock cursor */
570- if (state == MAUS_CURSOR_STATE_LOCKED) {
571- GetClientRect(hwnd, &r);
572- MapWindowPoints(hwnd, NULL, (POINT*)&r, 2);
573-
574- if (!ClipCursor(&r)) {
575- maus_log(stderr, "failed to grab mouse pointer");
576- return;
577- }
578-
579- return;
580- }
581-
582- /* unlock cursor */
583- if (state == MAUS_CURSOR_STATE_FREE) {
584- ClipCursor(NULL);
585- return;
586- }
587-}
588-
+0,
-806
1@@ -1,806 +0,0 @@
2-#include <limits.h>
3-#include <stdlib.h>
4-#include <string.h>
5-#include <sys/shm.h>
6-#include <sys/ipc.h>
7-
8-#include <X11/Xlib.h>
9-#include <X11/Xutil.h>
10-#include <X11/keysym.h>
11-#include <X11/cursorfont.h>
12-#include <X11/extensions/XShm.h>
13-
14-#include "maus.h"
15-#include "maus_input.h"
16-#include "maus_x11.h"
17-#include "utils.h"
18-
19-typedef struct {
20- KeySym x11;
21- MausKey maus;
22-} KeyMapEntry;
23-
24-static int8_t fb_create(Maus* mw);
25-static int8_t fb_create_shm(Maus* mw);
26-/* TODO static int8_t fb_create_ximage(Maus* mw); */
27-static void fb_destroy(Maus* mw);
28-static int8_t handle_event(XEvent* xev, MausEvent* ev, Maus* mw);
29-static MausKey keysym_to_mauskey(KeySym sym);
30-static MausMouseButton mouse_button_to_maus(int btn);
31-static int xerr(Display* dpy, XErrorEvent* ev);
32-
33-static const KeyMapEntry keymap[] = {
34- { XK_BackSpace, MAUS_KEY_BACKSPACE }, { XK_Tab, MAUS_KEY_TAB },
35- { XK_Return, MAUS_KEY_ENTER }, { XK_Escape, MAUS_KEY_ESCAPE },
36- { XK_apostrophe, MAUS_KEY_APOSTROPHE },{ XK_comma, MAUS_KEY_COMMA },
37- { XK_space, MAUS_KEY_SPACE }, { XK_minus, MAUS_KEY_MINUS },
38- { XK_period, MAUS_KEY_PERIOD }, { XK_slash, MAUS_KEY_SLASH },
39- { XK_semicolon, MAUS_KEY_SEMICOLON }, { XK_equal, MAUS_KEY_EQUAL },
40- { XK_Delete, MAUS_KEY_DELETE }, { XK_Left, MAUS_KEY_LEFT },
41- { XK_Right, MAUS_KEY_RIGHT }, { XK_Up, MAUS_KEY_UP },
42- { XK_Down, MAUS_KEY_DOWN }, { XK_Home, MAUS_KEY_HOME },
43- { XK_End, MAUS_KEY_END }, { XK_Page_Up, MAUS_KEY_PAGE_UP },
44- { XK_Page_Down, MAUS_KEY_PAGE_DOWN }, { XK_Insert, MAUS_KEY_INSERT },
45- { XK_Shift_L, MAUS_KEY_SHIFT_L }, { XK_Shift_R, MAUS_KEY_SHIFT_R },
46- { XK_Control_L, MAUS_KEY_CONTROL_L }, { XK_Control_R, MAUS_KEY_CONTROL_R },
47- { XK_Alt_L, MAUS_KEY_ALT_L }, { XK_Alt_R, MAUS_KEY_ALT_R },
48- { XK_Super_L, MAUS_KEY_SUPER_L }, { XK_Super_R, MAUS_KEY_SUPER_R },
49- { XK_Caps_Lock, MAUS_KEY_CAPS_LOCK }, { XK_Num_Lock, MAUS_KEY_NUM_LOCK },
50- { XK_Pause, MAUS_KEY_PAUSE }, { XK_Menu, MAUS_KEY_MENU },
51- { XK_KP_Add, MAUS_KEY_KP_ADD }, { XK_KP_Enter, MAUS_KEY_KP_ENTER },
52- { XK_bracketright, MAUS_KEY_RIGHT_BRACKET }, { XK_grave, MAUS_KEY_GRAVE },
53- { XK_Scroll_Lock, MAUS_KEY_SCROLL_LOCK }, { XK_Print, MAUS_KEY_PRINT_SCREEN },
54- { XK_KP_Decimal, MAUS_KEY_KP_DECIMAL }, { XK_KP_Divide, MAUS_KEY_KP_DIVIDE },
55- { XK_KP_Multiply, MAUS_KEY_KP_MULTIPLY }, { XK_KP_Subtract, MAUS_KEY_KP_SUBTRACT },
56- { XK_bracketleft, MAUS_KEY_LEFT_BRACKET }, { XK_backslash, MAUS_KEY_BACKSLASH },
57- { XK_KP_Equal, MAUS_KEY_KP_EQUAL },
58-};
59-
60-static int xerrored;
61-
62-static int8_t fb_create(Maus* mw)
63-{
64- MausBackend* be = &mw->backend;
65-
66- be->image = NULL;
67- be->shmat = 0;
68- be->shm.shmid = -1;
69- be->shm.shmaddr = NULL;
70- mw->fb = NULL;
71- mw->stride = 0;
72-
73- return fb_create_shm(mw);
74-}
75-
76-/* allocate and store a new shm for the framebuffer */
77-static int8_t fb_create_shm(Maus* mw)
78-{
79- MausBackend* be = &mw->backend;
80- int scr = DefaultScreen(be->display);
81- int depth = DefaultDepth(be->display, scr);
82- Visual* vis = DefaultVisual(be->display, scr);
83-
84- size_t size;
85- int (*old_xerr)(Display*, XErrorEvent*);
86-
87- if (!XShmQueryExtension(be->display))
88- return 0;
89-
90- if (!vis) {
91- maus_log(stderr, "could not get default visual");
92- return 0;
93- }
94-
95- be->image = XShmCreateImage(
96- be->display, vis, depth, ZPixmap, NULL,
97- &be->shm, mw->width, mw->height
98- );
99-
100- if (!be->image) {
101- maus_log(stderr, "could not create XImage (shm)");
102- return 0;
103- }
104-
105- if (be->image->bits_per_pixel != 32) {
106- XDestroyImage(be->image);
107- be->image = NULL;
108- maus_log(stderr, "XImage not 32bpp");
109- return 0;
110- }
111-
112- size = be->image->bytes_per_line * be->image->height;
113- be->shm.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
114- if (be->shm.shmid < 0) {
115- XDestroyImage(be->image);
116- be->image = NULL;
117- maus_log(stderr, "shmget() failed");
118- return 0;
119- }
120-
121- be->shm.shmaddr = shmat(be->shm.shmid, NULL, 0);
122- if (be->shm.shmaddr == (char*)-1) {
123- shmctl(be->shm.shmid, IPC_RMID, NULL);
124- XDestroyImage(be->image);
125- be->image = NULL;
126- maus_log(stderr, "shmat() failed");
127- return 0;
128- }
129-
130- be->shm.readOnly = False;
131- be->image->data = be->shm.shmaddr;
132-
133- xerrored = 0;
134- old_xerr = XSetErrorHandler(xerr);
135-
136- if (!XShmAttach(be->display, &be->shm))
137- xerrored = 1;
138-
139- XSync(be->display, False);
140- XSetErrorHandler(old_xerr);
141- if (xerrored) {
142- shmdt(be->shm.shmaddr);
143- shmctl(be->shm.shmid, IPC_RMID, NULL);
144- XDestroyImage(be->image);
145-
146- be->image = NULL;
147- mw->fb = NULL;
148- be->shm.shmaddr = NULL;
149- be->shm.shmid = -1;
150- maus_log(stderr, "XShmAttach failed");
151- return 0;
152- }
153-
154- shmctl(be->shm.shmid, IPC_RMID, NULL);
155-
156- be->shmat = 1;
157- mw->fb = (uint32_t*) be->image->data;
158- mw->stride = be->image->bytes_per_line / sizeof(uint32_t);
159-
160- return 1;
161-}
162-
163-static void fb_destroy(Maus* mw)
164-{
165- MausBackend* be = &mw->backend;
166- Display* dpy = be->display;
167-
168- if (be->shmat) {
169- XShmDetach(dpy, &be->shm);
170- XSync(dpy, False);
171- be->shmat = 0;
172- }
173-
174- if (be->image) {
175- XDestroyImage(be->image);
176- be->image = NULL;
177- }
178-
179- if (be->shm.shmaddr && be->shm.shmaddr != (char*) -1) {
180- shmdt(be->shm.shmaddr);
181- be->shm.shmaddr = NULL;
182- }
183-
184- /* normally already removed after attach but
185- can check anyways */
186- if (be->shm.shmid >= 0) {
187- shmctl(be->shm.shmid, IPC_RMID, NULL);
188- be->shm.shmid = -1;
189- }
190-
191- mw->fb = NULL;
192- mw->stride = 0;
193-}
194-
195-static int8_t handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
196-{
197- MausBackend* be = &mw->backend;
198- uint32_t code = 0;
199- unsigned int mb;
200- MausMouseButton mbtype;
201-
202- char buf[8] = {0};
203- int len;
204-
205- KeySym sym;
206-
207- XSelectionRequestEvent* req;
208- XEvent rsp; /* response */
209- Atom utf8_string;
210- Atom clipboard;
211-
212- int cx;
213- int cy;
214-
215- switch (xev->type) {
216- case Expose:
217- if (xev->xexpose.count != 0)
218- return 0;
219- ev->type = MAUS_EV_REDRAW;
220- return 1;
221-
222- case ClientMessage:
223- if ((Atom)xev->xclient.data.l[0] == be->atoms[MAUS_ATOM_WM_DELETE_WINDOW]) {
224- ev->type = MAUS_EV_CLOSE;
225- return 1;
226- }
227- break;
228-
229- case MappingNotify:
230- XRefreshKeyboardMapping(&xev->xmapping);
231- return 1;
232- break;
233-
234- case KeyPress: {
235- ev->type = MAUS_EV_KEY;
236- code = xev->xkey.keycode;
237- ev->key.code = code;
238- ev->key.pressed = 1;
239- if (code < MAUS_KEYCODE_LAST)
240- mw->key_codes[code] = 1;
241-
242- /* grab the raw, base sym */
243- sym = XLookupKeysym(&xev->xkey, 0);
244- ev->key.key = keysym_to_mauskey(sym);
245- if (ev->key.key != MAUS_KEY_NONE)
246- mw->key_syms[ev->key.key] = 1;
247-
248- len = XLookupString(&xev->xkey, buf, sizeof(buf), NULL, NULL);
249- if (len > 0)
250- ev->key.text = (buf[0] == '\r') ? '\n' : buf[0];
251- else
252- ev->key.text = 0;
253-
254- return 1;
255- }
256-
257- case KeyRelease: {
258- ev->type = MAUS_EV_KEY;
259- code = xev->xkey.keycode;
260- ev->key.code = code;
261- ev->key.pressed = 0;
262- ev->key.text = 0;
263-
264- if (code < MAUS_KEYCODE_LAST)
265- mw->key_codes[code] = 0;
266-
267- /* unset base sym set on `KeyPress` */
268- sym = XLookupKeysym(&xev->xkey, 0);
269- ev->key.key = keysym_to_mauskey(sym);
270- if (ev->key.key != MAUS_KEY_NONE)
271- mw->key_syms[ev->key.key] = 0;
272-
273- return 1;
274- }
275-
276- case ButtonPress:
277- ev->type = MAUS_EV_MOUSE_BUTTON;
278- mb = xev->xbutton.button;
279- mbtype = mouse_button_to_maus(mb);
280- ev->mouse.button.button = mbtype;
281- ev->mouse.button.pressed = 1;
282- mw->mouse_buttons[mbtype] = 1;
283- return 1;
284-
285- case ButtonRelease:
286- ev->type = MAUS_EV_MOUSE_BUTTON;
287- mb = xev->xbutton.button;
288- mbtype = mouse_button_to_maus(mb);
289- ev->mouse.button.button = mbtype;
290- ev->mouse.button.pressed = 0;
291- mw->mouse_buttons[mbtype] = 0;
292- return 1;
293-
294- case MotionNotify:
295- if (be->cur_rel) {
296- cx = mw->width / 2;
297- cy = mw->height / 2;
298-
299- if (be->ignore_warp && xev->xmotion.x == cx && xev->xmotion.y == cy) {
300- be->ignore_warp = 0;
301- return 0;
302- }
303-
304- ev->type = MAUS_EV_MOUSE_MOTION;
305- ev->mouse.motion.x = xev->xmotion.x - cx;
306- ev->mouse.motion.y = xev->xmotion.y - cy;
307- ev->mouse.motion.dx = ev->mouse.motion.x;
308- ev->mouse.motion.dy = ev->mouse.motion.y;
309-
310- if (ev->mouse.motion.x != 0 || ev->mouse.motion.y != 0) {
311- be->ignore_warp = 1;
312- XWarpPointer(
313- be->display, None, be->win,
314- 0, 0, 0, 0, cx, cy
315- );
316- XFlush(be->display);
317- }
318-
319- return ev->mouse.motion.x != 0 || ev->mouse.motion.y != 0;
320- }
321- ev->type = MAUS_EV_MOUSE_MOTION;
322- ev->mouse.motion.x = xev->xmotion.x;
323- ev->mouse.motion.y = xev->xmotion.y;
324- ev->mouse.motion.dx = be->mouse_pos_set ? xev->xmotion.x - be->mouse_x : 0;
325- ev->mouse.motion.dy = be->mouse_pos_set ? xev->xmotion.y - be->mouse_y : 0;
326- be->mouse_x = xev->xmotion.x;
327- be->mouse_y = xev->xmotion.y;
328- be->mouse_pos_set = 1;
329- return 1;
330-
331- case ConfigureNotify:
332- ev->type = MAUS_EV_RESIZE;
333- ev->resize.width = xev->xconfigure.width;
334- ev->resize.height = xev->xconfigure.height;
335- return 1;
336-
337- case SelectionRequest: {
338- req = &xev->xselectionrequest;
339-
340- utf8_string = XInternAtom(be->display, "UTF8_STRING", False);
341- clipboard = XInternAtom(be->display, "CLIPBOARD", False);
342-
343- rsp.type = SelectionNotify;
344- rsp.xselection.display = req->display;
345- rsp.xselection.requestor = req->requestor;
346- rsp.xselection.selection = req->selection;
347- rsp.xselection.target = req->target;
348- rsp.xselection.property = None;
349- rsp.xselection.time = req->time;
350-
351- /* assign clipboard text to requesting programs
352- window property */
353- if (req->selection == clipboard &&
354- req->target == utf8_string &&
355- mw->clipboard) {
356- XChangeProperty(
357- req->display, req->requestor,
358- req->property, utf8_string, 8,
359- PropModeReplace, (unsigned char*)mw->clipboard,
360- strlen(mw->clipboard)
361- );
362- rsp.xselection.property = req->property;
363- }
364-
365- /* send reply back to the prog requesting paste */
366- XSendEvent(req->display, req->requestor, False, 0, &rsp);
367- XFlush(be->display);
368-
369- return 0; /* skip maus polling it */
370- }
371- }
372-
373- return 0;
374-}
375-
376-static MausKey keysym_to_mauskey(KeySym sym)
377-{
378- size_t i;
379-
380- if (sym >= 0x20 && sym <= 0x7E)
381- return (MausKey)sym;
382-
383- if (sym >= XK_F1 && sym <= XK_F12)
384- return MAUS_KEY_F1 + (sym - XK_F1);
385- if (sym >= XK_KP_0 && sym <= XK_KP_9)
386- return MAUS_KEY_KP_0 + (sym - XK_KP_0);
387-
388- for (i = 0; i < sizeof(keymap)/ sizeof(keymap[0]); i++) {
389- if (keymap[i].x11 == sym)
390- return keymap[i].maus;
391- }
392-
393- return MAUS_KEY_NONE;
394-}
395-
396-static MausMouseButton mouse_button_to_maus(int btn)
397-{
398- switch (btn) {
399- case Button1: return MAUS_MOUSE_BUTTON_LEFT;
400- case Button2: return MAUS_MOUSE_BUTTON_MIDDLE;
401- case Button3: return MAUS_MOUSE_BUTTON_RIGHT;
402- case Button4: return MAUS_MOUSE_BUTTON_SCROLL_UP;
403- case Button5: return MAUS_MOUSE_BUTTON_SCROLL_DOWN;
404- default: return MAUS_MOUSE_BUTTON_NONE;
405- }
406-}
407-
408-static int xerr(Display* dpy, XErrorEvent* ev)
409-{
410- (void) dpy;
411- (void) ev;
412- xerrored = 1;
413- return 0;
414-}
415-
416-void maus_clipboard_set_text(Maus* mw, const char* text)
417-{
418- MausBackend* be = &mw->backend;
419- Atom clipboard;
420-
421- if (!be->display || be->win == None)
422- return;
423-
424- /* clear old entry */
425- if (mw->clipboard) {
426- free(mw->clipboard);
427- mw->clipboard = NULL;
428- }
429-
430- if (text)
431- mw->clipboard = maus_strdup(text);
432-
433- clipboard = XInternAtom(be->display, "CLIPBOARD", False);
434- XSetSelectionOwner(be->display, clipboard, be->win, CurrentTime);
435- XFlush(be->display);
436-}
437-
438-char* maus_clipboard_get_text(Maus* mw)
439-{
440- MausBackend* be = &mw->backend;
441- Atom clipboard = XInternAtom(be->display, "CLIPBOARD", False);
442- Atom utf8_string = XInternAtom(be->display, "UTF8_STRING", False);
443- Atom maus_clipboard_prop = XInternAtom(be->display, "MAUS_CLIPBOARD_PROP", False);
444-
445- XEvent xev;
446- int8_t ok = 0;
447-
448- int timeout;
449-
450- Atom actual_type;
451- int actual_fmt;
452- unsigned long nitems;
453- unsigned long bytes_after;
454- unsigned char* prop_data = NULL;
455-
456- char* res = NULL;
457-
458- /* fetch clipboard data to `maus_clipboard_prop`
459- window property */
460- XConvertSelection(
461- be->display, clipboard, utf8_string,
462- maus_clipboard_prop, be->win, CurrentTime
463- );
464- XFlush(be->display);
465-
466- /* check for selection response */
467- for (timeout = 0; timeout < 10000; timeout++) {
468- if (XCheckTypedWindowEvent(be->display, be->win, SelectionNotify, &xev)) {
469- if (xev.xselection.property != None)
470- ok = 1;
471- break;
472- }
473- }
474- if (!ok)
475- return NULL;
476-
477- /* read string off property */
478- XGetWindowProperty(
479- be->display, be->win, maus_clipboard_prop, 0,LONG_MAX,
480- True, utf8_string, &actual_type, &actual_fmt, &nitems,
481- &bytes_after, &prop_data
482- );
483-
484- if (prop_data) {
485- res = maus_strdup((char*)prop_data);
486- XFree(prop_data);
487- }
488-
489- return res;
490-}
491-
492-void maus_close(Maus* mw)
493-{
494- MausBackend* be = &mw->backend;
495-
496- fb_destroy(mw);
497- if (mw->bfb) {
498- free(mw->bfb);
499- mw->bfb = NULL;
500- }
501- if (mw->clipboard) {
502- free(mw->clipboard);
503- mw->clipboard = NULL;
504- }
505- if (be->win != None) {
506- (void) maus_close_window(mw);
507- }
508- if (be->display)
509- XCloseDisplay(be->display);
510-}
511-
512-int8_t maus_close_window(Maus* mw)
513-{
514- MausBackend* be = &mw->backend;
515-
516- if (be->gc) {
517- XFreeGC(be->display, be->gc);
518- be->gc = 0;
519- }
520-
521- if (be->win != None) {
522- XUnmapWindow(be->display, be->win);
523- XDestroyWindow(be->display, be->win);
524- }
525-
526- return 1;
527-}
528-
529-int8_t maus_create_window(Maus* mw)
530-{
531- MausBackend* be = &mw->backend;
532- Display* dpy = be->display;
533- Window* win = &be->win;
534-
535- *win = XCreateSimpleWindow(
536- dpy, be->root,
537- mw->x, mw->y,
538- mw->width, mw->height,
539- 0u, 0u, 0u
540- );
541-
542- if (*win == None)
543- return 0;
544-
545- XSelectInput(dpy, *win,
546- ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
547- ButtonReleaseMask | PointerMotionMask | StructureNotifyMask
548- );
549-
550- /* no black flashing when resizing */
551- XSetWindowBackgroundPixmap(dpy, *win, None);
552-
553- /* atoms */
554- be->atoms[MAUS_ATOM_WM_DELETE_WINDOW] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
555-
556- XSetWMProtocols(dpy, *win, &be->atoms[MAUS_ATOM_WM_DELETE_WINDOW], 1);
557- XStoreName(dpy, *win, mw->title);
558-
559- XMapWindow(dpy, *win);
560- XFlush(dpy);
561-
562- be->gc = XCreateGC(dpy, *win, 0, NULL);
563- if (!be->gc) {
564- maus_log(stderr, "failed to create window GC");
565- maus_close_window(mw);
566- return 0;
567- }
568-
569- return 1;
570-}
571-
572-void maus_clear(Maus* mw, MausColor col)
573-{
574- uint32_t col_up = MAUS_UNPACK_COL(col);
575- uint32_t pxs = mw->height * mw->width;
576- uint32_t i;
577- for (i = 0; i < pxs; i++)
578- mw->bfb[i] = col_up;
579-}
580-
581-Maus* maus_init(const char* title, int x, int y, int width, int height)
582-{
583- Display* d = XOpenDisplay(NULL);
584- Maus* mw = calloc(1, sizeof(Maus));
585- MausBackend* be = &mw->backend;
586-
587- if (MAUS_WARN_BACKEND_AUTO_SEL)
588- maus_log(stderr, "backend auto-selected: X11");
589-
590- if (!d) {
591- maus_die("failed to open X11 display");
592- return NULL;
593- }
594-
595- be->display = d;
596- be->root = DefaultRootWindow(d);
597- be->win = None;
598- be->cur_rel = 0;
599- be->ignore_warp = 0;
600- be->mouse_x = 0;
601- be->mouse_y = 0;
602- be->mouse_pos_set = 0;
603-
604- mw->frame_time_last = maus_get_time_ns();
605- mw->title = title;
606- mw->width = width;
607- mw->height = height;
608- mw->x = x;
609- mw->y = y;
610- mw->fb = NULL;
611-
612- be->gc = 0;
613- be->image = NULL;
614- be->shmat = 0;
615- be->shm.shmid = -1;
616- be->shm.shmaddr = NULL;
617- if (!fb_create(mw)) {
618- maus_log(stderr, "failed to create framebuffer");
619- maus_close(mw);
620- free(mw);
621- return NULL;
622- }
623- mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
624- if (!mw->bfb) {
625- maus_log(stderr, "failed to allocate back buffer");
626- maus_close(mw);
627- free(mw);
628- return NULL;
629- }
630-
631- return mw;
632-}
633-
634-int8_t maus_event_poll(Maus* mw, MausEvent* ev)
635-{
636- MausBackend* be = &mw->backend;
637- XEvent xev;
638-
639- while (XPending(be->display)) {
640- XNextEvent(be->display, &xev);
641- ev->type = MAUS_EV_NONE;
642- if (handle_event(&xev, ev, mw))
643- return 1;
644-
645- }
646-
647- return 0;
648-}
649-
650-void maus_event_wait(Maus* mw, MausEvent* ev)
651-{
652- MausBackend* be = &mw->backend;
653- XEvent xev;
654-
655- for (;;) {
656- XNextEvent(be->display, &xev);
657- ev->type = MAUS_EV_NONE;
658- if (handle_event(&xev, ev, mw))
659- return;
660- }
661-}
662-
663-void maus_present(Maus* mw)
664-{
665- MausBackend* be = &mw->backend;
666- uint32_t bytes;
667-
668- if (!be->image || be->win == None)
669- return;
670-
671- bytes = mw->stride * mw->height * sizeof(uint32_t);
672- memcpy(mw->fb, mw->bfb, bytes);
673-
674- XShmPutImage(
675- be->display, be->win, be->gc, be->image,
676- 0, 0, 0, 0, mw->width, mw->height, False
677- );
678-
679- XFlush(be->display);
680-}
681-
682-int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height)
683-{
684- MausBackend* be = &mw->backend;
685-
686- if (width == 0 || height == 0 ||
687- (mw->width == width && mw->height == height))
688- return 0;
689-
690- fb_destroy(mw);
691- if (mw->bfb) {
692- free(mw->bfb);
693- mw->bfb = NULL;
694- }
695-
696- mw->width = width;
697- mw->height = height;
698-
699- XSync(be->display, False);
700- XFlush(be->display);
701-
702- if (!fb_create(mw))
703- return 0;
704-
705- mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
706- if (!mw->bfb)
707- return 0;
708-
709- return 1;
710-}
711-
712-void maus_cur_set_mode(Maus* mw, MausCursorState state)
713-{
714- MausBackend* be = &mw->backend;
715- Display* dpy = be->display;
716- Window win = be->win;
717-
718- Mask mask;
719- int grab;
720-
721- if (!dpy) {
722- maus_log(stderr, "display is NULL");
723- return;
724- }
725- if (win == None) {
726- maus_log(stderr, "win is None");
727- return;
728- }
729-
730- /* show cursor */
731- if (state == MAUS_CURSOR_STATE_VISIBLE) {
732- XUndefineCursor(dpy, win);
733- XFlush(dpy);
734- return;
735- }
736-
737- /* hide cursor */
738- if (state == MAUS_CURSOR_STATE_HIDDEN) {
739- Pixmap blank_pm = XCreatePixmap(dpy, win, 1, 1, 1);
740- XColor black = {0, 0, 0, 0, 0, 0};
741- Cursor blank_cur = XCreatePixmapCursor(
742- dpy, blank_pm, blank_pm, &black, &black, 0, 0
743- );
744- XFreePixmap(dpy, blank_pm);
745-
746- XDefineCursor(dpy, win, blank_cur);
747- XFreeCursor(dpy, blank_cur);
748- XFlush(dpy);
749- return;
750- }
751-
752- /* lock cursor */
753- if (state == MAUS_CURSOR_STATE_LOCKED) {
754- mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
755- grab = XGrabPointer(
756- dpy, win, True, mask, GrabModeAsync,
757- GrabModeAsync, win, None, CurrentTime
758- );
759-
760- if (grab != GrabSuccess) {
761- maus_log(stderr, "failed to grab mouse pointer");
762- return;
763- }
764-
765- /* TODO keep position just snap to window dimensions */
766- XWarpPointer(dpy, None, win, 0, 0, 0, 0, mw->width/2, mw->height/2);
767- XFlush(dpy);
768- return;
769- }
770-
771- /* unlock cursor */
772- if (state == MAUS_CURSOR_STATE_FREE) {
773- XUngrabPointer(dpy, CurrentTime);
774- XFlush(dpy);
775- return;
776- }
777-
778- /* relative cursor */
779- if (state == MAUS_CURSOR_STATE_RELATIVE) {
780- mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
781- grab = XGrabPointer(
782- dpy, win, True, mask, GrabModeAsync,
783- GrabModeAsync, win, None, CurrentTime
784- );
785-
786- if (grab != GrabSuccess) {
787- maus_log(stderr, "failed to grab mouse pointer");
788- return;
789- }
790-
791- be->cur_rel = 1;
792- be->ignore_warp = 1;
793- XWarpPointer(dpy, None, win, 0, 0, 0, 0, mw->width/2, mw->height/2);
794- XFlush(dpy);
795- return;
796- }
797-
798- /* absolute cursor */
799- if (state == MAUS_CURSOR_STATE_ABSOLUTE) {
800- be->cur_rel = 0;
801- be->ignore_warp = 0;
802- XUngrabPointer(dpy, CurrentTime);
803- XFlush(dpy);
804- return;
805- }
806-}
807-
+0,
-21
1@@ -1,21 +0,0 @@
2-#include <stdlib.h>
3-#include <string.h>
4-
5-#include "utils.h"
6-
7-char* maus_strdup(const char* src)
8-{
9- size_t len;
10- char* dst;
11- if (src == NULL)
12- return NULL;
13-
14- len = strlen(src);
15- dst = malloc(len + 1);
16- if (dst == NULL)
17- return NULL;
18-
19- memcpy(dst, src, len + 1);
20- return dst;
21-}
22-
+0,
-11
1@@ -1,11 +0,0 @@
2-#ifndef UTIL_H
3-#define UTIL_H
4-
5-/* duplicate a string. returns pointer to address of
6- newly allocated string buffer. if NULL, allocation
7- failed or src is NULL
8- note: you must free this newly allocated string */
9-char* maus_strdup(const char* src);
10-
11-#endif /* UTIL_H */
12-