Skip to content

Commit

Permalink
Wayland: Initial progress
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Jun 18, 2024
1 parent 6ccfdd7 commit 01766c0
Show file tree
Hide file tree
Showing 13 changed files with 864 additions and 12 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@
build/
.vscode/
.cache/

protocols/*.cpp
protocols/*.hpp
46 changes: 44 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ set(INCLUDE ${CMAKE_INSTALL_FULL_INCLUDEDIR})
set(LIBDIR ${CMAKE_INSTALL_FULL_LIBDIR})

find_package(PkgConfig REQUIRED)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols hyprutils>=0.1.2)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols hyprutils>=0.1.2 pixman-1 wayland-client)

configure_file(aquamarine.pc.in aquamarine.pc @ONLY)

Expand All @@ -36,14 +36,56 @@ file(GLOB_RECURSE PUBLIC_HEADERS CONFIGURE_DEPENDS "include/*.hpp")
add_library(aquamarine SHARED ${SRCFILES})
target_include_directories( aquamarine
PUBLIC "./include"
PRIVATE "./src"
PRIVATE "./src" "./src/include" "./protocols"
)
set_target_properties(aquamarine PROPERTIES
VERSION ${AQUAMARINE_VERSION}
SOVERSION 0
)
target_link_libraries(aquamarine PkgConfig::deps)

# Protocols
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
pkg_get_variable(WAYLAND_CLIENT_DIR wayland-client pkgdatadir)
message(STATUS "Found wayland-client at ${WAYLAND_CLIENT_DIR}")

function(protocolNew protoPath protoName external)
if (external)
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
else()
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
endif()
add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp
${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp
COMMAND hyprwayland-scanner --client ${path}/${protoName}.xml ${CMAKE_SOURCE_DIR}/protocols/
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
target_sources(aquamarine PRIVATE protocols/${protoName}.cpp protocols/${protoName}.hpp)
endfunction()
function(protocolWayland)
add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
COMMAND hyprwayland-scanner --wayland-enums --client ${WAYLAND_CLIENT_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
target_sources(aquamarine PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
endfunction()

protocolWayland()

protocolNew("stable/xdg-shell" "xdg-shell" false)

# tests
add_custom_target(tests)

add_executable(simpleWindow "tests/SimpleWindow.cpp")
target_link_libraries(simpleWindow PRIVATE aquamarine PkgConfig::deps)
add_test(NAME "simpleWindow" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND simpleWindow "simpleWindow")
add_dependencies(tests simpleWindow)

# Installation
install(TARGETS aquamarine)
install(DIRECTORY "include/aquamarine" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
Expand Down
39 changes: 35 additions & 4 deletions include/aquamarine/backend/Backend.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#pragma once

#include <hyprutils/memory/SharedPtr.hpp>
#include <hyprutils/signal/Signal.hpp>
#include <vector>
#include <functional>
#include <mutex>
#include <condition_variable>

namespace Aquamarine {
enum eBackendType {
Expand Down Expand Up @@ -47,8 +50,13 @@ namespace Aquamarine {

class IBackendImplementation {
public:
virtual ~IBackendImplementation();
virtual eBackendType type() = 0;
virtual ~IBackendImplementation() {
;
}
virtual eBackendType type() = 0;
virtual bool start() = 0;
virtual int pollFD() = 0;
virtual bool dispatchEvents() = 0;
};

class CBackend {
Expand All @@ -63,10 +71,33 @@ namespace Aquamarine {

void log(eBackendLogLevel level, const std::string& msg);

/* Enters the event loop synchronously. For simple clients, this is probably what you want. For more complex ones,
see async methods further below */
void enterLoop();

struct {
Hyprutils::Signal::CSignal newOutput;
Hyprutils::Signal::CSignal newPointer;
Hyprutils::Signal::CSignal newKeyboard;
Hyprutils::Signal::CSignal newTouch;
} events;

private:
CBackend();

std::vector<IBackendImplementation> implementations;
SBackendOptions options;
bool terminate = false;

std::vector<SBackendImplementationOptions> implementationOptions;
std::vector<Hyprutils::Memory::CSharedPointer<IBackendImplementation>> implementations;
SBackendOptions options;

//
struct {
std::condition_variable loopSignal;
std::mutex loopMutex;
std::atomic<bool> shouldProcess = false;
std::mutex loopRequestMutex;
std::mutex eventLock;
} m_sEventLoopInternals;
};
};
106 changes: 106 additions & 0 deletions include/aquamarine/backend/Wayland.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#pragma once

#include "./Backend.hpp"
#include "../output/Output.hpp"
#include "../input/Input.hpp"
#include <hyprutils/memory/WeakPtr.hpp>
#include <wayland-client.h>
#include <wayland.hpp>
#include <xdg-shell.hpp>

