forked from pyrite-dev/milsko
Compare commits
19 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82319aa616 | |||
| 495ea93c74 | |||
| 0fc8b09913 | |||
| 39f44a56e3 | |||
| 247e0b361c | |||
| a932fc00ea | |||
| 0adc98a2a2 | |||
| c50e920123 | |||
| 8cbde42de3 | |||
| be2eb6483c | |||
| 749be3762b | |||
| 82626cab22 | |||
| 67df6592e7 | |||
| 37fe636c75 | |||
| 5ad21381c5 | |||
| b2ea14c354 | |||
| 43b0b86a0f | |||
| 5a9a33e873 | |||
| 843cc74c4c |
18 changed files with 1170 additions and 32 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -4,8 +4,8 @@
|
||||||
examples/*
|
examples/*
|
||||||
examples/*.exe
|
examples/*.exe
|
||||||
examples/*/*
|
examples/*/*
|
||||||
examples/*/*.exe
|
!examples/*/*.c
|
||||||
!examples/*/
|
!examples/*/*.spv
|
||||||
!examples/*.*
|
|
||||||
!examples/*/*.*
|
|
||||||
compile_flags.txt
|
compile_flags.txt
|
||||||
|
*.a
|
||||||
|
Makefile
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ MWDECL void MwLoop(MwWidget handle);
|
||||||
*/
|
*/
|
||||||
MWDECL int MwStep(MwWidget handle);
|
MWDECL int MwStep(MwWidget handle);
|
||||||
|
|
||||||
/*!
|
/*!MwStep(
|
||||||
* @brief Check if any event is pending
|
* @brief Check if any event is pending
|
||||||
* @param handle Widget
|
* @param handle Widget
|
||||||
* @return `1` if any event is pending
|
* @return `1` if any event is pending
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,15 @@ typedef void* MwLLPixmap;
|
||||||
|
|
||||||
enum MwLLBackends {
|
enum MwLLBackends {
|
||||||
MwLLBackendX11 = 0,
|
MwLLBackendX11 = 0,
|
||||||
MwLLBackendGDI
|
MwLLBackendGDI,
|
||||||
|
MwLLBackendWayland,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MwLLCommon {
|
struct _MwLLCommon {
|
||||||
void* user;
|
void* user;
|
||||||
int copy_buffer;
|
int copy_buffer;
|
||||||
int type;
|
int type;
|
||||||
|
int success;
|
||||||
|
|
||||||
MwLLHandler handler;
|
MwLLHandler handler;
|
||||||
};
|
};
|
||||||
|
|
@ -56,6 +58,9 @@ struct _MwLLCommonPixmap {
|
||||||
#ifdef USE_GDI
|
#ifdef USE_GDI
|
||||||
#include <Mw/LowLevel/GDI.h>
|
#include <Mw/LowLevel/GDI.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_WAYLAND
|
||||||
|
#include <Mw/LowLevel/Wayland.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
union _MwLL {
|
union _MwLL {
|
||||||
struct _MwLLCommon common;
|
struct _MwLLCommon common;
|
||||||
|
|
@ -65,6 +70,9 @@ union _MwLL {
|
||||||
#ifdef USE_GDI
|
#ifdef USE_GDI
|
||||||
struct _MwLLGDI gdi;
|
struct _MwLLGDI gdi;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_WAYLAND
|
||||||
|
struct _MwLLWayland wayland;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
union _MwLLColor {
|
union _MwLLColor {
|
||||||
|
|
@ -75,6 +83,9 @@ union _MwLLColor {
|
||||||
#ifdef USE_GDI
|
#ifdef USE_GDI
|
||||||
struct _MwLLGDIColor gdi;
|
struct _MwLLGDIColor gdi;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_WAYLAND
|
||||||
|
struct _MwLLWaylandColor wayland;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
union _MwLLPixmap {
|
union _MwLLPixmap {
|
||||||
|
|
@ -85,6 +96,9 @@ union _MwLLPixmap {
|
||||||
#ifdef USE_GDI
|
#ifdef USE_GDI
|
||||||
struct _MwLLGDIPixmap gdi;
|
struct _MwLLGDIPixmap gdi;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_WAYLAND
|
||||||
|
struct _MwLLWaylandPixmap wayland;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#include <Mw/TypeDefs.h>
|
#include <Mw/TypeDefs.h>
|
||||||
|
|
@ -150,6 +164,7 @@ MWDECL void (*MwLLDestroy)(MwLL handle);
|
||||||
|
|
||||||
MWDECL void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color);
|
MWDECL void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color);
|
||||||
MWDECL void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color);
|
MWDECL void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color);
|
||||||
|
MWDECL void (*MwLLEndDraw)(MwLL handle);
|
||||||
|
|
||||||
MWDECL MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b);
|
MWDECL MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b);
|
||||||
MWDECL void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b);
|
MWDECL void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b);
|
||||||
|
|
@ -184,8 +199,6 @@ MWDECL void (*MwLLMakePopup)(MwLL handle, MwLL parent);
|
||||||
MWDECL void (*MwLLBeginStateChange)(MwLL handle);
|
MWDECL void (*MwLLBeginStateChange)(MwLL handle);
|
||||||
MWDECL void (*MwLLEndStateChange)(MwLL handle);
|
MWDECL void (*MwLLEndStateChange)(MwLL handle);
|
||||||
|
|
||||||
MWDECL void (*MwLLSetBackground)(MwLL handle, MwLLColor color);
|
|
||||||
|
|
||||||
MWDECL void (*MwLLFocus)(MwLL handle);
|
MWDECL void (*MwLLFocus)(MwLL handle);
|
||||||
MWDECL void (*MwLLGrabPointer)(MwLL handle, int toggle);
|
MWDECL void (*MwLLGrabPointer)(MwLL handle, int toggle);
|
||||||
|
|
||||||
|
|
|
||||||
110
include/Mw/LowLevel/Wayland.h
Normal file
110
include/Mw/LowLevel/Wayland.h
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/*!
|
||||||
|
* @file Mw/LowLevel/Wayland.h
|
||||||
|
* @brief Wayland Backend
|
||||||
|
* @warning This is used internally
|
||||||
|
*/
|
||||||
|
#ifndef __MW_LOWLEVEL_WAYLAND_H__
|
||||||
|
#define __MW_LOWLEVEL_WAYLAND_H__
|
||||||
|
|
||||||
|
#include "Mw/BaseTypes.h"
|
||||||
|
#include <Mw/MachDep.h>
|
||||||
|
#include <Mw/TypeDefs.h>
|
||||||
|
#include <Mw/LowLevel.h>
|
||||||
|
|
||||||
|
#include <wayland-egl.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glext.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
MWDECL int MwLLWaylandCallInit(void);
|
||||||
|
|
||||||
|
#ifndef WL_PROTOCOLS_DEFINED
|
||||||
|
#define WL_PROTOCOLS_DEFINED
|
||||||
|
#include "Wayland/xdg-shell-client-protocol.h"
|
||||||
|
#include "Wayland/xdg-decoration-client-protocol.h"
|
||||||
|
#include "Wayland/cursor-shape-client-protocol.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct wayland_protocol {
|
||||||
|
void* listener;
|
||||||
|
void* context;
|
||||||
|
} wayland_protocol_t;
|
||||||
|
|
||||||
|
typedef wayland_protocol_t*(wl_setup_func)(MwU32, struct _MwLLWayland*);
|
||||||
|
|
||||||
|
struct _MwLLWaylandTopLevel {
|
||||||
|
struct xdg_surface* xdg_surface;
|
||||||
|
struct xdg_toplevel* xdg_top_level;
|
||||||
|
struct xdg_toplevel_listener xdg_toplevel_listener;
|
||||||
|
struct xdg_surface_listener xdg_surface_listener;
|
||||||
|
|
||||||
|
struct xkb_context* xkb_context;
|
||||||
|
|
||||||
|
MwBool running;
|
||||||
|
MwBool compositor_created;
|
||||||
|
MwBool xdg_wm_base_created;
|
||||||
|
MwBool xdg_surface_created;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MwLLWayland {
|
||||||
|
struct _MwLLCommon common;
|
||||||
|
union {
|
||||||
|
struct _MwLLWaylandTopLevel* toplevel;
|
||||||
|
struct wl_subsurface* subsurface;
|
||||||
|
};
|
||||||
|
enum {
|
||||||
|
MWLL_WAYLAND_TOPLEVEL = 0,
|
||||||
|
MWLL_WAYLAND_SUBSURFACE = 1,
|
||||||
|
} type;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const char* key;
|
||||||
|
wl_setup_func* value;
|
||||||
|
}* wl_protocol_setup_map;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const char* key;
|
||||||
|
wayland_protocol_t* value;
|
||||||
|
}* wl_protocol_map;
|
||||||
|
|
||||||
|
struct wl_display* display;
|
||||||
|
struct wl_registry* registry;
|
||||||
|
struct wl_compositor* compositor;
|
||||||
|
struct wl_subcompositor* subcompositor;
|
||||||
|
struct wl_surface* surface;
|
||||||
|
struct wl_shm* shm;
|
||||||
|
struct wl_registry_listener registry_listener;
|
||||||
|
|
||||||
|
MwBool configured;
|
||||||
|
MwBool force_redraw;
|
||||||
|
MwBool egl_setup;
|
||||||
|
MwBool egl_do_resetup;
|
||||||
|
MwU32 x, y, ww, wh;
|
||||||
|
int z_index;
|
||||||
|
|
||||||
|
MwLL parent;
|
||||||
|
|
||||||
|
GLuint fbo;
|
||||||
|
unsigned int fbo_texture;
|
||||||
|
|
||||||
|
EGLNativeWindowType egl_window_native;
|
||||||
|
EGLDisplay egl_display;
|
||||||
|
EGLContext egl_context;
|
||||||
|
EGLSurface egl_surface;
|
||||||
|
EGLConfig egl_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MwLLWaylandColor {
|
||||||
|
struct _MwLLCommonColor common;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MwLLWaylandPixmap {
|
||||||
|
struct _MwLLCommonPixmap common;
|
||||||
|
GLuint texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
1
include/Mw/LowLevel/Wayland/.gitignore
vendored
Normal file
1
include/Mw/LowLevel/Wayland/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*protocol.h
|
||||||
1
include/Mw/LowLevel/Wayland/README.md
Normal file
1
include/Mw/LowLevel/Wayland/README.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Folder for wayland-scanner to place any of its files.
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
# $Id$
|
# $Id$
|
||||||
|
|
||||||
|
if(system("wayland-scanner -v >/dev/null 2>&1") == 0){
|
||||||
|
use_backend("wayland", "x11");
|
||||||
|
} else {
|
||||||
use_backend("x11");
|
use_backend("x11");
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
||||||
13
pl/rules.pl
13
pl/rules.pl
|
|
@ -27,6 +27,19 @@ if (grep(/^gdi$/, @backends)) {
|
||||||
$gl_libs = "-lopengl32 -lglu32";
|
$gl_libs = "-lopengl32 -lglu32";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (grep(/^wayland$/, @backends)) {
|
||||||
|
add_cflags("-DUSE_WAYLAND");
|
||||||
|
new_object("src/backend/wayland.c");
|
||||||
|
add_libs("-lGL -lEGL -lwayland-egl -lwayland-client -lxkbcommon");
|
||||||
|
|
||||||
|
scan_wayland_protocol("stable", "xdg-shell","");
|
||||||
|
scan_wayland_protocol("stable", "tablet","-v2");
|
||||||
|
scan_wayland_protocol("staging", "cursor-shape","-v1");
|
||||||
|
scan_wayland_protocol("unstable", "xdg-decoration","-unstable-v1");
|
||||||
|
|
||||||
|
$gl_libs = "-lGL -lGLU";
|
||||||
|
}
|
||||||
|
|
||||||
if (param_get("stb-image")) {
|
if (param_get("stb-image")) {
|
||||||
add_cflags("-DUSE_STB_IMAGE");
|
add_cflags("-DUSE_STB_IMAGE");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
pl/utils.pl
17
pl/utils.pl
|
|
@ -55,6 +55,23 @@ sub use_backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub scan_wayland_protocol {
|
||||||
|
my $tier = $_[0];
|
||||||
|
my $proto = $_[1];
|
||||||
|
my $ver = $_[2];
|
||||||
|
|
||||||
|
my $proto_c = "src/backend/wayland-${proto}-protocol.c";
|
||||||
|
|
||||||
|
if(system("wayland-scanner private-code /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml ${proto_c}") != 0) {
|
||||||
|
print("^ Error on getting private code for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n");
|
||||||
|
} else {
|
||||||
|
new_object($proto_c);
|
||||||
|
};
|
||||||
|
if(system("wayland-scanner client-header /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml include/Mw/LowLevel/Wayland/${proto}-client-protocol.h")) {
|
||||||
|
print("^ Error on getting client header for /usr/share/wayland-protocols/${tier}/${proto}/${proto}${ver}.xml\n");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
our %params = ();
|
our %params = ();
|
||||||
|
|
||||||
sub param_set {
|
sub param_set {
|
||||||
|
|
|
||||||
1
src/backend/.gitignore
vendored
Normal file
1
src/backend/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
wayland*protocol.c
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
\
|
\
|
||||||
MwLLPolygon = MwLLPolygonImpl; \
|
MwLLPolygon = MwLLPolygonImpl; \
|
||||||
MwLLLine = MwLLLineImpl; \
|
MwLLLine = MwLLLineImpl; \
|
||||||
|
MwLLEndDraw = MwLLEndDrawImpl; \
|
||||||
\
|
\
|
||||||
MwLLAllocColor = MwLLAllocColorImpl; \
|
MwLLAllocColor = MwLLAllocColorImpl; \
|
||||||
MwLLColorUpdate = MwLLColorUpdateImpl; \
|
MwLLColorUpdate = MwLLColorUpdateImpl; \
|
||||||
|
|
@ -44,8 +45,6 @@
|
||||||
\
|
\
|
||||||
MwLLBeginStateChange = MwLLBeginStateChangeImpl; \
|
MwLLBeginStateChange = MwLLBeginStateChangeImpl; \
|
||||||
MwLLEndStateChange = MwLLEndStateChangeImpl; \
|
MwLLEndStateChange = MwLLEndStateChangeImpl; \
|
||||||
\
|
|
||||||
MwLLSetBackground = MwLLSetBackgroundImpl; \
|
|
||||||
\
|
\
|
||||||
MwLLFocus = MwLLFocusImpl; \
|
MwLLFocus = MwLLFocusImpl; \
|
||||||
MwLLGrabPointer = MwLLGrabPointerImpl; \
|
MwLLGrabPointer = MwLLGrabPointerImpl; \
|
||||||
|
|
|
||||||
|
|
@ -278,6 +278,8 @@ static void MwLLDestroyImpl(MwLL handle) {
|
||||||
free(handle);
|
free(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void MwLLEndDrawImpl(MwLL handle) {}
|
||||||
|
|
||||||
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
|
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
|
||||||
POINT* p = malloc(sizeof(*p) * points_count);
|
POINT* p = malloc(sizeof(*p) * points_count);
|
||||||
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
|
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
|
||||||
|
|
@ -342,11 +344,6 @@ static void MwLLFreeColorImpl(MwLLColor color) {
|
||||||
free(color);
|
free(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) {
|
|
||||||
(void)handle;
|
|
||||||
(void)color;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
|
static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
|
||||||
RECT rc;
|
RECT rc;
|
||||||
|
|
||||||
|
|
|
||||||
970
src/backend/wayland.c
Normal file
970
src/backend/wayland.c
Normal file
|
|
@ -0,0 +1,970 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
// #include <GL/gl.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <Mw/Milsko.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
|
||||||
|
#include "../../external/stb_ds.h"
|
||||||
|
#include "Mw/BaseTypes.h"
|
||||||
|
#include "Mw/LowLevel.h"
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <wayland-egl-core.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
|
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
|
||||||
|
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
|
||||||
|
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
|
||||||
|
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
|
||||||
|
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
|
||||||
|
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
||||||
|
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatus;
|
||||||
|
|
||||||
|
#define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name)
|
||||||
|
|
||||||
|
static void new_protocol(void* data, struct wl_registry* registry,
|
||||||
|
MwU32 name, const char* interface,
|
||||||
|
MwU32 version) {
|
||||||
|
struct _MwLLWayland* wayland = data;
|
||||||
|
|
||||||
|
wl_setup_func* func = shget(wayland->wl_protocol_setup_map, interface);
|
||||||
|
if(func != NULL) {
|
||||||
|
// printf("registering interface %s\n", interface);
|
||||||
|
shput(wayland->wl_protocol_map, interface, func(name, data));
|
||||||
|
} else {
|
||||||
|
// printf("unknown interface %s\n", interface);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void protocol_removed(void* data,
|
||||||
|
struct wl_registry* registry,
|
||||||
|
MwU32 name) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static void wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {};
|
||||||
|
static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
|
||||||
|
MwU32 capabilities) {};
|
||||||
|
|
||||||
|
void xdg_wm_base_ping(void* data,
|
||||||
|
struct xdg_wm_base* xdg_wm_base,
|
||||||
|
MwU32 serial) {
|
||||||
|
// The compositor will send us a ping event to check that we're responsive.
|
||||||
|
// We need to send back a pong request immediately.
|
||||||
|
xdg_wm_base_pong(xdg_wm_base, serial);
|
||||||
|
};
|
||||||
|
|
||||||
|
static wayland_protocol_t* wl_seat_setup(MwU32 name, struct _MwLLWayland* wayland) {
|
||||||
|
wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
|
||||||
|
proto->listener = malloc(sizeof(struct wl_seat_listener));
|
||||||
|
|
||||||
|
((struct wl_seat_listener*)proto->listener)->name = wl_seat_name;
|
||||||
|
((struct wl_seat_listener*)proto->listener)->capabilities = wl_seat_capabilities;
|
||||||
|
|
||||||
|
proto->context = wl_registry_bind(wayland->registry, name, &wl_seat_interface, 1);
|
||||||
|
wl_seat_add_listener(proto->context, proto->listener, wayland);
|
||||||
|
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland* wayland) {
|
||||||
|
wayland->compositor = wl_registry_bind(wayland->registry, name, &wl_compositor_interface, 1);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wayland_protocol_t* wl_subcompositor_setup(MwU32 name, struct _MwLLWayland* wayland) {
|
||||||
|
wayland->subcompositor = wl_registry_bind(wayland->registry, name, &wl_subcompositor_interface, 1);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wayland_protocol_t* xdg_wm_base_setup(MwU32 name, struct _MwLLWayland* wayland) {
|
||||||
|
wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
|
||||||
|
proto->listener = malloc(sizeof(struct xdg_wm_base_listener));
|
||||||
|
|
||||||
|
((struct xdg_wm_base_listener*)proto->listener)->ping = xdg_wm_base_ping;
|
||||||
|
|
||||||
|
proto->context = wl_registry_bind(wayland->registry, name, &xdg_wm_base_interface, 1);
|
||||||
|
xdg_wm_base_add_listener(proto->context, proto->listener, wayland);
|
||||||
|
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wayland_protocol_t* wp_cursor_shape_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) {
|
||||||
|
wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
|
||||||
|
proto->listener = NULL;
|
||||||
|
|
||||||
|
proto->context = wl_registry_bind(wayland->registry, name, &wp_cursor_shape_manager_v1_interface, 1);
|
||||||
|
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct zxdg_decoration_manager_v1_context {
|
||||||
|
struct zxdg_decoration_manager_v1* manager;
|
||||||
|
// struct zxdg_decoration_toplevel_v1* toplevel;
|
||||||
|
struct zxdg_toplevel_decoration_v1* decoration;
|
||||||
|
} zxdg_decoration_manager_v1_context_t;
|
||||||
|
|
||||||
|
static wayland_protocol_t* zxdg_decoration_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) {
|
||||||
|
wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
|
||||||
|
zxdg_decoration_manager_v1_context_t* ctx = malloc(sizeof(zxdg_decoration_manager_v1_context_t));
|
||||||
|
proto->listener = NULL;
|
||||||
|
|
||||||
|
ctx->manager = wl_registry_bind(wayland->registry, name, &zxdg_decoration_manager_v1_interface, 1);
|
||||||
|
;
|
||||||
|
|
||||||
|
proto->context = ctx;
|
||||||
|
|
||||||
|
return proto;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MwBool egl_setup(MwLL self, int width, int height) {
|
||||||
|
int err;
|
||||||
|
EGLint numConfigs;
|
||||||
|
EGLint majorVersion;
|
||||||
|
EGLint minorVersion;
|
||||||
|
EGLContext context;
|
||||||
|
EGLSurface surface;
|
||||||
|
EGLint fbAttribs[] =
|
||||||
|
{
|
||||||
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||||
|
EGL_RED_SIZE, 8,
|
||||||
|
EGL_GREEN_SIZE, 8,
|
||||||
|
EGL_BLUE_SIZE, 8,
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||||
|
EGL_NONE};
|
||||||
|
EGLint contextAttribs[] = {
|
||||||
|
EGL_CONTEXT_CLIENT_VERSION, 1,
|
||||||
|
EGL_CONTEXT_MAJOR_VERSION, 1,
|
||||||
|
EGL_CONTEXT_MINOR_VERSION, 1,
|
||||||
|
EGL_NONE};
|
||||||
|
|
||||||
|
EGLDisplay display = eglGetDisplay(self->wayland.display);
|
||||||
|
if(display == EGL_NO_DISPLAY) {
|
||||||
|
printf("ERROR: eglGetDisplay, %0X\n", eglGetError());
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize EGL
|
||||||
|
if(!eglInitialize(display, &majorVersion, &minorVersion)) {
|
||||||
|
printf("ERROR: eglInitialize, %0X\n", eglGetError());
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get configs
|
||||||
|
if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) {
|
||||||
|
printf("ERROR: eglGetConfigs, %0X\n", eglGetError());
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose config
|
||||||
|
if((eglChooseConfig(display, fbAttribs, &self->wayland.egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) {
|
||||||
|
printf("ERROR: eglChooseConfig, %0X\n", eglGetError());
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->wayland.egl_window_native =
|
||||||
|
wl_egl_window_create(self->wayland.surface, width, height);
|
||||||
|
if(self->wayland.egl_window_native == EGL_NO_SURFACE) {
|
||||||
|
printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n");
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a surface
|
||||||
|
surface = eglCreateWindowSurface(display, self->wayland.egl_config, self->wayland.egl_window_native, NULL);
|
||||||
|
if(surface == EGL_NO_SURFACE) {
|
||||||
|
printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError());
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
eglBindAPI(EGL_OPENGL_API);
|
||||||
|
|
||||||
|
// Create a GL context
|
||||||
|
context = eglCreateContext(display, self->wayland.egl_config, EGL_NO_CONTEXT, contextAttribs);
|
||||||
|
if(context == EGL_NO_CONTEXT) {
|
||||||
|
printf("ERROR: eglCreateContext, %0X\n", eglGetError());
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the context current
|
||||||
|
if(!eglMakeCurrent(display, surface, surface, context)) {
|
||||||
|
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)eglGetProcAddress("glGenFramebuffers");
|
||||||
|
glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D");
|
||||||
|
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)eglGetProcAddress("glGenRenderbuffers");
|
||||||
|
// glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)eglGetProcAddress("glRenderbufferStorage");
|
||||||
|
glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)eglGetProcAddress("glFramebufferRenderbuffer");
|
||||||
|
glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)eglGetProcAddress("glBindRenderbuffer");
|
||||||
|
glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)eglGetProcAddress("glBindFramebuffer");
|
||||||
|
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)eglGetProcAddress("glCheckFramebufferStatus");
|
||||||
|
|
||||||
|
glGenTextures(1, &self->wayland.fbo_texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self->wayland.fbo_texture);
|
||||||
|
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &self->wayland.fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER_BINDING, self->wayland.fbo);
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->wayland.fbo_texture, 0);
|
||||||
|
|
||||||
|
if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
printf("Error binding framebuffer: %0X\n", err);
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER_BINDING, 0);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, width, height, 0, -1, 1);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
|
self->wayland.egl_display = display;
|
||||||
|
self->wayland.egl_surface = surface;
|
||||||
|
self->wayland.egl_context = context;
|
||||||
|
printf("EGL success\n");
|
||||||
|
return MwTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void egl_resetup(MwLL handle) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if(!handle->wayland.egl_do_resetup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!eglMakeCurrent(handle->wayland.egl_display, 0, 0, handle->wayland.egl_context)) {
|
||||||
|
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!eglDestroySurface(handle->wayland.egl_display, handle->wayland.egl_surface)) {
|
||||||
|
printf("ERROR: eglDestroySurface, %0X\n", eglGetError());
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
handle->wayland.egl_surface = eglCreateWindowSurface(handle->wayland.egl_display, handle->wayland.egl_config, handle->wayland.egl_window_native, NULL);
|
||||||
|
if(handle->wayland.egl_surface == EGL_NO_SURFACE) {
|
||||||
|
printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) {
|
||||||
|
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteTextures(1, &handle->wayland.fbo_texture);
|
||||||
|
glGenTextures(1, &handle->wayland.fbo_texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture);
|
||||||
|
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, handle->wayland.ww, handle->wayland.wh, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &handle->wayland.fbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER_BINDING, handle->wayland.fbo);
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0);
|
||||||
|
|
||||||
|
if((err = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
printf("Error binding framebuffer: %0X\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER_BINDING, 0);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1);
|
||||||
|
glViewport(0, 0, handle->wayland.ww, handle->wayland.wh);
|
||||||
|
|
||||||
|
handle->wayland.egl_do_resetup = MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xdg_toplevel_configure(void* data,
|
||||||
|
struct xdg_toplevel* xdg_toplevel,
|
||||||
|
MwI32 width, MwI32 height,
|
||||||
|
struct wl_array* states) {
|
||||||
|
MwLL self = data;
|
||||||
|
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)eglGetProcAddress("glFramebufferTexture2D");
|
||||||
|
|
||||||
|
if(width == 0 || height == 0) {
|
||||||
|
width = self->wayland.ww;
|
||||||
|
height = self->wayland.wh;
|
||||||
|
// if it's still 0 then bail
|
||||||
|
if(width == 0 || height == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self->wayland.ww = width;
|
||||||
|
self->wayland.wh = height;
|
||||||
|
xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh);
|
||||||
|
|
||||||
|
MwLLSetWH(self, width, height);
|
||||||
|
MwLLDispatch(self, resize, NULL);
|
||||||
|
|
||||||
|
if(!self->wayland.egl_setup) {
|
||||||
|
self->wayland.egl_setup = egl_setup(self, width, height);
|
||||||
|
MwLLForceRender(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0);
|
||||||
|
self->wayland.egl_do_resetup = MwTRUE;
|
||||||
|
egl_resetup(self);
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void decoration_configure(
|
||||||
|
void* data, struct zxdg_toplevel_decoration_v1* zxdg_toplevel_decoration_v1,
|
||||||
|
MwU32 mode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xdg_toplevel_close(
|
||||||
|
void* data, struct xdg_toplevel* xdg_toplevel) {
|
||||||
|
MwLL self = data;
|
||||||
|
|
||||||
|
// Stop running if the user requests to close the toplevel
|
||||||
|
self->wayland.toplevel->running = MwFALSE;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void xdg_surface_configure(
|
||||||
|
void* data, struct xdg_surface* xdg_surface, MwU32 serial) {
|
||||||
|
MwLL self = data;
|
||||||
|
|
||||||
|
// The compositor configures our surface, acknowledge the configure event
|
||||||
|
xdg_surface_ack_configure(xdg_surface, serial);
|
||||||
|
|
||||||
|
if(self->wayland.configured) {
|
||||||
|
// If this isn't the first configure event we've received, we already
|
||||||
|
// have a buffer attached, so no need to do anything. Commit the
|
||||||
|
// surface to apply the configure acknowledgement.
|
||||||
|
// wl_surface_attach(self->surface, self->buffer, 0, 0);
|
||||||
|
wl_surface_commit(self->wayland.surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->wayland.configured = MwTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int event_loop(MwLL handle) {
|
||||||
|
enum {
|
||||||
|
DISPLAY_FD,
|
||||||
|
KEYREPEAT_FD,
|
||||||
|
CURSOR_FD
|
||||||
|
};
|
||||||
|
struct pollfd fd;
|
||||||
|
int timeout = 100;
|
||||||
|
struct _MwLLWayland* wayland = &handle->wayland;
|
||||||
|
|
||||||
|
if(wayland->display == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fd.fd = wl_display_get_fd(wayland->display);
|
||||||
|
fd.events = POLLIN;
|
||||||
|
|
||||||
|
/* If an error other than EAGAIN happens, we have likely been disconnected from the Wayland session */
|
||||||
|
while(wl_display_flush(wayland->display) == -1) {
|
||||||
|
if(errno != EAGAIN) {
|
||||||
|
return MwFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(poll(&fd, 1, -1) == -1) {
|
||||||
|
if(errno != EINTR && errno != EAGAIN) {
|
||||||
|
wl_display_cancel_read(wayland->display);
|
||||||
|
|
||||||
|
wayland->toplevel->running = MwFALSE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
IOI:
|
||||||
|
I took this from ioilib which I in turn adapted from SDL. I think this is meant to be required?
|
||||||
|
But doing this on my main machine causes the decorations manager to be null...? This doesn't show up on the project currently using ioilib.
|
||||||
|
Race condition? Random KDE bug? Who knows, but it seems that not polling for this works anyways (possibly because we already flush events above and then cancel reads when we actually need to close).
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
|
||||||
|
// Condition where no events are being sent.
|
||||||
|
if(!poll(&fd, 1, timeout)) {
|
||||||
|
wl_display_cancel_read(wayland->display);
|
||||||
|
// In this case, we need to commit the surface for any animations, etc.
|
||||||
|
wl_surface_commit(wayland->surface);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(fd.revents & POLLIN) {
|
||||||
|
wl_display_read_events(wayland->display);
|
||||||
|
if(wl_display_dispatch_pending(wayland->display) > 0) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(wl_display_dispatch_pending(wayland->display) == 0) {
|
||||||
|
MwLLDispatch(handle, draw, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WL_INTERFACE(interface) \
|
||||||
|
shput(wayland->wl_protocol_setup_map, interface##_interface.name, (wl_setup_func*)interface##_setup);
|
||||||
|
|
||||||
|
static void setup_callbacks(struct _MwLLWayland* wayland) {
|
||||||
|
wayland->registry_listener.global = new_protocol;
|
||||||
|
wayland->registry_listener.global_remove = protocol_removed;
|
||||||
|
wayland->wl_protocol_setup_map = NULL;
|
||||||
|
wayland->wl_protocol_map = NULL;
|
||||||
|
|
||||||
|
WL_INTERFACE(wl_compositor);
|
||||||
|
WL_INTERFACE(wl_subcompositor);
|
||||||
|
if(wayland->type == MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
WL_INTERFACE(wl_seat);
|
||||||
|
WL_INTERFACE(xdg_wm_base);
|
||||||
|
WL_INTERFACE(zxdg_decoration_manager_v1);
|
||||||
|
WL_INTERFACE(wp_cursor_shape_manager_v1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef WL_INTERFACE
|
||||||
|
|
||||||
|
static void setup_toplevel(MwLL r, int x, int y) {
|
||||||
|
int i;
|
||||||
|
struct wl_region* region;
|
||||||
|
|
||||||
|
r->wayland.type = MWLL_WAYLAND_TOPLEVEL;
|
||||||
|
r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel));
|
||||||
|
|
||||||
|
setup_callbacks(&r->wayland);
|
||||||
|
|
||||||
|
// Connect to the Wayland compositor
|
||||||
|
r->wayland.display = wl_display_connect(NULL);
|
||||||
|
if(r->wayland.display == NULL) {
|
||||||
|
printf("wayland: failed to create display\n");
|
||||||
|
r->common.success = MwFALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a roundtrip to ensure all interfaces are setup.
|
||||||
|
r->wayland.registry = wl_display_get_registry(r->wayland.display);
|
||||||
|
wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r);
|
||||||
|
if(wl_display_roundtrip(r->wayland.display) == -1) {
|
||||||
|
printf("roundtrip failed\n");
|
||||||
|
r->common.success = MwFALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Found globals: \n");
|
||||||
|
for(i = 0; i < shlen(r->wayland.wl_protocol_map); i++) {
|
||||||
|
wayland_protocol_t* proto = shget(r->wayland.wl_protocol_map, r->wayland.wl_protocol_map[i].key);
|
||||||
|
if(proto != NULL) {
|
||||||
|
printf("%s (%p)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value);
|
||||||
|
} else {
|
||||||
|
printf("%s (proto is null)\n", r->wayland.wl_protocol_map[i].key, r->wayland.wl_protocol_map[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that all globals we require are available
|
||||||
|
if(
|
||||||
|
r->wayland.compositor == NULL ||
|
||||||
|
WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context == NULL ||
|
||||||
|
WAYLAND_GET_INTERFACE(r->wayland, wl_seat)->context == NULL) {
|
||||||
|
|
||||||
|
printf("no wl_shm, wl_compositor, wl_seat, or xdg_wm_base support\n");
|
||||||
|
r->common.success = MwFALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->wayland.toplevel->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
|
||||||
|
// Create a wl_surface, a xdg_surface and a xdg_toplevel
|
||||||
|
r->wayland.surface = wl_compositor_create_surface(r->wayland.compositor);
|
||||||
|
r->wayland.toplevel->xdg_surface =
|
||||||
|
xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.surface);
|
||||||
|
r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface);
|
||||||
|
|
||||||
|
// setup mandatory listeners
|
||||||
|
r->wayland.toplevel->xdg_surface_listener.configure = xdg_surface_configure;
|
||||||
|
|
||||||
|
r->wayland.toplevel->xdg_toplevel_listener.configure = xdg_toplevel_configure;
|
||||||
|
r->wayland.toplevel->xdg_toplevel_listener.close = xdg_toplevel_close;
|
||||||
|
|
||||||
|
xdg_surface_add_listener(r->wayland.toplevel->xdg_surface, &r->wayland.toplevel->xdg_surface_listener, r);
|
||||||
|
xdg_toplevel_add_listener(r->wayland.toplevel->xdg_top_level, &r->wayland.toplevel->xdg_toplevel_listener,
|
||||||
|
r);
|
||||||
|
|
||||||
|
xdg_toplevel_set_title(r->wayland.toplevel->xdg_top_level, "Milsko Wayland App");
|
||||||
|
xdg_toplevel_set_app_id(r->wayland.toplevel->xdg_top_level, "MilskoWaylandApp");
|
||||||
|
|
||||||
|
// Perform the initial commit and wait for the first configure event
|
||||||
|
region = wl_compositor_create_region(r->wayland.compositor);
|
||||||
|
wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh);
|
||||||
|
wl_surface_set_opaque_region(r->wayland.surface, region);
|
||||||
|
wl_surface_commit(r->wayland.surface);
|
||||||
|
event_loop(r);
|
||||||
|
wl_region_destroy(region);
|
||||||
|
|
||||||
|
// setup decorations if we can
|
||||||
|
if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) {
|
||||||
|
zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context;
|
||||||
|
|
||||||
|
dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||||
|
dec->manager, r->wayland.toplevel->xdg_top_level);
|
||||||
|
|
||||||
|
zxdg_toplevel_decoration_v1_set_mode(
|
||||||
|
dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||||
|
} else {
|
||||||
|
printf("zxdg null\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// buffer_setup(&r->wayland);
|
||||||
|
|
||||||
|
// glGenBuffers(1, &vertex_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_subsurface(MwLL parent, MwLL r, int x, int y) {
|
||||||
|
struct wl_compositor* compositor = parent->wayland.compositor;
|
||||||
|
struct wl_subcompositor* subcompositor = parent->wayland.subcompositor;
|
||||||
|
struct wl_surface* parent_surface = parent->wayland.surface;
|
||||||
|
MwLL topmost_parent = parent;
|
||||||
|
struct wl_region* region;
|
||||||
|
|
||||||
|
while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
topmost_parent = topmost_parent->wayland.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->wayland.type = MWLL_WAYLAND_SUBSURFACE;
|
||||||
|
|
||||||
|
r->wayland.display = parent->wayland.display;
|
||||||
|
|
||||||
|
r->wayland.surface = wl_compositor_create_surface(compositor);
|
||||||
|
|
||||||
|
region = wl_compositor_create_region(compositor);
|
||||||
|
wl_region_add(region, 0, 0, r->wayland.ww, r->wayland.wh);
|
||||||
|
wl_surface_set_opaque_region(r->wayland.surface, region);
|
||||||
|
wl_surface_commit(r->wayland.surface);
|
||||||
|
event_loop(r);
|
||||||
|
wl_region_destroy(region);
|
||||||
|
|
||||||
|
r->wayland.subsurface = wl_subcompositor_get_subsurface(subcompositor, r->wayland.surface, parent_surface);
|
||||||
|
|
||||||
|
wl_subsurface_set_position(r->wayland.subsurface, x, y);
|
||||||
|
|
||||||
|
// printf("position %d %d\n", x, y);
|
||||||
|
|
||||||
|
setup_callbacks(&r->wayland);
|
||||||
|
|
||||||
|
r->wayland.registry = wl_display_get_registry(topmost_parent->wayland.display);
|
||||||
|
r->wayland.display = topmost_parent->wayland.display;
|
||||||
|
|
||||||
|
wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r);
|
||||||
|
if(wl_display_roundtrip(r->wayland.display) == -1) {
|
||||||
|
printf("roundtrip failed\n");
|
||||||
|
raise(SIGTRAP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrpush(parent->wayland.subsurfaces, r);
|
||||||
|
|
||||||
|
r->wayland.configured = MwTRUE;
|
||||||
|
|
||||||
|
r->wayland.egl_context = topmost_parent->wayland.egl_context;
|
||||||
|
r->wayland.egl_display = topmost_parent->wayland.egl_display;
|
||||||
|
r->wayland.egl_surface = topmost_parent->wayland.egl_surface;
|
||||||
|
r->wayland.fbo = topmost_parent->wayland.fbo;
|
||||||
|
r->wayland.fbo_texture = topmost_parent->wayland.fbo_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void framebuffer_action_begin(MwLL handle) {
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, handle->wayland.fbo);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle->wayland.fbo_texture, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void framebuffer_action_end(MwLL handle) {
|
||||||
|
glFinish();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
|
||||||
|
MwLL r;
|
||||||
|
r = malloc(sizeof(*r));
|
||||||
|
MwLLCreateCommon(r);
|
||||||
|
|
||||||
|
r->common.type = MwLLBackendWayland;
|
||||||
|
|
||||||
|
if(width == 0) width = 1;
|
||||||
|
if(height == 0) height = 1;
|
||||||
|
|
||||||
|
r->wayland.ww = width;
|
||||||
|
r->wayland.wh = height;
|
||||||
|
printf("%d %d\n", x, y);
|
||||||
|
|
||||||
|
r->wayland.parent = parent;
|
||||||
|
|
||||||
|
r->wayland.force_redraw = MwFALSE;
|
||||||
|
r->common.success = MwTRUE;
|
||||||
|
|
||||||
|
r->wayland.x = x;
|
||||||
|
r->wayland.y = y;
|
||||||
|
if(parent == NULL) {
|
||||||
|
setup_toplevel(r, x, y);
|
||||||
|
} else {
|
||||||
|
setup_subsurface(parent, r, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLDestroyImpl(MwLL handle) {
|
||||||
|
MwLLDestroyCommon(handle);
|
||||||
|
|
||||||
|
free(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
|
||||||
|
*x = handle->wayland.x;
|
||||||
|
*y = handle->wayland.y;
|
||||||
|
*w = handle->wayland.ww;
|
||||||
|
*h = handle->wayland.wh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLSetXYImpl(MwLL handle, int x, int y) {
|
||||||
|
if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
handle->wayland.x = x;
|
||||||
|
handle->wayland.y = y;
|
||||||
|
wl_subsurface_set_position(handle->wayland.subsurface, x, y);
|
||||||
|
MwLLForceRender(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLSetWHImpl(MwLL handle, int w, int h) {
|
||||||
|
/* Prevent an integer underflow when the w/h is too low */
|
||||||
|
if((w < 10 || h < 10)) {
|
||||||
|
handle->wayland.ww = 10;
|
||||||
|
handle->wayland.wh = 10;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handle->wayland.ww = w;
|
||||||
|
handle->wayland.wh = h;
|
||||||
|
|
||||||
|
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
|
||||||
|
int i, n;
|
||||||
|
float maxX = 0, maxY = 0;
|
||||||
|
float centerX, centerY;
|
||||||
|
|
||||||
|
glLineWidth(5);
|
||||||
|
|
||||||
|
if(points_count > 3) {
|
||||||
|
/* To avoid having to do a real triangulation algorithim:
|
||||||
|
1.) loop through the points once to determine the bounds of the polygon
|
||||||
|
2.) calculate the center of the polygon
|
||||||
|
|
||||||
|
*/
|
||||||
|
for(i = 0; i < points_count; i++) {
|
||||||
|
float x = round(handle->wayland.x) + round(points[i].x);
|
||||||
|
float y = round(handle->wayland.y) + round(points[i].y);
|
||||||
|
if(x >= maxX) {
|
||||||
|
maxX = x;
|
||||||
|
}
|
||||||
|
if(y >= maxY) {
|
||||||
|
maxY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
centerX = (handle->wayland.x + maxX / 2);
|
||||||
|
centerY = (handle->wayland.y + maxY / 2);
|
||||||
|
|
||||||
|
/* Efficient? No. But at the end of the day it's still not that many polygons, and if a computer can't handle 12 polygons over 6 then it should not be using Wayland anyways */
|
||||||
|
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
framebuffer_action_begin(handle);
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
for(i = 0; i < points_count; i++) {
|
||||||
|
float x = round(handle->wayland.x) + round(points[i].x);
|
||||||
|
float y = round(handle->wayland.y) + round(points[i].y);
|
||||||
|
|
||||||
|
glColor3f(color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0);
|
||||||
|
|
||||||
|
glVertex2f(x, y);
|
||||||
|
if(points_count > 4) {
|
||||||
|
glVertex2f(maxX, maxY);
|
||||||
|
glVertex2f(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
|
framebuffer_action_end(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLEndDrawImpl(MwLL handle) {
|
||||||
|
int w, h;
|
||||||
|
|
||||||
|
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
w = handle->wayland.ww;
|
||||||
|
h = handle->wayland.wh;
|
||||||
|
} else {
|
||||||
|
MwLL parent = handle->wayland.parent;
|
||||||
|
w = parent->wayland.ww;
|
||||||
|
h = parent->wayland.wh;
|
||||||
|
}
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glClearColor(1.0, 0, 0, 1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, handle->wayland.fbo_texture);
|
||||||
|
|
||||||
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0.0f, 1);
|
||||||
|
glVertex2f(0, 0);
|
||||||
|
glTexCoord2f(1, 1);
|
||||||
|
glVertex2f(w, 0);
|
||||||
|
glTexCoord2f(1, 0.0f);
|
||||||
|
glVertex2f(w, h);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex2f(0, h);
|
||||||
|
glEnd();
|
||||||
|
glFinish();
|
||||||
|
|
||||||
|
wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
|
||||||
|
if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) {
|
||||||
|
printf("error swapping buffers! %0X\n", eglGetError());
|
||||||
|
} else {
|
||||||
|
wl_surface_commit(handle->wayland.surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) {
|
||||||
|
MwLLColor c = malloc(sizeof(*c));
|
||||||
|
|
||||||
|
c->common.red = r;
|
||||||
|
c->common.blue = b;
|
||||||
|
c->common.green = g;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLColorUpdateImpl(MwLL handle, MwLLColor c, int r, int g, int b) {
|
||||||
|
c->common.red = r;
|
||||||
|
c->common.blue = b;
|
||||||
|
c->common.green = g;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLFreeColorImpl(MwLLColor color) {
|
||||||
|
free(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int MwLLPendingImpl(MwLL handle) {
|
||||||
|
return event_loop(handle) || handle->wayland.force_redraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLNextEventImpl(MwLL handle) {
|
||||||
|
MwBool render = handle->wayland.force_redraw;
|
||||||
|
|
||||||
|
if(render) {
|
||||||
|
int x, y;
|
||||||
|
unsigned int w, h;
|
||||||
|
|
||||||
|
MwLLGetXYWH(handle, &x, &y, &w, &h);
|
||||||
|
|
||||||
|
MwLLDispatch(handle, draw, NULL);
|
||||||
|
handle->wayland.force_redraw = MwFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLSetTitleImpl(MwLL handle, const char* title) {
|
||||||
|
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MwLLPixmap MwLLCreatePixmapImpl(MwLL handle, unsigned char* data, int width, int height) {
|
||||||
|
MwLLPixmap r = malloc(sizeof(*r));
|
||||||
|
|
||||||
|
r->common.width = width;
|
||||||
|
r->common.height = height;
|
||||||
|
r->common.raw = data;
|
||||||
|
r->wayland.texture = 0;
|
||||||
|
|
||||||
|
glGenTextures(1, &r->wayland.texture);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, r->wayland.texture);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
MwLLPixmapUpdate(r);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLPixmapUpdateImpl(MwLLPixmap r) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, r->wayland.texture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r->common.width, r->common.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, r->common.raw);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) {
|
||||||
|
glDeleteTextures(1, &pixmap->wayland.texture);
|
||||||
|
free(pixmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
|
||||||
|
int x, y;
|
||||||
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
x = handle->wayland.x + rect->x;
|
||||||
|
y = handle->wayland.y + rect->y;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, pixmap->wayland.texture);
|
||||||
|
glActiveTexture(pixmap->wayland.texture);
|
||||||
|
|
||||||
|
framebuffer_action_begin(handle);
|
||||||
|
// glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glColor3f(1, 1, 1);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0.0f, 0);
|
||||||
|
glVertex2f(x, y);
|
||||||
|
glTexCoord2f(1, 0);
|
||||||
|
glVertex2f(x + rect->width, y);
|
||||||
|
glTexCoord2f(1, 1);
|
||||||
|
glVertex2f(x + rect->width, y + rect->height);
|
||||||
|
glTexCoord2f(0.0f, 1);
|
||||||
|
glVertex2f(x, y + rect->height);
|
||||||
|
glEnd();
|
||||||
|
glFinish();
|
||||||
|
framebuffer_action_end(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLForceRenderImpl(MwLL handle) {
|
||||||
|
wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
|
||||||
|
|
||||||
|
wl_surface_commit(handle->wayland.surface);
|
||||||
|
|
||||||
|
handle->wayland.force_redraw = MwTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLDetachImpl(MwLL handle, MwPoint* point) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLShowImpl(MwLL handle, int show) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLMakePopupImpl(MwLL handle, MwLL parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLSetSizeHintsImpl(MwLL handle, int minx, int miny, int maxx, int maxy) {
|
||||||
|
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
xdg_toplevel_set_min_size(handle->wayland.toplevel->xdg_top_level, minx, miny);
|
||||||
|
xdg_toplevel_set_max_size(handle->wayland.toplevel->xdg_top_level, maxx, maxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLMakeBorderlessImpl(MwLL handle, int toggle) {
|
||||||
|
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
|
||||||
|
if(WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context != NULL) {
|
||||||
|
zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(handle->wayland, zxdg_decoration_manager_v1)->context;
|
||||||
|
|
||||||
|
dec->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||||
|
dec->manager, handle->wayland.toplevel->xdg_top_level);
|
||||||
|
|
||||||
|
zxdg_toplevel_decoration_v1_set_mode(
|
||||||
|
dec->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
|
||||||
|
} else {
|
||||||
|
// TODO: hide our custom window decorations when we have them.
|
||||||
|
printf("zxdg null\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLFocusImpl(MwLL handle) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* MwLLGetClipboardImpl(MwLL handle) {
|
||||||
|
char* r = NULL;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLMakeToolWindowImpl(MwLL handle) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLGetCursorCoordImpl(MwLL handle, MwPoint* point) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLBeginStateChangeImpl(MwLL handle) {
|
||||||
|
MwLLShow(handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MwLLEndStateChangeImpl(MwLL handle) {
|
||||||
|
MwLLShow(handle, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int MwLLWaylandCallInitImpl(void) {
|
||||||
|
#ifdef __linux__
|
||||||
|
if(strcmp(getenv("XDG_SESSION_TYPE"), "wayland")) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "call.c"
|
||||||
|
CALL(Wayland);
|
||||||
|
|
@ -256,6 +256,8 @@ static void MwLLDestroyImpl(MwLL handle) {
|
||||||
free(handle);
|
free(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void MwLLEndDrawImpl(MwLL handle) {}
|
||||||
|
|
||||||
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
|
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLLColor color) {
|
||||||
int i;
|
int i;
|
||||||
XPoint* p = malloc(sizeof(*p) * points_count);
|
XPoint* p = malloc(sizeof(*p) * points_count);
|
||||||
|
|
@ -395,10 +397,6 @@ static void MwLLFreeColorImpl(MwLLColor color) {
|
||||||
free(color);
|
free(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLSetBackgroundImpl(MwLL handle, MwLLColor color) {
|
|
||||||
XSetWindowBackground(handle->x11.display, handle->x11.window, color->x11.pixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int MwLLPendingImpl(MwLL handle) {
|
static int MwLLPendingImpl(MwLL handle) {
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
if(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
|
if(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) {
|
||||||
|
|
@ -1019,7 +1017,6 @@ static void MwLLEndStateChangeImpl(MwLL handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MwLLX11CallInitImpl(void) {
|
static int MwLLX11CallInitImpl(void) {
|
||||||
/* TODO: check properly */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
23
src/core.c
23
src/core.c
|
|
@ -1,10 +1,13 @@
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
#include <Mw/Milsko.h>
|
#include <Mw/Milsko.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
#include "../external/stb_ds.h"
|
#include "../external/stb_ds.h"
|
||||||
|
#include "Mw/LowLevel.h"
|
||||||
|
|
||||||
static void lldrawhandler(MwLL handle, void* data) {
|
static void lldrawhandler(MwLL handle, void* data) {
|
||||||
MwWidget h = (MwWidget)handle->common.user;
|
MwWidget h = (MwWidget)handle->common.user;
|
||||||
|
int ind;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
|
|
@ -12,6 +15,12 @@ static void lldrawhandler(MwLL handle, void* data) {
|
||||||
MwDispatch(h, draw);
|
MwDispatch(h, draw);
|
||||||
if(h->draw_inject != NULL) h->draw_inject(h);
|
if(h->draw_inject != NULL) h->draw_inject(h);
|
||||||
MwDispatchUserHandler(h, MwNdrawHandler, NULL);
|
MwDispatchUserHandler(h, MwNdrawHandler, NULL);
|
||||||
|
|
||||||
|
if(h->parent == NULL) {
|
||||||
|
MwLLEndDraw(h->lowlevel);
|
||||||
|
} else if(h->parent->lowlevel == NULL) {
|
||||||
|
MwLLEndDraw(h->lowlevel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lluphandler(MwLL handle, void* data) {
|
static void lluphandler(MwLL handle, void* data) {
|
||||||
|
|
@ -295,7 +304,10 @@ int MwStep(MwWidget handle) {
|
||||||
arrfree(widgets);
|
arrfree(widgets);
|
||||||
|
|
||||||
handle->prop_event = 0;
|
handle->prop_event = 0;
|
||||||
if(handle->lowlevel != NULL && MwLLPending(handle->lowlevel)) MwLLNextEvent(handle->lowlevel);
|
|
||||||
|
if(handle->lowlevel != NULL && MwLLPending(handle->lowlevel))
|
||||||
|
MwLLNextEvent(handle->lowlevel);
|
||||||
|
|
||||||
handle->prop_event = 1;
|
handle->prop_event = 1;
|
||||||
|
|
||||||
clean_destroy_queue(handle);
|
clean_destroy_queue(handle);
|
||||||
|
|
@ -378,11 +390,7 @@ void MwSetText(MwWidget handle, const char* key, const char* value) {
|
||||||
shput(handle->text, key, v);
|
shput(handle->text, key, v);
|
||||||
}
|
}
|
||||||
if(handle->prop_event) MwDispatch3(handle, prop_change, key);
|
if(handle->prop_event) MwDispatch3(handle, prop_change, key);
|
||||||
if(strcmp(key, MwNbackground) == 0) {
|
|
||||||
MwLLColor c = MwParseColor(handle, value);
|
|
||||||
MwLLSetBackground(handle->lowlevel, c);
|
|
||||||
MwLLFreeColor(c);
|
|
||||||
}
|
|
||||||
if(strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0) {
|
if(strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0) {
|
||||||
MwForceRender(handle);
|
MwForceRender(handle);
|
||||||
}
|
}
|
||||||
|
|
@ -687,6 +695,9 @@ MwWidget MwGetParent(MwWidget handle) {
|
||||||
typedef int (*call_t)(void);
|
typedef int (*call_t)(void);
|
||||||
int MwLibraryInit(void) {
|
int MwLibraryInit(void) {
|
||||||
call_t calls[] = {
|
call_t calls[] = {
|
||||||
|
#ifdef USE_WAYLAND
|
||||||
|
MwLLWaylandCallInit,
|
||||||
|
#endif
|
||||||
#ifdef USE_X11
|
#ifdef USE_X11
|
||||||
MwLLX11CallInit,
|
MwLLX11CallInit,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
#include "Mw/LowLevel.h"
|
||||||
#include <Mw/Milsko.h>
|
#include <Mw/Milsko.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef USE_STB_IMAGE
|
#ifdef USE_STB_IMAGE
|
||||||
#include "../external/stb_image.h"
|
#include "../external/stb_image.h"
|
||||||
|
|
@ -484,6 +486,7 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert,
|
||||||
p4[2].y = rect->y + s * border;
|
p4[2].y = rect->y + s * border;
|
||||||
}
|
}
|
||||||
MwLLPolygon(handle->lowlevel, p4, 3, col);
|
MwLLPolygon(handle->lowlevel, p4, 3, col);
|
||||||
|
|
||||||
if(color != col) MwLLFreeColor(col);
|
if(color != col) MwLLFreeColor(col);
|
||||||
|
|
||||||
MwLLFreeColor(lighter);
|
MwLLFreeColor(lighter);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ void (*MwLLDestroy)(MwLL handle);
|
||||||
void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color);
|
void (*MwLLPolygon)(MwLL handle, MwPoint* points, int points_count, MwLLColor color);
|
||||||
void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color);
|
void (*MwLLLine)(MwLL handle, MwPoint* points, MwLLColor color);
|
||||||
|
|
||||||
|
void (*MwLLEndDraw)(MwLL handle);
|
||||||
|
|
||||||
MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b);
|
MwLLColor (*MwLLAllocColor)(MwLL handle, int r, int g, int b);
|
||||||
void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b);
|
void (*MwLLColorUpdate)(MwLL handle, MwLLColor c, int r, int g, int b);
|
||||||
void (*MwLLFreeColor)(MwLLColor color);
|
void (*MwLLFreeColor)(MwLLColor color);
|
||||||
|
|
@ -40,8 +42,6 @@ void (*MwLLMakePopup)(MwLL handle, MwLL parent);
|
||||||
void (*MwLLBeginStateChange)(MwLL handle);
|
void (*MwLLBeginStateChange)(MwLL handle);
|
||||||
void (*MwLLEndStateChange)(MwLL handle);
|
void (*MwLLEndStateChange)(MwLL handle);
|
||||||
|
|
||||||
void (*MwLLSetBackground)(MwLL handle, MwLLColor color);
|
|
||||||
|
|
||||||
void (*MwLLFocus)(MwLL handle);
|
void (*MwLLFocus)(MwLL handle);
|
||||||
void (*MwLLGrabPointer)(MwLL handle, int toggle);
|
void (*MwLLGrabPointer)(MwLL handle, int toggle);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue