[wayland_egl] begin hand-rolled software rendered window border
parent
2041d28ba0
commit
f56e3dedde
|
|
@ -244,7 +244,7 @@ static void
|
||||||
xdg_surface_configure(void *user_data, struct xdg_surface *xdg_surface,
|
xdg_surface_configure(void *user_data, struct xdg_surface *xdg_surface,
|
||||||
uint32_t serial){
|
uint32_t serial){
|
||||||
ctx.has_cached_config = 1;
|
ctx.has_cached_config = 1;
|
||||||
ctx.cached_config.serial = serial;
|
ctx.cached_config_serial = serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure, };
|
const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure, };
|
||||||
|
|
@ -280,10 +280,10 @@ xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.has_cached_config = 1;
|
ctx.has_cached_config = 1;
|
||||||
ctx.cached_config.initialized = 1;
|
ctx.cached_config_initialized = 1;
|
||||||
ctx.cached_config.window_width = width;
|
ctx.cached_config_window_width = width;
|
||||||
ctx.cached_config.window_height = height;
|
ctx.cached_config_window_height = height;
|
||||||
ctx.cached_config.window_state = window_state;
|
ctx.cached_config_window_state = window_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -293,30 +293,14 @@ xdg_toplevel_close(void *user_data, struct xdg_toplevel *xdg_toplevel){
|
||||||
|
|
||||||
#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
|
#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
|
||||||
static void
|
static void
|
||||||
xdg_toplevel_configure_bounds(void *user_data, struct xdg_toplevel *xdg_toplevel, int32_t w, int32_t h){
|
xdg_toplevel_configure_bounds(void *user_data, struct xdg_toplevel *xdg_toplevel,
|
||||||
// TODO(allen):
|
int32_t w, int32_t h){}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
|
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
|
||||||
static void
|
static void
|
||||||
xdg_toplevel_wm_capabilities(void *user_data,
|
xdg_toplevel_wm_capabilities(void *user_data, struct xdg_toplevel *xdg_toplevel,
|
||||||
struct xdg_toplevel *xdg_toplevel,
|
struct wl_array *capabilities){}
|
||||||
struct wl_array *capabilities){
|
|
||||||
enum xdg_toplevel_wm_capabilities *wm_cap;
|
|
||||||
|
|
||||||
ctx.wm_capabilities = 0;
|
|
||||||
|
|
||||||
wl_array_for_each(wm_cap, capabilities) {
|
|
||||||
switch (*wm_cap) {
|
|
||||||
case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU: ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_WINDOW_MENU; break;
|
|
||||||
case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE: ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MAXIMIZE; break;
|
|
||||||
case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN: ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_FULLSCREEN; break;
|
|
||||||
case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE: ctx.wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MINIMIZE; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||||
|
|
@ -425,11 +409,8 @@ border_component_reallocate(struct border_component *component, int w, int h){
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
/* get desktop settings */
|
/* get desktop settings */
|
||||||
|
desktop_settings_get_cursor_settings(&ctx.cursor_theme_name, &ctx.cursor_size);
|
||||||
ctx.color_scheme = desktop_settings_get_color_scheme();
|
ctx.color_scheme = desktop_settings_get_color_scheme();
|
||||||
if (desktop_settings_get_cursor_settings(&ctx.cursor_theme_name, &ctx.cursor_size)){
|
|
||||||
ctx.cursor_theme_name = 0;
|
|
||||||
ctx.cursor_size = 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup GTK context */
|
/* setup GTK context */
|
||||||
int gtk_init_success = 0;
|
int gtk_init_success = 0;
|
||||||
|
|
@ -476,7 +457,6 @@ int main(){
|
||||||
|
|
||||||
wl_display_flush(ctx.wl_display);
|
wl_display_flush(ctx.wl_display);
|
||||||
wl_display_dispatch(ctx.wl_display);
|
wl_display_dispatch(ctx.wl_display);
|
||||||
wl_display_roundtrip(ctx.wl_display);
|
|
||||||
|
|
||||||
if (ctx.wl_compositor == 0){
|
if (ctx.wl_compositor == 0){
|
||||||
printf("failed to get wl_compositor\n");
|
printf("failed to get wl_compositor\n");
|
||||||
|
|
@ -591,10 +571,6 @@ int main(){
|
||||||
|
|
||||||
if (ctx.wl_surface != 0){
|
if (ctx.wl_surface != 0){
|
||||||
ctx.visible = true;
|
ctx.visible = true;
|
||||||
ctx.wm_capabilities = (LIBDECOR_WM_CAPABILITIES_WINDOW_MENU |
|
|
||||||
LIBDECOR_WM_CAPABILITIES_MAXIMIZE |
|
|
||||||
LIBDECOR_WM_CAPABILITIES_FULLSCREEN |
|
|
||||||
LIBDECOR_WM_CAPABILITIES_MINIMIZE);
|
|
||||||
ctx.frame_capabilities = (LIBDECOR_ACTION_MOVE |
|
ctx.frame_capabilities = (LIBDECOR_ACTION_MOVE |
|
||||||
LIBDECOR_ACTION_RESIZE |
|
LIBDECOR_ACTION_RESIZE |
|
||||||
LIBDECOR_ACTION_MINIMIZE |
|
LIBDECOR_ACTION_MINIMIZE |
|
||||||
|
|
@ -689,8 +665,6 @@ int main(){
|
||||||
exit_loop = 1;
|
exit_loop = 1;
|
||||||
}
|
}
|
||||||
for (;!exit_loop;){
|
for (;!exit_loop;){
|
||||||
for (;g_main_context_iteration(0, 0);){}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
struct pollfd fds[1] = {0};
|
struct pollfd fds[1] = {0};
|
||||||
|
|
||||||
|
|
@ -727,6 +701,8 @@ int main(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (;g_main_context_iteration(0, 0);){}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (ctx.pointer_leave){
|
if (ctx.pointer_leave){
|
||||||
ctx.pointer_leave = 0;
|
ctx.pointer_leave = 0;
|
||||||
|
|
@ -775,13 +751,10 @@ int main(){
|
||||||
|
|
||||||
if (ctx.titlebar_gesture.state == TITLEBAR_GESTURE_STATE_BUTTON_PRESSED){
|
if (ctx.titlebar_gesture.state == TITLEBAR_GESTURE_STATE_BUTTON_PRESSED){
|
||||||
if (ctx.titlebar_gesture.first_pressed_button == BTN_LEFT){
|
if (ctx.titlebar_gesture.first_pressed_button == BTN_LEFT){
|
||||||
if (ctx.seat->pointer_x != ctx.titlebar_gesture.pressed_x ||
|
|
||||||
ctx.seat->pointer_y != ctx.titlebar_gesture.pressed_y){
|
|
||||||
xdg_toplevel_move(ctx.xdg_toplevel, ctx.seat->wl_seat, ctx.titlebar_gesture.serial);
|
xdg_toplevel_move(ctx.xdg_toplevel, ctx.seat->wl_seat, ctx.titlebar_gesture.serial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.pointer_button){
|
if (ctx.pointer_button){
|
||||||
ctx.pointer_button = 0;
|
ctx.pointer_button = 0;
|
||||||
|
|
@ -986,8 +959,8 @@ int main(){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.has_cached_config){
|
if (ctx.has_cached_config){
|
||||||
if (ctx.cached_config.initialized){
|
if (ctx.cached_config_initialized){
|
||||||
ctx.frame_window_state = ctx.cached_config.window_state;
|
ctx.frame_window_state = ctx.cached_config_window_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -998,7 +971,6 @@ int main(){
|
||||||
if (csd){
|
if (csd){
|
||||||
if (csd_show_title_from_state(ctx.frame_window_state)){
|
if (csd_show_title_from_state(ctx.frame_window_state)){
|
||||||
gtk_widget_get_preferred_height(ctx.header, 0, &csd_size.y[0]);
|
gtk_widget_get_preferred_height(ctx.header, 0, &csd_size.y[0]);
|
||||||
|
|
||||||
gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), "");
|
gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), "");
|
||||||
gtk_widget_get_preferred_width(ctx.header, 0, &csd_size_bounds.x[0]);
|
gtk_widget_get_preferred_width(ctx.header, 0, &csd_size_bounds.x[0]);
|
||||||
gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ctx.title);
|
gtk_header_bar_set_title(GTK_HEADER_BAR(ctx.header), ctx.title);
|
||||||
|
|
@ -1009,11 +981,11 @@ int main(){
|
||||||
int csd_h = csd_size.y[0] + csd_size.y[1];
|
int csd_h = csd_size.y[0] + csd_size.y[1];
|
||||||
|
|
||||||
if (ctx.has_cached_config){
|
if (ctx.has_cached_config){
|
||||||
if (ctx.cached_config.initialized &&
|
if (ctx.cached_config_initialized &&
|
||||||
ctx.cached_config.window_width != 0 &&
|
ctx.cached_config_window_width != 0 &&
|
||||||
ctx.cached_config.window_height != 0){
|
ctx.cached_config_window_height != 0){
|
||||||
ctx.w = ctx.cached_config.window_width - csd_w;
|
ctx.w = ctx.cached_config_window_width - csd_w;
|
||||||
ctx.h = ctx.cached_config.window_height - csd_h;
|
ctx.h = ctx.cached_config_window_height - csd_h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1244,9 +1216,13 @@ int main(){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.has_cached_config){
|
if (ctx.has_cached_config){
|
||||||
xdg_surface_ack_configure(ctx.xdg_surface, ctx.cached_config.serial);
|
xdg_surface_ack_configure(ctx.xdg_surface, ctx.cached_config_serial);
|
||||||
ctx.has_cached_config = 0;
|
ctx.has_cached_config = 0;
|
||||||
memset(&ctx.cached_config, 0, sizeof ctx.cached_config);
|
ctx.cached_config_initialized = 0;
|
||||||
|
ctx.cached_config_window_state = 0;
|
||||||
|
ctx.cached_config_window_width = 0;
|
||||||
|
ctx.cached_config_window_height = 0;
|
||||||
|
ctx.cached_config_serial = 0;
|
||||||
}
|
}
|
||||||
wl_surface_commit(ctx.wl_surface);
|
wl_surface_commit(ctx.wl_surface);
|
||||||
|
|
||||||
|
|
@ -1497,6 +1473,7 @@ render_shadow(cairo_t *cr, cairo_surface_t *surface,
|
||||||
}
|
}
|
||||||
|
|
||||||
//#include "os-compatibility.c"
|
//#include "os-compatibility.c"
|
||||||
|
|
||||||
#ifndef HAVE_MKOSTEMP
|
#ifndef HAVE_MKOSTEMP
|
||||||
static int
|
static int
|
||||||
set_cloexec_or_close(int fd){
|
set_cloexec_or_close(int fd){
|
||||||
|
|
@ -1521,26 +1498,6 @@ set_cloexec_or_close(int fd){
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
|
||||||
create_tmpfile_cloexec(char *tmpname){
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
#ifdef HAVE_MKOSTEMP
|
|
||||||
fd = mkostemp(tmpname, O_CLOEXEC);
|
|
||||||
if (fd >= 0){
|
|
||||||
unlink(tmpname);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
fd = mkstemp(tmpname);
|
|
||||||
fd = set_cloexec_or_close(fd);
|
|
||||||
if (fd >= 0) {
|
|
||||||
unlink(tmpname);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
os_resize_anonymous_file(int fd, off_t size){
|
os_resize_anonymous_file(int fd, off_t size){
|
||||||
#ifdef HAVE_POSIX_FALLOCATE
|
#ifdef HAVE_POSIX_FALLOCATE
|
||||||
|
|
@ -1599,7 +1556,20 @@ int os_create_anonymous_file(off_t size){
|
||||||
if (name != 0){
|
if (name != 0){
|
||||||
strcpy(name, path);
|
strcpy(name, path);
|
||||||
strcat(name, key);
|
strcat(name, key);
|
||||||
fd = create_tmpfile_cloexec(name);
|
|
||||||
|
#ifdef HAVE_MKOSTEMP
|
||||||
|
fd = mkostemp(name, O_CLOEXEC);
|
||||||
|
if (fd >= 0){
|
||||||
|
unlink(name);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
fd = mkstemp(name);
|
||||||
|
fd = set_cloexec_or_close(fd);
|
||||||
|
if (fd >= 0) {
|
||||||
|
unlink(name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1630,14 +1600,8 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface,
|
||||||
enum header_element button_type){
|
enum header_element button_type){
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation;
|
||||||
|
|
||||||
gchar *icon_name;
|
|
||||||
int scale;
|
|
||||||
GtkWidget *icon_widget;
|
|
||||||
GtkAllocation allocation_icon;
|
|
||||||
GtkIconInfo* icon_info;
|
|
||||||
|
|
||||||
double sx;
|
GtkIconInfo* icon_info;
|
||||||
double sy;
|
|
||||||
|
|
||||||
gint icon_width, icon_height;
|
gint icon_width, icon_height;
|
||||||
|
|
||||||
|
|
@ -1679,7 +1643,10 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface,
|
||||||
gtk_style_context_restore(button_style);
|
gtk_style_context_restore(button_style);
|
||||||
|
|
||||||
/* symbol */
|
/* symbol */
|
||||||
switch (button_type) {
|
gchar *icon_name = 0;
|
||||||
|
switch (button_type){
|
||||||
|
default: break;
|
||||||
|
|
||||||
case HEADER_MIN: {
|
case HEADER_MIN: {
|
||||||
icon_name = "window-minimize-symbolic";
|
icon_name = "window-minimize-symbolic";
|
||||||
}break;
|
}break;
|
||||||
|
|
@ -1693,19 +1660,16 @@ draw_header_button(cairo_t *cr, cairo_surface_t *surface,
|
||||||
case HEADER_CLOSE: {
|
case HEADER_CLOSE: {
|
||||||
icon_name = "window-close-symbolic";
|
icon_name = "window-close-symbolic";
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
default: {
|
|
||||||
icon_name = NULL;
|
|
||||||
}break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get scale */
|
/* get scale */
|
||||||
|
double sx;
|
||||||
|
double sy;
|
||||||
cairo_surface_get_device_scale(surface, &sx, &sy);
|
cairo_surface_get_device_scale(surface, &sx, &sy);
|
||||||
scale = (sx+sy)/2.0;
|
int scale = (sx + sy)/2.0;
|
||||||
|
|
||||||
/* get original icon dimensions */
|
/* get original icon dimensions */
|
||||||
icon_widget = gtk_bin_get_child(GTK_BIN(button));
|
GtkWidget *icon_widget = gtk_bin_get_child(GTK_BIN(button));
|
||||||
gtk_widget_get_allocation(icon_widget, &allocation_icon);
|
|
||||||
|
|
||||||
/* icon info */
|
/* icon info */
|
||||||
if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height)) {
|
if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height)) {
|
||||||
|
|
@ -1787,16 +1751,18 @@ edge_from_pos(int x, int y){
|
||||||
|
|
||||||
//#include "desktop-settings.c"
|
//#include "desktop-settings.c"
|
||||||
|
|
||||||
static int
|
static void
|
||||||
get_cursor_settings_from_env(char **theme, int *size){
|
get_cursor_settings_from_env(char **theme, int *size){
|
||||||
char *env_xtheme = getenv("XCURSOR_THEME");
|
char *env_xtheme = getenv("XCURSOR_THEME");
|
||||||
char *env_xsize = getenv("XCURSOR_SIZE");
|
char *env_xsize = getenv("XCURSOR_SIZE");
|
||||||
int got_theme = (env_xtheme != 0 && env_xsize != 0);
|
if (env_xtheme != 0 && env_xsize != 0){
|
||||||
if (got_theme){
|
|
||||||
*theme = strdup(env_xtheme);
|
*theme = strdup(env_xtheme);
|
||||||
*size = atoi(env_xsize);
|
*size = atoi(env_xsize);
|
||||||
}
|
}
|
||||||
return(got_theme);
|
else{
|
||||||
|
*theme = 0;
|
||||||
|
*size = 24;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_DBUS
|
#ifdef HAS_DBUS
|
||||||
|
|
@ -1851,7 +1817,7 @@ parse_type(DBusMessage *const reply, const int type, void *value){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
desktop_settings_get_cursor_settings(char **theme, int *size){
|
desktop_settings_get_cursor_settings(char **theme, int *size){
|
||||||
static const char name[] = "org.gnome.desktop.interface";
|
static const char name[] = "org.gnome.desktop.interface";
|
||||||
static const char key_theme[] = "cursor-theme";
|
static const char key_theme[] = "cursor-theme";
|
||||||
|
|
@ -1885,10 +1851,8 @@ desktop_settings_get_cursor_settings(char **theme, int *size){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!got_theme){
|
if (!got_theme){
|
||||||
got_theme = get_cursor_settings_from_env(theme, size);
|
get_cursor_settings_from_env(theme, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(got_theme);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum libdecor_color_scheme
|
enum libdecor_color_scheme
|
||||||
|
|
@ -1915,9 +1879,9 @@ desktop_settings_get_color_scheme(){
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
bool
|
void
|
||||||
desktop_settings_get_cursor_settings(char **theme, int *size){
|
desktop_settings_get_cursor_settings(char **theme, int *size){
|
||||||
return(get_cursor_settings_from_env(theme, size));
|
get_cursor_settings_from_env(theme, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
|
|
||||||
|
|
@ -122,19 +122,12 @@ enum libdecor_capabilities {
|
||||||
LIBDECOR_ACTION_CLOSE = 1 << 4,
|
LIBDECOR_ACTION_CLOSE = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum libdecor_wm_capabilities {
|
|
||||||
LIBDECOR_WM_CAPABILITIES_WINDOW_MENU = 1 << 0,
|
|
||||||
LIBDECOR_WM_CAPABILITIES_MAXIMIZE = 1 << 1,
|
|
||||||
LIBDECOR_WM_CAPABILITIES_FULLSCREEN = 1 << 2,
|
|
||||||
LIBDECOR_WM_CAPABILITIES_MINIMIZE = 1 << 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// libdecor-plugin.h
|
// libdecor-plugin.h
|
||||||
|
|
||||||
enum header_element {
|
enum header_element {
|
||||||
HEADER_NONE,
|
HEADER_NONE,
|
||||||
HEADER_FULL, /* entire header bar */
|
HEADER_FULL,
|
||||||
HEADER_TITLE, /* label */
|
HEADER_TITLE,
|
||||||
HEADER_MIN,
|
HEADER_MIN,
|
||||||
HEADER_MAX,
|
HEADER_MAX,
|
||||||
HEADER_CLOSE,
|
HEADER_CLOSE,
|
||||||
|
|
@ -179,14 +172,6 @@ struct libdecor_state {
|
||||||
int content_height;
|
int content_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct libdecor_configuration{
|
|
||||||
bool initialized;
|
|
||||||
uint32_t serial;
|
|
||||||
enum libdecor_window_state window_state;
|
|
||||||
int window_width;
|
|
||||||
int window_height;
|
|
||||||
};
|
|
||||||
|
|
||||||
// #include "desktop-settings.h"
|
// #include "desktop-settings.h"
|
||||||
|
|
||||||
enum libdecor_color_scheme {
|
enum libdecor_color_scheme {
|
||||||
|
|
@ -240,7 +225,7 @@ void render_shadow(cairo_t *cr, cairo_surface_t *surface,
|
||||||
int x, int y, int width, int height, int margin, int top_margin);
|
int x, int y, int width, int height, int margin, int top_margin);
|
||||||
|
|
||||||
// #include "desktop-settings.h"
|
// #include "desktop-settings.h"
|
||||||
bool desktop_settings_get_cursor_settings(char **theme, int *size);
|
void desktop_settings_get_cursor_settings(char **theme, int *size);
|
||||||
enum libdecor_color_scheme desktop_settings_get_color_scheme();
|
enum libdecor_color_scheme desktop_settings_get_color_scheme();
|
||||||
|
|
||||||
// #include "os-compatibility.h"
|
// #include "os-compatibility.h"
|
||||||
|
|
@ -288,7 +273,11 @@ typedef struct Ctx{
|
||||||
EGLSurface egl_surface;
|
EGLSurface egl_surface;
|
||||||
|
|
||||||
int has_cached_config;
|
int has_cached_config;
|
||||||
struct libdecor_configuration cached_config;
|
int cached_config_initialized;
|
||||||
|
enum libdecor_window_state cached_config_window_state;
|
||||||
|
int cached_config_window_width;
|
||||||
|
int cached_config_window_height;
|
||||||
|
uint32_t cached_config_serial;
|
||||||
|
|
||||||
/* uncategorized experiments */
|
/* uncategorized experiments */
|
||||||
struct seat *seat;
|
struct seat *seat;
|
||||||
|
|
@ -314,7 +303,6 @@ typedef struct Ctx{
|
||||||
enum zxdg_toplevel_decoration_v1_mode decoration_mode;
|
enum zxdg_toplevel_decoration_v1_mode decoration_mode;
|
||||||
|
|
||||||
enum libdecor_capabilities frame_capabilities;
|
enum libdecor_capabilities frame_capabilities;
|
||||||
enum libdecor_wm_capabilities wm_capabilities;
|
|
||||||
|
|
||||||
bool visible;
|
bool visible;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,799 @@
|
||||||
|
#if 0
|
||||||
|
libdecor_path="/home/mr4th/mr4th/libdecor"
|
||||||
|
root_path="$PWD"
|
||||||
|
dbus_flags="$(pkg-config --cflags --libs dbus-1)"
|
||||||
|
my_flags="-Iwayland -I$libdecor_path/src -I$libdecor_path/src/plugins -I$libdecor_path/build"
|
||||||
|
my_flags+=" -lwayland-client -lwayland-cursor -lwayland-egl -lEGL -lm"
|
||||||
|
mkdir -p build
|
||||||
|
clang -o build/demo -g $root_path/wayland_egl.c $dbus_flags $my_flags
|
||||||
|
exit 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-client-core.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
|
#include <wayland-egl.h>
|
||||||
|
/*~ NOTE: wayland-egl.h *before* EGL/ */
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#include <GL/glcorearb.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "xdg-shell-client-protocol.h"
|
||||||
|
#include "xdg-decoration-client-protocol.h"
|
||||||
|
|
||||||
|
#include "xdg-shell-client-protocol.c"
|
||||||
|
#include "xdg-decoration-client-protocol.c"
|
||||||
|
|
||||||
|
#include "wayland_egl.h"
|
||||||
|
|
||||||
|
// X(N:name,R:return,P:params)
|
||||||
|
#define GL_FUNCS_XLIST(X)\
|
||||||
|
X(glDrawBuffer, void, (GLenum buf)) \
|
||||||
|
X(glViewport, void, (GLint x, GLint y, GLsizei w, GLsizei h)) \
|
||||||
|
X(glClear, void, (GLbitfield mask)) \
|
||||||
|
X(glClearColor, void, (GLfloat r, GLfloat g, GLfloat b, GLfloat a))
|
||||||
|
|
||||||
|
#define X(N,R,P) R (*N)P = 0;
|
||||||
|
GL_FUNCS_XLIST(X)
|
||||||
|
#undef X
|
||||||
|
|
||||||
|
static Ctx ctx = {0};
|
||||||
|
|
||||||
|
static void
|
||||||
|
shm_format(void *udata, struct wl_shm *wl_shm, uint32_t format){
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_shm_listener shm_listener = {
|
||||||
|
shm_format
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_wm_base_ping(void *udata, struct xdg_wm_base *xdg_wm_base, uint32_t serial){
|
||||||
|
xdg_wm_base_pong(xdg_wm_base, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||||
|
xdg_wm_base_ping
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_enter(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
|
||||||
|
struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y){
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_leave(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
|
||||||
|
struct wl_surface *surface){
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_motion(void *udata, struct wl_pointer *wl_pointer, uint32_t time,
|
||||||
|
wl_fixed_t surface_x, wl_fixed_t surface_y){
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_button(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
|
||||||
|
uint32_t time, uint32_t button, uint32_t state){
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_axis(void *udata, struct wl_pointer *wl_pointer,
|
||||||
|
uint32_t time, uint32_t axis, wl_fixed_t value){
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_pointer_listener pointer_listener = {
|
||||||
|
pointer_enter,
|
||||||
|
pointer_leave,
|
||||||
|
pointer_motion,
|
||||||
|
pointer_button,
|
||||||
|
pointer_axis
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
seat_capabilities(void *udata, struct wl_seat *wl_seat, uint32_t capabilities){
|
||||||
|
if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && ctx.wl_pointer == 0){
|
||||||
|
ctx.wl_pointer = wl_seat_get_pointer(ctx.wl_seat);
|
||||||
|
wl_pointer_add_listener(ctx.wl_pointer, &pointer_listener, 0);
|
||||||
|
}
|
||||||
|
else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && ctx.wl_pointer != 0){
|
||||||
|
wl_pointer_release(ctx.wl_pointer);
|
||||||
|
ctx.wl_pointer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
seat_name(void *udata, struct wl_seat *wl_seat, const char *name){
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_seat_listener seat_listener = {
|
||||||
|
seat_capabilities,
|
||||||
|
seat_name
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_global(void *udata, struct wl_registry *wl_registry,
|
||||||
|
uint32_t name, const char *interface,
|
||||||
|
uint32_t version){
|
||||||
|
if (strcmp(interface, "wl_compositor") == 0){
|
||||||
|
ctx.wl_compositor = (struct wl_compositor*)
|
||||||
|
wl_registry_bind(wl_registry, name, &wl_compositor_interface, Min(version, 4));
|
||||||
|
}
|
||||||
|
else if (strcmp(interface, "wl_subcompositor") == 0){
|
||||||
|
ctx.wl_subcompositor = wl_registry_bind(ctx.wl_registry, name, &wl_subcompositor_interface, 1);
|
||||||
|
}
|
||||||
|
else if (strcmp(interface, "wl_shm") == 0){
|
||||||
|
ctx.wl_shm = wl_registry_bind(ctx.wl_registry, name, &wl_shm_interface, 1);
|
||||||
|
wl_shm_add_listener(ctx.wl_shm, &shm_listener, 0);
|
||||||
|
}
|
||||||
|
else if (!strcmp(interface, xdg_wm_base_interface.name)){
|
||||||
|
ctx.xdg_wm_base = wl_registry_bind(ctx.wl_registry, name, &xdg_wm_base_interface, Min(version, 2));
|
||||||
|
xdg_wm_base_add_listener(ctx.xdg_wm_base, &xdg_wm_base_listener, 0);
|
||||||
|
}
|
||||||
|
else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)){
|
||||||
|
ctx.zxdg_decoration_manager = wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, Min(version, 2));
|
||||||
|
}
|
||||||
|
else if (strcmp(interface, "wl_seat") == 0){
|
||||||
|
ctx.wl_seat = wl_registry_bind(ctx.wl_registry, name, &wl_seat_interface, 3);
|
||||||
|
wl_seat_add_listener(ctx.wl_seat, &seat_listener, 0);
|
||||||
|
ctx.cursor_surface = wl_compositor_create_surface(ctx.wl_compositor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_global_remove(void *udata, struct wl_registry *registry,
|
||||||
|
uint32_t name){
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_registry_listener registry_listener = {
|
||||||
|
registry_global,
|
||||||
|
registry_global_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_surface_configure(void *udata, struct xdg_surface *xdg_surface,
|
||||||
|
uint32_t serial){
|
||||||
|
ctx.config_staged.serial = serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure, };
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_toplevel_configure(void *udata, struct xdg_toplevel *xdg_toplevel,
|
||||||
|
int32_t width, int32_t height, struct wl_array *states){
|
||||||
|
if (width != 0 && height != 0){
|
||||||
|
ctx.config_staged.dim[0] = width;
|
||||||
|
ctx.config_staged.dim[1] = height;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ctx.config_staged.dim[0] = ctx.config.dim[0];
|
||||||
|
ctx.config_staged.dim[1] = ctx.config.dim[1];
|
||||||
|
}
|
||||||
|
ctx.config_staged.flags = window_flags_from_states_array(states);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_toplevel_close(void *udata, struct xdg_toplevel *xdg_toplevel){
|
||||||
|
ctx.close_signal = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_toplevel_configure_bounds(void *udata, struct xdg_toplevel *xdg_toplevel,
|
||||||
|
int32_t w, int32_t h){
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_toplevel_wm_capabilities(void *udata, struct xdg_toplevel *xdg_toplevel,
|
||||||
|
struct wl_array *capabilities){
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||||
|
xdg_toplevel_configure,
|
||||||
|
xdg_toplevel_close,
|
||||||
|
xdg_toplevel_configure_bounds,
|
||||||
|
xdg_toplevel_wm_capabilities,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_toplevel_decoration_configure(void *udata, struct zxdg_toplevel_decoration_v1 *toplevel,
|
||||||
|
uint32_t mode){
|
||||||
|
ctx.config_staged.decoration_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct zxdg_toplevel_decoration_v1_listener zxdg_toplevel_decoration_listener = {
|
||||||
|
xdg_toplevel_decoration_configure
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
/* desktop settings */
|
||||||
|
ctx.color_scheme = ds_get_color_scheme();
|
||||||
|
ctx.cursor_theme = ds_get_cursor_theme();
|
||||||
|
|
||||||
|
/* setup Wayland */
|
||||||
|
{
|
||||||
|
ctx.wl_display = wl_display_connect(0);
|
||||||
|
ctx.wl_registry = wl_display_get_registry(ctx.wl_display);
|
||||||
|
wl_registry_add_listener(ctx.wl_registry, ®istry_listener, 0);
|
||||||
|
|
||||||
|
wl_display_flush(ctx.wl_display);
|
||||||
|
wl_display_dispatch(ctx.wl_display);
|
||||||
|
|
||||||
|
ctx.wl_cursor_theme = wl_cursor_theme_load(ctx.cursor_theme.name,
|
||||||
|
ctx.cursor_theme.size,
|
||||||
|
ctx.wl_shm);
|
||||||
|
|
||||||
|
#define X(k,n) ctx.wl_cursors[k] = wl_cursor_theme_get_cursor(ctx.wl_cursor_theme, n);
|
||||||
|
X(CursorShape_Pointer, "left_ptr");
|
||||||
|
X(CursorShape_Resize_Top, "top_side");
|
||||||
|
X(CursorShape_Resize_Bottom, "bottom_side");
|
||||||
|
X(CursorShape_Resize_Left, "left_side");
|
||||||
|
X(CursorShape_Resize_Right, "right_side");
|
||||||
|
X(CursorShape_Resize_TopLeft, "top_left_corner");
|
||||||
|
X(CursorShape_Resize_BottomLeft, "bottom_left_corner");
|
||||||
|
X(CursorShape_Resize_TopRight, "top_right_corner");
|
||||||
|
X(CursorShape_Resize_BottomRight, "bottom_right_corner");
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup EGL */
|
||||||
|
{
|
||||||
|
ctx.egl_display = eglGetDisplay(ctx.wl_display);
|
||||||
|
|
||||||
|
EGLint major = 0, minor = 0;
|
||||||
|
eglInitialize(ctx.egl_display, &major, &minor);
|
||||||
|
eglBindAPI(EGL_OPENGL_API);
|
||||||
|
|
||||||
|
{
|
||||||
|
EGLint attr[] = {
|
||||||
|
EGL_CONTEXT_MAJOR_VERSION, 3,
|
||||||
|
EGL_CONTEXT_MINOR_VERSION, 3,
|
||||||
|
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
ctx.egl_context = eglCreateContext(ctx.egl_display, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
eglMakeCurrent(ctx.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx.egl_context);
|
||||||
|
|
||||||
|
#define X(N,R,P) N = (R(*)P)(eglGetProcAddress(#N));
|
||||||
|
GL_FUNCS_XLIST(X)
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a window */
|
||||||
|
{
|
||||||
|
/* window main surface */
|
||||||
|
ctx.main_wl_surface = wl_compositor_create_surface(ctx.wl_compositor);
|
||||||
|
ctx.main_xdg_surface = xdg_wm_base_get_xdg_surface(ctx.xdg_wm_base, ctx.main_wl_surface);
|
||||||
|
xdg_surface_add_listener(ctx.main_xdg_surface, &xdg_surface_listener, 0);
|
||||||
|
ctx.main_xdg_toplevel = xdg_surface_get_toplevel(ctx.main_xdg_surface);
|
||||||
|
xdg_toplevel_add_listener(ctx.main_xdg_toplevel, &xdg_toplevel_listener, 0);
|
||||||
|
|
||||||
|
ctx.config.dim[0] = 640;
|
||||||
|
ctx.config.dim[1] = 480;
|
||||||
|
ctx.control_flags = ~0;
|
||||||
|
|
||||||
|
ctx.config_staged.decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
|
||||||
|
if (ctx.zxdg_decoration_manager != 0){
|
||||||
|
ctx.main_zxdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(ctx.zxdg_decoration_manager, ctx.main_xdg_toplevel);
|
||||||
|
zxdg_toplevel_decoration_v1_add_listener(ctx.main_zxdg_toplevel_decoration, &zxdg_toplevel_decoration_listener, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < 2; k += 1){
|
||||||
|
ctx.mmbox[k][0] = 0;
|
||||||
|
ctx.mmbox[k][1] = (1 << 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
xdg_toplevel_set_app_id(ctx.main_xdg_toplevel, "demo");
|
||||||
|
xdg_toplevel_set_title(ctx.main_xdg_toplevel, "Example Window");
|
||||||
|
wl_surface_commit(ctx.main_wl_surface);
|
||||||
|
|
||||||
|
/* window subsurface */
|
||||||
|
ctx.shadow_wl_surface = wl_compositor_create_surface(ctx.wl_compositor);
|
||||||
|
ctx.shadow_wl_subsurface =
|
||||||
|
wl_subcompositor_get_subsurface(ctx.wl_subcompositor,
|
||||||
|
ctx.shadow_wl_surface,
|
||||||
|
ctx.main_wl_surface);
|
||||||
|
|
||||||
|
{
|
||||||
|
int dim[2] = {640, 25};
|
||||||
|
|
||||||
|
int stride = 4*dim[0];
|
||||||
|
uint64_t size = 4*dim[0]*dim[1];
|
||||||
|
|
||||||
|
int fd = os_create_anonymous_file(size);
|
||||||
|
if (fd >= 0){
|
||||||
|
void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (data != MAP_FAILED){
|
||||||
|
struct wl_shm_pool *pool = wl_shm_create_pool(ctx.wl_shm, fd, size);
|
||||||
|
struct wl_buffer *wl_buffer = wl_shm_pool_create_buffer(pool, 0, dim[0], dim[1], stride,
|
||||||
|
WL_SHM_FORMAT_ARGB8888);
|
||||||
|
wl_shm_pool_destroy(pool);
|
||||||
|
|
||||||
|
ctx.shadow_wl_buffer = wl_buffer;
|
||||||
|
ctx.shadow_data = data;
|
||||||
|
ctx.shadow_size = size;
|
||||||
|
for (int i = 0; i < 2; i += 1){
|
||||||
|
ctx.shadow_dim[i] = dim[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* window egl */
|
||||||
|
ctx.main_wl_egl_window = wl_egl_window_create(ctx.main_wl_surface,
|
||||||
|
ctx.config.dim[0],
|
||||||
|
ctx.config.dim[1]);
|
||||||
|
|
||||||
|
EGLConfig configs[64];
|
||||||
|
EGLint config_cap = sizeof(configs)/sizeof(*configs);
|
||||||
|
EGLint config_count = 0;
|
||||||
|
{
|
||||||
|
EGLint attributes[] = {
|
||||||
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
|
EGL_CONFORMANT, EGL_OPENGL_BIT,
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||||
|
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
|
||||||
|
EGL_RED_SIZE, 8,
|
||||||
|
EGL_GREEN_SIZE, 8,
|
||||||
|
EGL_BLUE_SIZE, 8,
|
||||||
|
EGL_DEPTH_SIZE, 24,
|
||||||
|
EGL_STENCIL_SIZE, 8,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
eglChooseConfig(ctx.egl_display, attributes, configs, config_cap, &config_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EGLint attributes[] = {
|
||||||
|
EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
for (EGLint i = 0; i < config_count; i += 1){
|
||||||
|
ctx.main_egl_surface = eglCreateWindowSurface(ctx.egl_display, configs[i], ctx.main_wl_egl_window, attributes);
|
||||||
|
if (ctx.main_egl_surface != EGL_NO_SURFACE){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eglMakeCurrent(ctx.egl_display, ctx.main_egl_surface,
|
||||||
|
ctx.main_egl_surface, ctx.egl_context);
|
||||||
|
|
||||||
|
eglSwapInterval(ctx.egl_display, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* main loop */
|
||||||
|
int exit_loop = 0;
|
||||||
|
for (;!exit_loop;){
|
||||||
|
/* poll for events */
|
||||||
|
{
|
||||||
|
struct pollfd fds[1] = {0};
|
||||||
|
|
||||||
|
/* register fds[0] ~ wayland events */
|
||||||
|
bool wayland_started_read = false;
|
||||||
|
bool wayland_did_read = false;
|
||||||
|
{
|
||||||
|
fds[0].fd = -1;
|
||||||
|
|
||||||
|
wl_display_dispatch_pending(ctx.wl_display);
|
||||||
|
wayland_started_read = (wl_display_prepare_read(ctx.wl_display) != -1);
|
||||||
|
if (wayland_started_read){
|
||||||
|
fds[0].fd = wl_display_get_fd(ctx.wl_display);
|
||||||
|
fds[0].events = POLLIN;
|
||||||
|
wl_display_flush(ctx.wl_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* poll and handle events */
|
||||||
|
int ret = poll(fds, sizeof(fds)/sizeof(*fds), 0);
|
||||||
|
if (ret > 0){
|
||||||
|
|
||||||
|
/* handle fds[0] ~ wayland events */
|
||||||
|
if (fds[0].revents & POLLIN){
|
||||||
|
wayland_did_read = true;
|
||||||
|
wl_display_read_events(ctx.wl_display);
|
||||||
|
wl_display_dispatch_pending(ctx.wl_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wayland event read cleanup */
|
||||||
|
if (wayland_started_read && !wayland_did_read){
|
||||||
|
wl_display_cancel_read(ctx.wl_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply config */
|
||||||
|
if (ctx.config.serial != ctx.config_staged.serial){
|
||||||
|
ctx.config = ctx.config_staged;
|
||||||
|
xdg_surface_ack_configure(ctx.main_xdg_surface, ctx.config.serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
int csd = (ctx.config.decoration_mode ==
|
||||||
|
ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
|
||||||
|
|
||||||
|
/* window sizing */
|
||||||
|
CSD_Frame csd_frame = {0};
|
||||||
|
int32_t csd_dim[2];
|
||||||
|
{
|
||||||
|
if (csd){
|
||||||
|
csd_frame = csd_impl_calculate_frame();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 2; i += 1){
|
||||||
|
csd_dim[i] = csd_frame.border[i][0] + csd_frame.border[i][1];
|
||||||
|
int32_t d = ctx.config.dim[i] - csd_dim[i];
|
||||||
|
d = ClampBot(d, ctx.mmbox[i][0]);
|
||||||
|
d = ClampTop(d, ctx.mmbox[i][1]);
|
||||||
|
d = ClampBot(d, csd_frame.minbox[i]);
|
||||||
|
ctx.dim[i] = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* window frame render */
|
||||||
|
if (csd){
|
||||||
|
uint32_t *pxl = (uint32_t*)ctx.shadow_data;
|
||||||
|
for (int32_t y = 0; y < ctx.shadow_dim[1]; y += 1){
|
||||||
|
for (int32_t x = 0; x < ctx.shadow_dim[0]; x += 1){
|
||||||
|
*pxl = 0xFFFF0000;
|
||||||
|
pxl += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* window frame commit */
|
||||||
|
if (csd){
|
||||||
|
{
|
||||||
|
wl_surface_attach(ctx.shadow_wl_surface, ctx.shadow_wl_buffer, 0, 0);
|
||||||
|
wl_surface_set_buffer_scale(ctx.shadow_wl_surface, 1);
|
||||||
|
wl_surface_damage_buffer(ctx.shadow_wl_surface, 0, 0,
|
||||||
|
ctx.shadow_dim[0], ctx.shadow_dim[1]);
|
||||||
|
wl_subsurface_set_position(ctx.shadow_wl_subsurface, 0, -25);
|
||||||
|
wl_surface_commit(ctx.shadow_wl_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ctx.control_flags & WindowControlFlag_Resize)){
|
||||||
|
xdg_toplevel_set_min_size(ctx.main_xdg_toplevel, ctx.dim[0], ctx.dim[1]);
|
||||||
|
xdg_toplevel_set_max_size(ctx.main_xdg_toplevel, ctx.dim[0], ctx.dim[1]);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for (int i = 0; i < 2; i += 1){
|
||||||
|
int32_t mw = ClampBot(ctx.mmbox[0][i], csd_frame.minbox[i]) + csd_dim[0];
|
||||||
|
int32_t mh = ctx.mmbox[1][i] + csd_dim[1];
|
||||||
|
if (i == 0){
|
||||||
|
xdg_toplevel_set_min_size(ctx.main_xdg_toplevel, mw, mh);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
xdg_toplevel_set_max_size(ctx.main_xdg_toplevel, mw, mh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* app update & render */
|
||||||
|
{
|
||||||
|
if (ctx.close_signal){
|
||||||
|
exit_loop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawBuffer(GL_BACK);
|
||||||
|
glViewport(0, 0, ctx.config.dim[0], ctx.config.dim[1]);
|
||||||
|
glClearColor(0.40f, 0.90f, 0.15f, 1.f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
eglSwapBuffers(ctx.egl_display, ctx.main_egl_surface);
|
||||||
|
wl_surface_commit(ctx.main_wl_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* csd implementation */
|
||||||
|
|
||||||
|
static CSD_Frame
|
||||||
|
csd_impl_calculate_frame(void){
|
||||||
|
CSD_Frame frame = {0};
|
||||||
|
bool show_title = (!(ctx.config.flags & WindowFlag_IsFullscreen));
|
||||||
|
if (show_title){
|
||||||
|
frame.border[1][0] = 25;
|
||||||
|
}
|
||||||
|
return(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wayland helpers */
|
||||||
|
|
||||||
|
static WindowFlags
|
||||||
|
window_flags_from_states_array(struct wl_array *states){
|
||||||
|
WindowFlags flags = 0;
|
||||||
|
uint32_t *p;
|
||||||
|
wl_array_for_each(p, states){
|
||||||
|
switch (*p) {
|
||||||
|
case XDG_TOPLEVEL_STATE_FULLSCREEN: flags |= WindowFlag_IsFullscreen; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_MAXIMIZED: flags |= WindowFlag_IsMax; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_ACTIVATED: flags |= WindowFlag_IsActivated; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_TILED_LEFT: flags |= WindowFlag_IsTiledLeft; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_TILED_RIGHT: flags |= WindowFlag_IsTiledRight; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_TILED_TOP: flags |= WindowFlag_IsTiledTop; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_TILED_BOTTOM: flags |= WindowFlag_IsTiledBottom; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_RESIZING: flags |= WindowFlag_IsResizing; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_SUSPENDED: flags |= WindowFlag_IsSuspended; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: flags |= WindowFlag_IsConstrainedLeft; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: flags |= WindowFlag_IsConstrainedRight; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: flags |= WindowFlag_IsConstrainedTop; break;
|
||||||
|
case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: flags |= WindowFlag_IsConstrainedBottom; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* os */
|
||||||
|
|
||||||
|
static int
|
||||||
|
os_resize_anonymous_file(int fd, off_t size){
|
||||||
|
#ifdef HAVE_POSIX_FALLOCATE
|
||||||
|
|
||||||
|
sigset_t mask;
|
||||||
|
sigset_t old_mask;
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, SIGALRM);
|
||||||
|
sigprocmask(SIG_BLOCK, &mask, &old_mask);
|
||||||
|
|
||||||
|
do {
|
||||||
|
errno = posix_fallocate(fd, 0, size);
|
||||||
|
} while (errno == EINTR);
|
||||||
|
sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
if (errno != 0){
|
||||||
|
result = -1;
|
||||||
|
if (errno == EINVAL || errno == EOPNOTSUPP){
|
||||||
|
if (ftruncate(fd, size) >= 0){
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int result = -1;
|
||||||
|
if (ftruncate(fd, size) >= 0){
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
os_create_anonymous_file(off_t size){
|
||||||
|
static const char key[] = "/libdecor-shared-XXXXXX";
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
#ifdef HAVE_MEMFD_CREATE
|
||||||
|
fd = memfd_create("libdecor", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||||
|
if (fd >= 0){
|
||||||
|
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (fd < 0){
|
||||||
|
const char *path = getenv("XDG_RUNTIME_DIR");
|
||||||
|
if (path == 0){
|
||||||
|
errno = ENOENT;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
char *name = malloc(strlen(path) + sizeof(key));
|
||||||
|
if (name != 0){
|
||||||
|
strcpy(name, path);
|
||||||
|
strcat(name, key);
|
||||||
|
|
||||||
|
#ifdef HAVE_MKOSTEMP
|
||||||
|
fd = mkostemp(name, O_CLOEXEC);
|
||||||
|
if (fd >= 0){
|
||||||
|
unlink(name);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
fd = mkstemp(name);
|
||||||
|
|
||||||
|
if (fd >= 0){
|
||||||
|
if (fcntl(fd, F_GETFD) == -1){
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
else if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1){
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd >= 0) {
|
||||||
|
unlink(name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd >= 0 && os_resize_anonymous_file(fd, size) < 0){
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* desktop settings */
|
||||||
|
|
||||||
|
static CursorTheme
|
||||||
|
ds__get_cursor_theme_from_env(void){
|
||||||
|
CursorTheme result = {0};
|
||||||
|
char *env_xtheme = getenv("XCURSOR_THEME");
|
||||||
|
char *env_xsize = getenv("XCURSOR_SIZE");
|
||||||
|
if (env_xtheme != 0 && env_xsize != 0){
|
||||||
|
result.name = strdup(env_xtheme);
|
||||||
|
result.size = atoi(env_xsize);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result.name = 0;
|
||||||
|
result.size = 24;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_DBUS
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
|
||||||
|
static DBusMessage *
|
||||||
|
ds__get_setting_sync(DBusConnection *const connection, const char *key1, const char *key2){
|
||||||
|
DBusMessage *reply = 0;
|
||||||
|
DBusMessage *message =
|
||||||
|
dbus_message_new_method_call("org.freedesktop.portal.Desktop",
|
||||||
|
"/org/freedesktop/portal/desktop",
|
||||||
|
"org.freedesktop.portal.Settings",
|
||||||
|
"Read");
|
||||||
|
|
||||||
|
if (message != 0){
|
||||||
|
dbus_bool_t success = dbus_message_append_args(message,
|
||||||
|
DBUS_TYPE_STRING, &key1,
|
||||||
|
DBUS_TYPE_STRING, &key2,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
if (success){
|
||||||
|
DBusError error;
|
||||||
|
dbus_error_init(&error);
|
||||||
|
reply = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error);
|
||||||
|
if (dbus_error_is_set(&error) && reply != 0){
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
reply = 0;
|
||||||
|
}
|
||||||
|
dbus_error_free(&error);
|
||||||
|
}
|
||||||
|
dbus_message_unref(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ds__parse_type(DBusMessage *const reply, const int type, void *value){
|
||||||
|
int result = 0;
|
||||||
|
DBusMessageIter iter[3];
|
||||||
|
dbus_message_iter_init(reply, &iter[0]);
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter[0]) == DBUS_TYPE_VARIANT){
|
||||||
|
dbus_message_iter_recurse(&iter[0], &iter[1]);
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter[1]) == DBUS_TYPE_VARIANT){
|
||||||
|
dbus_message_iter_recurse(&iter[1], &iter[2]);
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter[2]) == type){
|
||||||
|
dbus_message_iter_get_basic(&iter[2], value);
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CursorTheme
|
||||||
|
ds_get_cursor_theme(void){
|
||||||
|
static const char key[] = "org.gnome.desktop.interface";
|
||||||
|
static const char key_theme[] = "cursor-theme";
|
||||||
|
static const char key_size[] = "cursor-size";
|
||||||
|
|
||||||
|
char *name = 0;
|
||||||
|
int size = 0;
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
DBusError error;
|
||||||
|
dbus_error_init(&error);
|
||||||
|
DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
|
||||||
|
|
||||||
|
if (!dbus_error_is_set(&error)){
|
||||||
|
DBusMessage *reply = ds__get_setting_sync(connection, key, key_theme);
|
||||||
|
if (reply != 0){
|
||||||
|
if (!ds__parse_type(reply, DBUS_TYPE_STRING, &name)){
|
||||||
|
name = 0;
|
||||||
|
}
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name != 0){
|
||||||
|
DBusMessage *reply = ds__get_setting_sync(connection, key, key_size);
|
||||||
|
if (reply){
|
||||||
|
if (ds__parse_type(reply, DBUS_TYPE_INT32, &size)){
|
||||||
|
success = 1;
|
||||||
|
}
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CursorTheme result = {0};
|
||||||
|
if (success){
|
||||||
|
result.name = name;
|
||||||
|
result.size = size;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result = ds__get_cursor_theme_from_env();
|
||||||
|
}
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ColorScheme
|
||||||
|
ds_get_color_scheme(){
|
||||||
|
static const char name[] = "org.freedesktop.appearance";
|
||||||
|
static const char key_color_scheme[] = "color-scheme";
|
||||||
|
uint32_t color = 0;
|
||||||
|
|
||||||
|
DBusError error;
|
||||||
|
dbus_error_init(&error);
|
||||||
|
DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
|
||||||
|
|
||||||
|
if (!dbus_error_is_set(&error)){
|
||||||
|
DBusMessage *reply = ds__get_setting_sync(connection, name, key_color_scheme);
|
||||||
|
if (reply){
|
||||||
|
if (!ds__parse_type(reply, DBUS_TYPE_UINT32, &color)) {
|
||||||
|
color = 0;
|
||||||
|
}
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static CursorTheme
|
||||||
|
ds_get_cursor_them(void){
|
||||||
|
return(ds__get_cursor_theme_from_env());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ColorScheme
|
||||||
|
ds_get_color_scheme(){
|
||||||
|
return(ColorScheme_Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
#ifndef WAYLAND_EGL_EXAMPLE_H
|
||||||
|
#define WAYLAND_EGL_EXAMPLE_H
|
||||||
|
|
||||||
|
#define HAS_DBUS
|
||||||
|
#define HAVE_MEMFD_CREATE
|
||||||
|
#define HAVE_POSIX_FALLOCATE
|
||||||
|
|
||||||
|
#define Min(a, b) ((a)>(b)?(b):(a))
|
||||||
|
#define Max(a, b) ((a)<(b)?(b):(a))
|
||||||
|
|
||||||
|
#define ClampTop(x, a) Min(x, a)
|
||||||
|
#define ClampBot(x, a) Max(x, a)
|
||||||
|
|
||||||
|
typedef enum ColorScheme{
|
||||||
|
ColorScheme_Default,
|
||||||
|
ColorScheme_Dark,
|
||||||
|
ColorScheme_Light
|
||||||
|
} ColorScheme;
|
||||||
|
|
||||||
|
typedef struct CursorTheme{
|
||||||
|
char *name;
|
||||||
|
int size;
|
||||||
|
} CursorTheme;
|
||||||
|
|
||||||
|
enum{
|
||||||
|
CursorShape_Pointer,
|
||||||
|
CursorShape_Resize_Top,
|
||||||
|
CursorShape_Resize_Bottom,
|
||||||
|
CursorShape_Resize_Left,
|
||||||
|
CursorShape_Resize_Right,
|
||||||
|
CursorShape_Resize_TopLeft,
|
||||||
|
CursorShape_Resize_TopRight,
|
||||||
|
CursorShape_Resize_BottomLeft,
|
||||||
|
CursorShape_Resize_BottomRight,
|
||||||
|
CursorShape_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint32_t WindowFlags;
|
||||||
|
enum{
|
||||||
|
WindowFlag_IsFullscreen = (1 << 0),
|
||||||
|
WindowFlag_IsMax = (1 << 1),
|
||||||
|
WindowFlag_IsActivated = (1 << 2),
|
||||||
|
WindowFlag_IsTiledLeft = (1 << 3),
|
||||||
|
WindowFlag_IsTiledRight = (1 << 4),
|
||||||
|
WindowFlag_IsTiledTop = (1 << 5),
|
||||||
|
WindowFlag_IsTiledBottom = (1 << 6),
|
||||||
|
WindowFlag_IsResizing = (1 << 7),
|
||||||
|
WindowFlag_IsSuspended = (1 << 8),
|
||||||
|
WindowFlag_IsConstrainedLeft = (1 << 9),
|
||||||
|
WindowFlag_IsConstrainedRight = (1 << 10),
|
||||||
|
WindowFlag_IsConstrainedTop = (1 << 11),
|
||||||
|
WindowFlag_IsConstrainedBottom = (1 << 12),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint32_t WindowControlFlags;
|
||||||
|
enum{
|
||||||
|
WindowControlFlag_Move = (1 << 0),
|
||||||
|
WindowControlFlag_Resize = (1 << 1),
|
||||||
|
WindowControlFlag_Min = (1 << 2),
|
||||||
|
WindowControlFlag_Max = (1 << 3),
|
||||||
|
WindowControlFlag_Close = (1 << 4),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Config{
|
||||||
|
uint32_t serial;
|
||||||
|
int32_t dim[2];
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t decoration_mode;
|
||||||
|
} Config;
|
||||||
|
|
||||||
|
typedef struct CSD_Frame{
|
||||||
|
int32_t border[2][2]; // [0][]:x [1][]:y [][0]:min [][1]:max
|
||||||
|
int32_t minbox[2];
|
||||||
|
} CSD_Frame;
|
||||||
|
|
||||||
|
typedef struct Ctx{
|
||||||
|
/* "application variables" */
|
||||||
|
int close_signal;
|
||||||
|
|
||||||
|
/* globals: desktop settings */
|
||||||
|
ColorScheme color_scheme;
|
||||||
|
CursorTheme cursor_theme;
|
||||||
|
|
||||||
|
/* globals: wayland */
|
||||||
|
struct wl_display *wl_display;
|
||||||
|
struct wl_registry *wl_registry;
|
||||||
|
struct wl_compositor *wl_compositor;
|
||||||
|
struct wl_subcompositor *wl_subcompositor;
|
||||||
|
struct wl_shm *wl_shm;
|
||||||
|
struct xdg_wm_base *xdg_wm_base;
|
||||||
|
struct zxdg_decoration_manager_v1 *zxdg_decoration_manager;
|
||||||
|
|
||||||
|
struct wl_cursor_theme *wl_cursor_theme;
|
||||||
|
struct wl_cursor *wl_cursors[CursorShape_COUNT];
|
||||||
|
|
||||||
|
/* globals: egl */
|
||||||
|
EGLDisplay egl_display;
|
||||||
|
EGLContext egl_context;
|
||||||
|
|
||||||
|
/* per-seat: wayland */
|
||||||
|
struct wl_seat *wl_seat;
|
||||||
|
struct wl_pointer *wl_pointer;
|
||||||
|
struct wl_surface *cursor_surface;
|
||||||
|
|
||||||
|
/* per-window: wayland */
|
||||||
|
struct wl_surface *main_wl_surface;
|
||||||
|
struct xdg_surface *main_xdg_surface;
|
||||||
|
struct xdg_toplevel *main_xdg_toplevel;
|
||||||
|
struct zxdg_toplevel_decoration_v1 *main_zxdg_toplevel_decoration;
|
||||||
|
|
||||||
|
struct wl_surface *shadow_wl_surface;
|
||||||
|
struct wl_subsurface *shadow_wl_subsurface;
|
||||||
|
struct wl_buffer *shadow_wl_buffer;
|
||||||
|
void *shadow_data;
|
||||||
|
uint64_t shadow_size;
|
||||||
|
int32_t shadow_dim[2];
|
||||||
|
|
||||||
|
/* per-window: egl */
|
||||||
|
struct wl_egl_window *main_wl_egl_window;
|
||||||
|
EGLSurface main_egl_surface;
|
||||||
|
|
||||||
|
/* per-window */
|
||||||
|
WindowControlFlags control_flags;
|
||||||
|
Config config;
|
||||||
|
Config config_staged;
|
||||||
|
int32_t mmbox[2][2]; // [0][]:x [1][]:y [][0]:min [][1]:max
|
||||||
|
int32_t dim[2];
|
||||||
|
} Ctx;
|
||||||
|
|
||||||
|
|
||||||
|
/* csd implementation */
|
||||||
|
|
||||||
|
static CSD_Frame csd_impl_calculate_frame(void);
|
||||||
|
|
||||||
|
|
||||||
|
/* wayland helpers */
|
||||||
|
|
||||||
|
static WindowFlags window_flags_from_states_array(struct wl_array *states);
|
||||||
|
|
||||||
|
/* os */
|
||||||
|
|
||||||
|
static int os_resize_anonymous_file(int fd, off_t size);
|
||||||
|
static int os_create_anonymous_file(off_t size);
|
||||||
|
|
||||||
|
/* desktop settings */
|
||||||
|
|
||||||
|
static CursorTheme ds_get_cursor_theme(void);
|
||||||
|
static ColorScheme ds_get_color_scheme(void);
|
||||||
|
|
||||||
|
static CursorTheme ds__get_cursor_theme_from_env(void);
|
||||||
|
|
||||||
|
#if defined(HAS_DBUS)
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
static DBusMessage* ds__get_setting_sync(DBusConnection *const connection, const char *k, const char *v);
|
||||||
|
static int ds__parse_type(DBusMessage *const reply, const int type, void *value);
|
||||||
|
#endif /* defined(HAS_DBUS) */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* WAYLAND_EGL_EXAMPLE_H */
|
||||||
Loading…
Reference in New Issue