Skip to content

[WIP] Wayland #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
60cface
Snake and gradient examples
versionpatch Jun 8, 2022
953d84a
Implemented wl_surface.c
versionpatch Jun 13, 2022
cdc804e
Wayland backend
versionpatch Jun 14, 2022
10135a0
Made surface object store a pointer to the SHM object to avoid needin…
versionpatch Jun 15, 2022
5282488
Wayland mouse and keyboard support.
versionpatch Jun 15, 2022
f45952f
Implemented window hiding. Fixed some formatting issues.
versionpatch Jun 15, 2022
03eb44e
Simple client side decoration setup
versionpatch Jun 16, 2022
a0c474d
Decoration title rendering
versionpatch Jun 17, 2022
acd94b2
Refactored some parts common between surface and decoration
versionpatch Jun 17, 2022
59c2556
Added close button
versionpatch Jun 17, 2022
51eae1b
Resize WIP
versionpatch Jun 21, 2022
fe0ff2d
Fixed resize memory problems
versionpatch Jun 21, 2022
3df780b
Decorations react to resize
versionpatch Jun 21, 2022
627d783
Moved resize time from buffer release to before drawing
versionpatch Jun 22, 2022
1ea160b
Allow disabling of decorations
versionpatch Jun 22, 2022
2c642b9
Added resize direction checks
versionpatch Jun 22, 2022
6c98065
Removed dependency on the decoration close button, a dummy buffer is …
versionpatch Jun 22, 2022
0be4c71
Cursor changes in resize region
versionpatch Jun 22, 2022
5c7906d
Backend stop, focus, middle mouse button
versionpatch Jun 23, 2022
0d18603
Added XDG decoration protocol
versionpatch Jun 23, 2022
7f08134
Added server side decorations
versionpatch Jun 23, 2022
437ee62
Linking
versionpatch Jun 23, 2022
d5c879a
Server side decoration fixes
versionpatch Jun 23, 2022
86f15be
Min Max buttons
versionpatch Jun 23, 2022
d14989a
Removed examples from wayland branch
versionpatch Jun 24, 2022
9f80d01
Refactored surface destruction
versionpatch Jun 27, 2022
fd06b92
Added asserts and the HAS_WAYLAND conditional to xdg-decor-protocol
versionpatch Jun 27, 2022
2fd0963
Modifiers + more fixes
versionpatch Jun 27, 2022
6f39813
Refactored keyboard file
versionpatch Jun 27, 2022
b9ea6f3
Frameless window fix
versionpatch Jun 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dune
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
gdi_keyboard gdi_backend gdi_target gdi_window gdi_surface
qtz_keyboard qtz_backend qtz_target qtz_window qtz_surface
x11_keysym x11_keyboard x11_backend x11_target x11_window x11_surface
wl_backend wl_target wl_window wl_surface xdg-shell-protocol
wl_backend wl_target wl_window wl_surface wl_decoration xdg-shell-protocol
window surface
path arc polygon polygonize poly_render
font_desc gdi_font qtz_font ft_font font
Expand Down
38 changes: 29 additions & 9 deletions src/implem/wayland/wl_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
#include <string.h>
#include <assert.h>
#include <time.h>

#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#include <wayland-client.h>
#include <wayland-cursor.h>
#include "xdg-shell-client-protocol.h"
#include <xkbcommon/xkbcommon.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>



#include "../event.h"
Expand Down Expand Up @@ -72,6 +72,9 @@ printf("Global: %s\n", interface);
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
wl_back->shm = (struct wl_shm *)
wl_registry_bind(registry, id, &wl_shm_interface, 1);
} else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
wl_back->subcompositor = (struct wl_subcompositor*)
wl_registry_bind(registry, id, &wl_subcompositor_interface,version);
}

}
Expand Down Expand Up @@ -129,9 +132,16 @@ _wl_pointer_enter_handler(
wl_back->cursor_image->hotspot_x,
wl_back->cursor_image->hotspot_y);
if (surface)
wl_back->focus_window = wl_surface_get_user_data(surface);
{
wl_back->focus_window = (wl_window_t*)wl_surface_get_user_data(surface);
if (surface == wl_back->focus_window->decoration->wl_surface)
wl_back->inside_decor = 1;
}
else
{
wl_back->focus_window = NULL;
wl_back->inside_decor = 1;
}
event_t evt;

}
Expand All @@ -143,7 +153,8 @@ _wl_pointer_leave_handler(
uint32_t serial,
struct wl_surface *surface)
{

wl_backend_t *wl_back = (wl_backend_t *)data;
wl_back->inside_decor = 0;
}

static void
Expand Down Expand Up @@ -178,20 +189,27 @@ _wl_pointer_button_handler(
uint32_t state)
{
//When the focus screen is hidden with a key down event for example, the key up event will still trigger. This check mitigates that.
if (wl_back->focus_window && wl_back->focus_window->base.visible) {
if (wl_back->focus_window && wl_back->focus_window->base.visible && !wl_back->inside_decor) {
wl_backend_t *wl_back = (wl_backend_t *)data;
event_t evt;
evt.type = EVENT_BUTTON;
evt.time = _wl_get_time();
evt.target = wl_back->focus_window;
//TODO : Support other buttons
evt.desc.button.button = (button == 0) ? BUTTON_LEFT : BUTTON_RIGHT;
//TODO : Find a way to get RMB's code (is it always 272?)
evt.desc.button.button = (button == 272) ? BUTTON_LEFT : BUTTON_RIGHT;
evt.desc.button.state = (state == WL_POINTER_BUTTON_STATE_PRESSED) ? BUTTON_DOWN : BUTTON_UP;
evt.desc.button.x = wl_back->mouse_posx / 256;
evt.desc.button.y = wl_back->mouse_posy / 256;
event_notify(wl_back->listener, &evt);
printf("button: 0x%x state: %d\n", button, state);
}

if (wl_back->inside_decor && state == WL_POINTER_BUTTON_STATE_PRESSED && button == 272)
{
printf("henlo");
xdg_toplevel_move(wl_back->focus_window->xdg_toplevel,wl_back->seat,serial);
}
}

static void
Expand Down Expand Up @@ -373,6 +391,7 @@ wl_backend_init(
wl_back->pointer = wl_seat_get_pointer(wl_back->seat);
if (wl_back->pointer)
wl_pointer_add_listener(wl_back->pointer, &_wl_pointer_listener, wl_back);
wl_back->inside_decor = 0;
/* Retrieve the keyboard, iinitiate xkb_context and add listener */
wl_back->keyboard = wl_seat_get_keyboard(wl_back->seat);
if (wl_back->keyboard) {
Expand Down Expand Up @@ -460,6 +479,7 @@ static void wl_callback_handle_frame(
evt.target = (wl_window_t*)data;
if (event_notify(wl_back->listener,&evt))
{
wl_decoration_present(wl_window->decoration);
evt.type = EVENT_PRESENT;
event_notify(wl_back->listener,&evt);
}
Expand Down
3 changes: 2 additions & 1 deletion src/implem/wayland/wl_backend_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ typedef struct wl_backend_t {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_subcompositor *subcompositor;
struct wl_seat *seat;
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
Expand All @@ -53,7 +54,7 @@ typedef struct wl_backend_t {
/*Mouse objects*/
wl_fixed_t mouse_posx;
wl_fixed_t mouse_posy;

uint8_t inside_decor;
} wl_backend_t;

extern wl_backend_t *wl_back;
Expand Down
158 changes: 158 additions & 0 deletions src/implem/wayland/wl_decoration.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/**************************************************************************/
/* */
/* Copyright 2022 OCamlPro */
/* */
/* All rights reserved. This file is distributed under the terms of the */
/* GNU Lesser General Public License version 2.1, with the special */
/* exception on linking described in the file LICENSE. */
/* */
/**************************************************************************/

#ifdef HAS_WAYLAND

#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>

#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <wayland-client.h>
#include <sys/mman.h>

#include "wl_decoration.h"
#include "wl_backend.h"
#include "wl_backend_internal.h"



//TODO : Factor this between surface and decoration
static void
_randname(
char *buf)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
long r = ts.tv_nsec;
for (int i = 0; i < 6; ++i) {
buf[i] = 'A'+(r&15)+(r&16)*2;
r >>= 5;
}
}
//TODO : Factor this between surface and decoration
static int
_create_shm_file()
{
int retries = 100;
do {
char name[] = "/canvas_shm-XXXXXX";
_randname(name + sizeof(name) - 7);
--retries;
int fd = shm_open(name, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600);
if (fd >= 0) {
shm_unlink(name);
return fd;
}
} while (retries > 0 && errno == EEXIST);
return -1;
}
//TODO : Factor this between surface and decoration
static int
_allocate_shm_file(
size_t size)
{
int fd = _create_shm_file();
if (fd < 0)
return -1;
int ret;
do {
ret = ftruncate(fd, size);
} while (ret < 0 && errno == EINTR);
if (ret < 0) {
close(fd);
return -1;
}
return fd;
}



wl_decoration_t*
wl_decoration_create(
struct wl_surface *parent,
uint32_t width
)
{

//TODO : Make this adapt to screen
uint32_t _decor_height = 40;

assert(parent != NULL);
wl_decoration_t *decor = (wl_decoration_t*)calloc(1, sizeof(wl_decoration_t));
if (decor == NULL)
return NULL;
decor->wl_surface = wl_compositor_create_surface(wl_back->compositor);
decor->wl_subsurface = wl_subcompositor_get_subsurface(wl_back->subcompositor,decor->wl_surface,parent);

//TODO : Factor this between surface and decoration
uint32_t shm_pool_size = width * _decor_height * 4;
int fd = _allocate_shm_file(shm_pool_size);
uint8_t *pool_data = (uint8_t *)mmap(NULL, shm_pool_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);

struct wl_shm_pool *pool = wl_shm_create_pool(wl_back->shm,
fd, shm_pool_size);
close(fd);

struct wl_buffer *wl_buffer =
wl_shm_pool_create_buffer(pool, 0, width, _decor_height, width * 4,
WL_SHM_FORMAT_ARGB8888); // or ARGB for alpha
wl_shm_pool_destroy(pool);

//TODO : Improve the design
for (int i = 0;i < width*_decor_height;i++)
{
pool_data[4*i] = 0;
pool_data[4*i + 1] = 0;
pool_data[4*i + 2] = 0;
pool_data[4*i + 3] = 255;
}

munmap(pool_data,shm_pool_size);

wl_surface_attach(decor->wl_surface,wl_buffer,0,0);
wl_subsurface_set_position(decor->wl_subsurface,0,-_decor_height);
decor->background_buffer = wl_buffer;

return decor;
}

void
wl_decoration_destroy(
wl_decoration_t *decoration
)
{
assert(decoration != NULL);
assert(decoration->background_buffer != NULL);
assert(decoration->wl_subsurface != NULL);
assert(decoration->wl_surface != NULL);

wl_buffer_destroy(decoration->background_buffer);
wl_subsurface_destroy(decoration->wl_subsurface);
wl_surface_destroy(decoration->wl_surface);
}

void
wl_decoration_present(
wl_decoration_t* decoration
)
{
wl_surface_commit(decoration->wl_surface);
}


#endif /*HAS_WAYLAND*/
46 changes: 46 additions & 0 deletions src/implem/wayland/wl_decoration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**************************************************************************/
/* */
/* Copyright 2022 OCamlPro */
/* */
/* All rights reserved. This file is distributed under the terms of the */
/* GNU Lesser General Public License version 2.1, with the special */
/* exception on linking described in the file LICENSE. */
/* */
/**************************************************************************/

#ifndef __WL_DECORATION_H
#define __WL_DECORATION_H

#include <stdint.h>
#include <stdbool.h>
#include <sys/mman.h>

#include <wayland-client.h>

#include "../color.h"

typedef struct wl_decoration_t {
struct wl_surface *wl_surface;
struct wl_subsurface *wl_subsurface;
struct wl_buffer *background_buffer;
} wl_decoration_t;

wl_decoration_t*
wl_decoration_create(
struct wl_surface *parent,
uint32_t width
);

void
wl_decoration_destroy(
wl_decoration_t *decoration
);

void
wl_decoration_present(
wl_decoration_t* decoration
);



#endif /* __WL_DECORATION_H */
9 changes: 8 additions & 1 deletion src/implem/wayland/wl_window.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,14 @@ wl_window_create(
window->base.width = clip_i32_to_i16(max(1, width));
window->base.height = clip_i32_to_i16(max(1, height));

window->title = title;

window->wl_surface = wl_compositor_create_surface(wl_back->compositor);
wl_surface_set_user_data(window->wl_surface,window);

window->decoration = wl_decoration_create(window->wl_surface,width);
wl_surface_set_user_data(window->decoration->wl_surface,window);

wl_backend_add_window(window);

return window;
Expand All @@ -122,6 +127,7 @@ wl_window_destroy(
wl_callback_destroy(window->wl_callback);
xdg_toplevel_destroy(window->xdg_toplevel);
xdg_surface_destroy(window->xdg_surface);
wl_decoration_destroy(window->decoration);
wl_surface_destroy(window->wl_surface);
free(window);
}
Expand Down Expand Up @@ -182,8 +188,9 @@ wl_window_show(
xdg_surface_add_listener(window->xdg_surface, &_wl_xdg_surface_listener, &window);
window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
xdg_toplevel_add_listener(window->xdg_toplevel,&_wl_xdg_toplevel_listener,window);
xdg_toplevel_set_title(window->xdg_toplevel,window->title);
window->base.visible = true;
wl_surface_commit(window->wl_surface);
wl_surface_commit(window->wl_surface);
}
_wl_window_update_position(window);

Expand Down
9 changes: 7 additions & 2 deletions src/implem/wayland/wl_window_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,23 @@
#include "xdg-shell-client-protocol.h"

#include "../window_internal.h"

#include "wl_decoration.h"

typedef struct wl_window_t {

/* Common to all windows */
window_t base;

/* Specific to Quartz windows */
/* Specific to Wayland windows */
struct wl_surface *wl_surface;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
struct wl_callback *wl_callback;
const char *title;

/*Client Side Decorations*/
//TODO : Check if KDE is used before enabling this
wl_decoration_t *decoration;

} wl_window_t;

Expand Down