namespace Aquamarine {
class CBackend;
class CWaylandBackend;

class CWaylandOutput : public IOutput {
public:
virtual ~CWaylandOutput();
virtual void commit();

private:
CWaylandOutput(const std::string& name_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);

std::string name;
Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend;

struct {
Hyprutils::Memory::CSharedPointer<CWlSurface> surface;
Hyprutils::Memory::CSharedPointer<CXdgSurface> xdgSurface;
Hyprutils::Memory::CSharedPointer<CXdgToplevel> xdgToplevel;
} waylandState;

friend class CWaylandBackend;
friend class CWaylandPointer;
};

class CWaylandKeyboard : public IKeyboard {
public:
CWaylandKeyboard(Hyprutils::Memory::CSharedPointer<CWlKeyboard> keyboard_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
virtual ~CWaylandKeyboard();

virtual const std::string& getName();

Hyprutils::Memory::CSharedPointer<CWlKeyboard> keyboard;
Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend;

private:
const std::string name = "wl_keyboard";
};

class CWaylandPointer : public IPointer {
public:
CWaylandPointer(Hyprutils::Memory::CSharedPointer<CWlPointer> pointer_, Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend_);
virtual ~CWaylandPointer();

virtual const std::string& getName();

Hyprutils::Memory::CSharedPointer<CWlPointer> pointer;
Hyprutils::Memory::CWeakPointer<CWaylandBackend> backend;

private:
const std::string name = "wl_pointer";
};

class CWaylandBackend : public IBackendImplementation {
public:
virtual ~CWaylandBackend();
virtual eBackendType type();
virtual bool start();
virtual int pollFD();
virtual bool dispatchEvents();

Hyprutils::Memory::CWeakPointer<CWaylandBackend> self;

private:
CWaylandBackend(Hyprutils::Memory::CSharedPointer<CBackend> backend);

void initSeat();
void initShell();
void createOutput(const std::string& szName);

//
Hyprutils::Memory::CWeakPointer<CBackend> backend;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandOutput>> outputs;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandKeyboard>> keyboards;
std::vector<Hyprutils::Memory::CSharedPointer<CWaylandPointer>> pointers;

// pointer focus
Hyprutils::Memory::CWeakPointer<CWaylandOutput> focusedOutput;
uint32_t lastEnterSerial = 0;

struct {
wl_display* display = nullptr;

// hw-s types
Hyprutils::Memory::CSharedPointer<CWlRegistry> registry;
Hyprutils::Memory::CSharedPointer<CWlSeat> seat;
Hyprutils::Memory::CSharedPointer<CXdgWmBase> xdg;
Hyprutils::Memory::CSharedPointer<CWlCompositor> compositor;
} waylandState;

friend class CBackend;
friend class CWaylandKeyboard;
friend class CWaylandPointer;
friend class CWaylandOutput;
};
};
72 changes: 72 additions & 0 deletions include/aquamarine/buffer/Buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once

#include <array>
#include <tuple>
#include <hyprutils/signal/Signal.hpp>
#include <hyprutils/math/Region.hpp>

namespace Aquamarine {
enum eBufferCapability {
BUFFER_CAPABILITY_DATAPTR = (1 << 0),
};

enum eBufferType {
BUFFER_TYPE_DMABUF = 0,
BUFFER_TYPE_SHM,
BUFFER_TYPE_MISC,
};

class CWLBufferResource;

struct SDMABUFAttrs {
bool success = false;
Hyprutils::Math::Vector2D size;
uint32_t format = 0; // fourcc
uint64_t modifier = 0;

int planes = 1;
std::array<uint32_t, 4> offsets = {0};
std::array<uint32_t, 4> strides = {0};
std::array<int, 4> fds = {-1, -1, -1, -1};
};

struct SSHMAttrs {
bool success = false;
int fd = 0;
uint32_t format = 0;
Hyprutils::Math::Vector2D size;
int stride = 0;
int64_t offset = 0;
};

class IBuffer {
public:
virtual ~IBuffer() {
;
};

virtual eBufferCapability caps() = 0;
virtual eBufferType type() = 0;
virtual void update(const Hyprutils::Math::CRegion& damage) = 0;
virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
virtual SDMABUFAttrs dmabuf();
virtual SSHMAttrs shm();
virtual std::tuple<uint8_t*, uint32_t, size_t> beginDataPtr(uint32_t flags);
virtual void endDataPtr();
virtual void sendRelease();
virtual void lock();
virtual void unlock();
virtual bool locked();

Hyprutils::Math::Vector2D size;
bool opaque = false;

struct {
Hyprutils::Signal::CSignal destroy;
} events;

private:
int locks = 0;
};

};
50 changes: 48 additions & 2 deletions include/aquamarine/input/Input.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
#pragma once

#include <hyprutils/signal/Signal.hpp>
#include <hyprutils/math/Vector2D.hpp>

struct libinput_device;

namespace Aquamarine {
class IKeyboard {
public:
virtual libinput_device* getLibinputHandle();
virtual ~IKeyboard() {
events.destroy.emit();
}
virtual libinput_device* getLibinputHandle();
virtual const std::string& getName() = 0;

struct SKeyEvent {
uint32_t timeMs = 0;
uint32_t key = 0;
bool pressed = false;
};

struct SModifiersEvent {
uint32_t depressed = 0, latched = 0, locked = 0, group = 0;
};

struct {
Hyprutils::Signal::CSignal destroy;
Expand All @@ -18,14 +33,45 @@ namespace Aquamarine {

class IPointer {
public:
virtual libinput_device* getLibinputHandle();
virtual ~IPointer() {
events.destroy.emit();
}

virtual libinput_device* getLibinputHandle();
virtual const std::string& getName() = 0;

enum ePointerAxis {
AQ_POINTER_AXIS_VERTICAL = 0,
AQ_POINTER_AXIS_HORIZONTAL,
};

struct SMoveEvent {
Hyprutils::Math::Vector2D delta;
};

struct SWarpEvent {
Hyprutils::Math::Vector2D absolute;
};

struct SButtonEvent {
uint32_t timeMs = 0;
uint32_t button = 0;
bool pressed = false;
};

struct SAxisEvent {
uint32_t timeMs = 0;
ePointerAxis axis = AQ_POINTER_AXIS_VERTICAL;
double value = 0.0;
};

struct {
Hyprutils::Signal::CSignal destroy;
Hyprutils::Signal::CSignal move;
Hyprutils::Signal::CSignal warp;
Hyprutils::Signal::CSignal button;
Hyprutils::Signal::CSignal axis;
Hyprutils::Signal::CSignal frame;
} events;
};
}
Loading

0 comments on commit 01766c0

Please sign in to comment.