[wayland_egl.c] self contained wayland setup example
parent
f56e3dedde
commit
b5932166ae
|
|
@ -376,7 +376,7 @@ border_component_reallocate(struct border_component *component, int w, int h){
|
|||
component->wl_buffer = 0;
|
||||
}
|
||||
if (component->data != 0){
|
||||
munmap(component->data, component->data_size);
|
||||
cmunmap(component->data, component->data_size);
|
||||
component->data = 0;
|
||||
}
|
||||
component->data_size = 0;
|
||||
|
|
|
|||
282
wayland_egl.c
282
wayland_egl.c
|
|
@ -75,29 +75,78 @@ const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
|||
xdg_wm_base_ping
|
||||
};
|
||||
|
||||
#define SHADOW_MARGIN 20
|
||||
#define SHADOW_THICK 10
|
||||
|
||||
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){
|
||||
struct wl_surface *surface, wl_fixed_t fx, wl_fixed_t fy){
|
||||
int x = ctx.p[0] = wl_fixed_to_int(fx);
|
||||
int y = ctx.p[1] = wl_fixed_to_int(fy);
|
||||
ctx.hover = surface;
|
||||
if (surface == ctx.main_wl_surface){
|
||||
printf("pointer_enter (main) %d,%d\n", x, y);
|
||||
}
|
||||
else if (surface == ctx.shadow_wl_surface){
|
||||
printf("pointer_enter (shadow) %d,%d\n", x, y);
|
||||
}
|
||||
else{
|
||||
printf("pointer_enter (unidentified) %d,%d\n", x, y);
|
||||
ctx.hover = 0;
|
||||
}
|
||||
ctx.hover_serial = serial;
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_leave(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
|
||||
struct wl_surface *surface){
|
||||
if (surface == ctx.main_wl_surface){
|
||||
printf("pointer_leave (main)\n");
|
||||
}
|
||||
else if (surface == ctx.shadow_wl_surface){
|
||||
printf("pointer_leave (shadow)\n");
|
||||
}
|
||||
else{
|
||||
printf("pointer_leave (unidentified)\n");
|
||||
}
|
||||
ctx.hover = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_motion(void *udata, struct wl_pointer *wl_pointer, uint32_t time,
|
||||
wl_fixed_t surface_x, wl_fixed_t surface_y){
|
||||
wl_fixed_t fx, wl_fixed_t fy){
|
||||
int x = ctx.p[0] = wl_fixed_to_int(fx);
|
||||
int y = ctx.p[1] = wl_fixed_to_int(fy);
|
||||
printf("pointer_motion %d,%d\n", x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_button(void *udata, struct wl_pointer *wl_pointer, uint32_t serial,
|
||||
uint32_t time, uint32_t button, uint32_t state){
|
||||
char *state_str = (state == 1?"press":"release");
|
||||
if (button == BTN_LEFT){
|
||||
printf("pointer_button (left) %s\n", state_str);
|
||||
}
|
||||
else if (button == BTN_RIGHT){
|
||||
printf("pointer_button (right) %s\n", state_str);
|
||||
}
|
||||
else if (button == BTN_MIDDLE){
|
||||
printf("pointer_button (middle) %s\n", state_str);
|
||||
}
|
||||
else{
|
||||
printf("pointer_button (unidentified) %s\n", state_str);
|
||||
}
|
||||
if (state){
|
||||
ctx.button = button;
|
||||
ctx.button_serial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_axis(void *udata, struct wl_pointer *wl_pointer,
|
||||
uint32_t time, uint32_t axis, wl_fixed_t value){
|
||||
uint32_t time, uint32_t axis, wl_fixed_t fv){
|
||||
int v = wl_fixed_to_int(fv);
|
||||
printf("pointer_axis %u,%d\n", axis, v);
|
||||
}
|
||||
|
||||
const struct wl_pointer_listener pointer_listener = {
|
||||
|
|
@ -287,10 +336,10 @@ int main(){
|
|||
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.dim[0] = 640;
|
||||
ctx.dim[1] = 480;
|
||||
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);
|
||||
|
|
@ -313,37 +362,9 @@ int main(){
|
|||
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]);
|
||||
ctx.dim[0], ctx.dim[1]);
|
||||
|
||||
EGLConfig configs[64];
|
||||
EGLint config_cap = sizeof(configs)/sizeof(*configs);
|
||||
|
|
@ -434,61 +455,180 @@ int main(){
|
|||
|
||||
/* window sizing */
|
||||
CSD_Frame csd_frame = {0};
|
||||
int32_t csd_dim[2];
|
||||
int32_t csd_dim[2] = {0};
|
||||
{
|
||||
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];
|
||||
}
|
||||
for (int i = 0; i < 2; i += 1){
|
||||
int32_t d = ctx.config.dim[i] - csd_dim[i];
|
||||
if (!ctx.handled_first_size){
|
||||
d = ctx.dim[i];
|
||||
ctx.config.dim[i] = d + 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;
|
||||
}
|
||||
ctx.handled_first_size = 1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* frame cursor & interaction */
|
||||
CursorShape cursor_shape = CursorShape_Pointer;
|
||||
if (ctx.control_flags & WindowControlFlag_Resize){
|
||||
static const CursorShape cursor_box[] = {
|
||||
CursorShape_Resize_TopLeft, CursorShape_Resize_Top, CursorShape_Resize_TopRight,
|
||||
CursorShape_Resize_Left, CursorShape_Pointer, CursorShape_Resize_Right,
|
||||
CursorShape_Resize_BottomLeft, CursorShape_Resize_Bottom, CursorShape_Resize_BottomRight,
|
||||
};
|
||||
|
||||
static const enum xdg_toplevel_resize_edge xedge_box[] = {
|
||||
XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_TOP, XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT,
|
||||
XDG_TOPLEVEL_RESIZE_EDGE_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_NONE, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
|
||||
XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT,
|
||||
};
|
||||
|
||||
int l = (ctx.p[0] < SHADOW_MARGIN);
|
||||
int r = (!l && ctx.p[0] >= ctx.dim[0] + SHADOW_MARGIN);
|
||||
int t = (ctx.p[1] < SHADOW_MARGIN);
|
||||
int b = (!t && ctx.p[1] >= ctx.dim[1] + SHADOW_MARGIN);
|
||||
int loc = 3*(b - t) + (r - l);
|
||||
cursor_shape = cursor_box[4 + loc];
|
||||
if (ctx.button == BTN_LEFT){
|
||||
ctx.button = 0;
|
||||
if (loc != 0){
|
||||
xdg_toplevel_resize(ctx.main_xdg_toplevel, ctx.wl_seat,
|
||||
ctx.button_serial, xedge_box[4 + loc]);
|
||||
}
|
||||
else{
|
||||
xdg_toplevel_move(ctx.main_xdg_toplevel, ctx.wl_seat,
|
||||
ctx.button_serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* window frame commit */
|
||||
/* window frame render */
|
||||
if (csd){
|
||||
if (ctx.shadow_data != 0){
|
||||
munmap(ctx.shadow_data, ctx.shadow_size);
|
||||
ctx.shadow_data = 0;
|
||||
}
|
||||
if (ctx.shadow_wl_buffer != 0){
|
||||
wl_buffer_destroy(ctx.shadow_wl_buffer);
|
||||
ctx.shadow_wl_buffer = 0;
|
||||
}
|
||||
|
||||
{
|
||||
int dim[2];
|
||||
for (int i = 0; i < 2; i += 1){
|
||||
dim[i] = ctx.dim[i] + SHADOW_MARGIN*2;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
|
||||
{
|
||||
int x0 = SHADOW_MARGIN - SHADOW_THICK;
|
||||
int y0 = SHADOW_MARGIN - SHADOW_THICK;
|
||||
int x1 = x0 + ctx.dim[0] + SHADOW_THICK*2;
|
||||
int y1 = y0 + ctx.dim[1] + SHADOW_THICK*2;
|
||||
|
||||
if (x0 <= x && x < x1 && y0 <= y && y < y1){
|
||||
int xd0 = x - x0;
|
||||
int xd1 = x1 - x - 1;
|
||||
int yd0 = y - y0;
|
||||
int yd1 = y1 - y - 1;
|
||||
int d = Min(Min(xd0, xd1), Min(yd0, yd1));
|
||||
|
||||
if (d < SHADOW_THICK){
|
||||
int c = d*0xFF/SHADOW_THICK;
|
||||
((uint8_t*)pxl)[0] = 0;
|
||||
((uint8_t*)pxl)[1] = 0;
|
||||
((uint8_t*)pxl)[2] = 0;
|
||||
((uint8_t*)pxl)[3] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
pxl += 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct wl_region *region = wl_compositor_create_region(ctx.wl_compositor);
|
||||
wl_region_add(region, 0, 0, ctx.shadow_dim[0], ctx.shadow_dim[1]);
|
||||
wl_region_subtract(region, SHADOW_MARGIN, SHADOW_MARGIN,
|
||||
ctx.dim[0], ctx.dim[1]);
|
||||
wl_surface_set_input_region(ctx.shadow_wl_surface, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
{
|
||||
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_subsurface_set_position(ctx.shadow_wl_subsurface, -SHADOW_MARGIN, -SHADOW_MARGIN);
|
||||
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);
|
||||
}
|
||||
/* window frame commit */
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xdg_surface_set_window_geometry(ctx.main_xdg_surface,
|
||||
-csd_frame.border[0][0],
|
||||
-csd_frame.border[1][0],
|
||||
ctx.dim[0] + csd_dim[0],
|
||||
ctx.dim[1] + csd_dim[1]);
|
||||
|
||||
wl_egl_window_resize(ctx.main_wl_egl_window, ctx.dim[0], ctx.dim[1], 0, 0);
|
||||
|
||||
/* app update & render */
|
||||
{
|
||||
if (ctx.close_signal){
|
||||
|
|
@ -496,13 +636,29 @@ int main(){
|
|||
}
|
||||
|
||||
glDrawBuffer(GL_BACK);
|
||||
glViewport(0, 0, ctx.config.dim[0], ctx.config.dim[1]);
|
||||
glViewport(0, 0, ctx.dim[0], ctx.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);
|
||||
|
||||
/* commit new cursor */
|
||||
{
|
||||
struct wl_cursor *cursor = ctx.wl_cursors[cursor_shape];
|
||||
if (cursor != 0){
|
||||
struct wl_cursor_image *cursor_image = cursor->images[0];
|
||||
struct wl_buffer *cursor_buffer = wl_cursor_image_get_buffer(cursor_image);
|
||||
wl_surface_set_buffer_scale(ctx.cursor_surface, 1);
|
||||
wl_surface_attach(ctx.cursor_surface, cursor_buffer, 0, 0);
|
||||
wl_surface_damage_buffer(ctx.cursor_surface, 0, 0,
|
||||
cursor_image->width, cursor_image->height);
|
||||
wl_surface_commit(ctx.cursor_surface);
|
||||
wl_pointer_set_cursor(ctx.wl_pointer, ctx.hover_serial, ctx.cursor_surface,
|
||||
cursor_image->hotspot_x, cursor_image->hotspot_y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
|
@ -515,7 +671,11 @@ 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;
|
||||
for (int i = 0; i < 2; i += 1){
|
||||
for (int j = 0; j < 2; j += 1){
|
||||
frame.border[i][j] = SHADOW_MARGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(frame);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ typedef struct CursorTheme{
|
|||
int size;
|
||||
} CursorTheme;
|
||||
|
||||
typedef uint32_t CursorShape;
|
||||
enum{
|
||||
CursorShape_Hidden,
|
||||
CursorShape_Pointer,
|
||||
CursorShape_Resize_Top,
|
||||
CursorShape_Resize_Bottom,
|
||||
|
|
@ -125,6 +127,13 @@ typedef struct Ctx{
|
|||
Config config_staged;
|
||||
int32_t mmbox[2][2]; // [0][]:x [1][]:y [][0]:min [][1]:max
|
||||
int32_t dim[2];
|
||||
|
||||
uint32_t hover_serial;
|
||||
uint32_t button_serial;
|
||||
struct wl_surface *hover;
|
||||
int32_t p[2];
|
||||
uint32_t button;
|
||||
int handled_first_size;
|
||||
} Ctx;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue