Wayland example window

This commit is contained in:
jmsgrogan 2022-05-18 08:42:44 +01:00
parent 160b746182
commit 26f54c4581
30 changed files with 825 additions and 22 deletions

View file

@ -20,8 +20,12 @@ list(APPEND core_LIB_INCLUDES
file_utilities/BinaryFile.cpp file_utilities/BinaryFile.cpp
file_utilities/File.cpp file_utilities/File.cpp
file_utilities/FileFormats.cpp file_utilities/FileFormats.cpp
memory/SharedMemory.cpp
RandomUtils.cpp
StringUtils.cpp StringUtils.cpp
http/HttpResponse.cpp) http/HttpResponse.cpp
http/HttpHeader.cpp
http/HttpRequest.cpp)
# add the executable # add the executable
add_library(core SHARED ${core_LIB_INCLUDES} ${core_HEADERS}) add_library(core SHARED ${core_LIB_INCLUDES} ${core_HEADERS})
@ -30,6 +34,7 @@ target_include_directories(core PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/file_utilities" "${CMAKE_CURRENT_SOURCE_DIR}/file_utilities"
"${CMAKE_CURRENT_SOURCE_DIR}/loggers" "${CMAKE_CURRENT_SOURCE_DIR}/loggers"
"${CMAKE_CURRENT_SOURCE_DIR}/memory"
) )
set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
set_property(TARGET core PROPERTY FOLDER src) set_property(TARGET core PROPERTY FOLDER src)

22
src/core/RandomUtils.cpp Normal file
View file

@ -0,0 +1,22 @@
#include "RandomUtils.h"
#include <random>
#include <algorithm>
#include <iterator>
std::vector<unsigned> RandomUtils::getRandomVecUnsigned(std::size_t size)
{
std::random_device rnd_device;
std::mt19937 mersenne_engine {rnd_device()};
std::uniform_int_distribution<unsigned> dist {0, 9};
auto generator = [&dist, &mersenne_engine]()
{
return dist(mersenne_engine);
};
std::vector<unsigned> vec(size);
std::generate(std::begin(vec), std::end(vec), generator);
return vec;
}

10
src/core/RandomUtils.h Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include <vector>
class RandomUtils
{
public:
static std::vector<unsigned> getRandomVecUnsigned(std::size_t size);
};

View file

@ -13,6 +13,7 @@ public:
static constexpr char EQUALS = '='; static constexpr char EQUALS = '=';
static constexpr char DOUBLE_QUOTE = '"'; static constexpr char DOUBLE_QUOTE = '"';
static constexpr char SINGLE_QUOTE = '\''; static constexpr char SINGLE_QUOTE = '\'';
static constexpr char COLON = ':';
static bool IsAlphaNumeric(char c); static bool IsAlphaNumeric(char c);
static bool IsSpace(char c); static bool IsSpace(char c);

View file

@ -0,0 +1,80 @@
#include "HttpHeader.h"
#include "StringUtils.h"
void HttpHeader::parse(const std::vector<std::string >& message)
{
std::string tag;
std::string value;
bool foundDelimiter{false};
for (const auto& line : message)
{
for(std::size_t idx = 0; idx< line.size(); idx++)
{
const auto c = line[idx];
if (c == StringUtils::COLON)
{
foundDelimiter = true;
}
else if(foundDelimiter)
{
value.push_back(c);
}
else
{
tag.push_back(c);
}
}
}
if (tag.empty() || value.empty())
{
return;
}
if (tag == "Host")
{
mHost = value;
}
else if (tag == "User-Agent")
{
mUserAgent = value;
}
else if (tag == "Accept")
{
mAccept = value;
}
else if (tag == "Accept-Language")
{
mAcceptLanguage = value;
}
else if (tag == "Accept-Encoding")
{
mAcceptEncoding = value;
}
else if (tag == "Connection")
{
mConnection = value;
}
else if (tag == "Referer")
{
mReferer = value;
}
else if (tag == "Sec-Fetch-Dest")
{
mSecFetchDest = value;
}
else if (tag == "Sec-Fetch-Mode")
{
mSecFetchMode = value;
}
else if (tag == "Sec-Fetch-Site")
{
mSecFetchSite = value;
}
else
{
mOtherFields[tag] = value;
}
}

View file

@ -0,0 +1,26 @@
#pragma once
#include <string>
#include <vector>
#include <map>
class HttpHeader
{
public:
void parse(const std::vector<std::string >& message);
private:
std::string mHost;
std::string mUserAgent;
std::string mAccept;
std::string mAcceptLanguage;
std::string mAcceptEncoding;
std::string mConnection;
std::string mReferer;
std::string mSecFetchDest;
std::string mSecFetchMode;
std::string mSecFetchSite;
std::map<std::string, std::string> mOtherFields;
};

View file

@ -0,0 +1,68 @@
#include "HttpRequest.h"
#include "StringUtils.h"
#include <sstream>
void HttpRequest::parseMessage(const std::string& message)
{
std::stringstream ss(message);
std::string buffer;
bool firstLine {true};
std::vector<std::string> headers;
while(std::getline(ss, buffer, '\n'))
{
if (firstLine)
{
parseFirstLine(buffer);
firstLine = false;
}
else
{
headers.push_back(buffer);
}
}
mHeader.parse(headers);
}
void HttpRequest::parseFirstLine(const std::string& line)
{
bool inPath{false};
bool inMethod{true};
bool inProtocol{false};
for (std::size_t idx=0; idx<line.size();idx++)
{
const auto c = line[idx];
if (inPath)
{
if (StringUtils::IsSpace(c))
{
inPath = false;
inMethod = true;
}
else
{
mMethod.push_back(c);
}
}
else if (inMethod)
{
if (StringUtils::IsSpace(c))
{
inMethod = false;
inProtocol = true;
}
else
{
mPath.push_back(c);
}
}
else if (inProtocol)
{
mProtocolVersion.push_back(c);
}
}
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "HttpHeader.h"
#include <string>
class HttpRequest
{
public:
HttpRequest() = default;
void parseMessage(const std::string& message);
private:
void parseFirstLine(const std::string& line);
HttpHeader mHeader;
std::string mMethod;
std::string mPath;
std::string mProtocolVersion;
};

View file

@ -5,11 +5,6 @@
class HttpResponse class HttpResponse
{ {
std::string mHttpVersion;
std::string mResponseCode;
std::string mContentType;
std::string mBody;
public: public:
HttpResponse(); HttpResponse();
@ -23,4 +18,10 @@ public:
std::string GetHeaderString() const; std::string GetHeaderString() const;
std::string ToString() const; std::string ToString() const;
private:
std::string mHttpVersion;
std::string mResponseCode;
std::string mContentType;
std::string mBody;
}; };

View file

@ -0,0 +1,68 @@
#include "SharedMemory.h"
#include "RandomUtils.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
void SharedMemory::allocate(const std::string& namePrefix, std::size_t size)
{
createFile(namePrefix);
if (!mIsValid)
{
return;
}
int ret{-1};
do {
ret = ftruncate(mFileDescriptor, size);
} while (ret < 0 && errno == EINTR);
if (ret < 0)
{
close(mFileDescriptor);
mIsValid = false;
}
}
int SharedMemory::getFileDescriptor() const
{
return mFileDescriptor;
}
bool SharedMemory::isValid() const
{
return mIsValid;
}
void SharedMemory::createFile(const std::string& namePrefix)
{
unsigned retries = 100;
do {
const auto name = getRandomName(namePrefix);
--retries;
const int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd >= 0)
{
shm_unlink(name.c_str());
mFileDescriptor = fd;
mIsValid = true;
break;
}
} while (retries > 0 && errno == EEXIST);
}
std::string SharedMemory::getRandomName(const std::string& namePrefix) const
{
std::string randomSuffix;
for (const auto entry : RandomUtils::getRandomVecUnsigned(6))
{
randomSuffix += std::to_string(entry);
}
return namePrefix + randomSuffix;
}

View file

@ -0,0 +1,22 @@
#pragma once
#include <string>
class SharedMemory
{
public:
void allocate(const std::string& namePrefix, std::size_t size);
int getFileDescriptor() const;
bool isValid() const;
private:
void createFile(const std::string& namePrefix);
std::string getRandomName(const std::string& namePrefix) const;
int mFileDescriptor{0};
bool mIsValid{false};
};

View file

@ -8,11 +8,13 @@ list(APPEND network_HEADERS
NetworkManager.h NetworkManager.h
sockets/Socket.h sockets/Socket.h
sockets/SocketInterface.h sockets/SocketInterface.h
sockets/ISocketMessageHandler.h
) )
list(APPEND network_LIB_INCLUDES list(APPEND network_LIB_INCLUDES
NetworkManager.cpp NetworkManager.cpp
sockets/Socket.cpp sockets/Socket.cpp
web/HttpMessageHandler.cpp
) )
add_library(network SHARED ${network_LIB_INCLUDES} ${platform_INCLUDES} ${network_HEADERS}) add_library(network SHARED ${network_LIB_INCLUDES} ${platform_INCLUDES} ${network_HEADERS})
@ -20,6 +22,7 @@ add_library(network SHARED ${network_LIB_INCLUDES} ${platform_INCLUDES} ${networ
target_include_directories(network PUBLIC target_include_directories(network PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/sockets" "${CMAKE_CURRENT_SOURCE_DIR}/sockets"
"${CMAKE_CURRENT_SOURCE_DIR}/web"
"${PROJECT_SOURCE_DIR}/src/core/http" "${PROJECT_SOURCE_DIR}/src/core/http"
) )
set_target_properties( network PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) set_target_properties( network PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )

View file

@ -3,6 +3,8 @@
#include "UnixSocketInterface.h" #include "UnixSocketInterface.h"
#endif #endif
#include <iostream>
NetworkManager::NetworkManager() NetworkManager::NetworkManager()
: mActiveSockets(), : mActiveSockets(),
mSocketInterface() mSocketInterface()
@ -29,6 +31,7 @@ void NetworkManager::Initialize()
void NetworkManager::RunHttpServer() void NetworkManager::RunHttpServer()
{ {
std::cout << "Running http server" << std::endl;
if (!mSocketInterface) if (!mSocketInterface)
{ {
Initialize(); Initialize();
@ -40,6 +43,19 @@ void NetworkManager::RunHttpServer()
mSocketInterface->Run(socket); mSocketInterface->Run(socket);
} }
void NetworkManager::RunHttpClient()
{
std::cout << "Running http client" << std::endl;
if (!mSocketInterface)
{
Initialize();
}
auto socket = Socket::Create();
mSocketInterface->InitializeSocket(socket, "127.0.0.1");
mSocketInterface->Write(socket, "Hello Friend");
}
void NetworkManager::ShutDown() void NetworkManager::ShutDown()
{ {

View file

@ -20,11 +20,14 @@ public:
void RunHttpServer(); void RunHttpServer();
void RunHttpClient();
void ShutDown(); void ShutDown();
private: private:
std::vector<SocketPtr> mActiveSockets; std::vector<SocketPtr> mActiveSockets;
ISocketInterfaceUPtr mSocketInterface; ISocketInterfaceUPtr mSocketInterface;
}; };
using NetworkManagerUPtr = std::unique_ptr<NetworkManager>; using NetworkManagerUPtr = std::unique_ptr<NetworkManager>;

View file

@ -0,0 +1,10 @@
#pragma once
#include <string>
class ISocketMessageHandler
{
public:
virtual ~ISocketMessageHandler() = default;
virtual std::string onMessage(const std::string& message) = 0;
};

View file

@ -47,3 +47,14 @@ unsigned Socket::GetPort() const
{ {
return mPort; return mPort;
} }
std::string Socket::getAddress() const
{
return mAddress;
}
void Socket::setAddress(const std::string& address)
{
mAddress = address;
}

View file

@ -26,11 +26,15 @@ public:
void SetMessage(const std::string& message); void SetMessage(const std::string& message);
std::string getAddress() const;
void setAddress(const std::string& address);
private: private:
SocketHandle mHandle; SocketHandle mHandle;
unsigned mPort{0}; unsigned mPort{0};
std::string mMessage; std::string mMessage;
std::string mAddress;
}; };
using SocketPtr = std::unique_ptr<Socket>; using SocketPtr = std::unique_ptr<Socket>;

View file

@ -13,9 +13,11 @@ public:
virtual ~ISocketInterface() = default; virtual ~ISocketInterface() = default;
virtual void InitializeSocket(const SocketPtr& socket) = 0; virtual void InitializeSocket(const SocketPtr& socket, const std::string& address = {}) = 0;
virtual void Listen(const SocketPtr& socket) = 0; virtual void Listen(const SocketPtr& socket) = 0;
virtual void Run(const SocketPtr& socket) = 0; virtual void Run(const SocketPtr& socket) = 0;
virtual void Write(const SocketPtr& socket, const std::string& message) = 0;
}; };
using ISocketInterfaceUPtr = std::unique_ptr<ISocketInterface>; using ISocketInterfaceUPtr = std::unique_ptr<ISocketInterface>;

View file

@ -2,17 +2,20 @@
#include "HttpResponse.h" #include "HttpResponse.h"
#include "HttpMessageHandler.h"
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h>
UnixSocketInterface::UnixSocketInterface() UnixSocketInterface::UnixSocketInterface()
: mBufferSize(1024) : mBufferSize(1024)
{ {
mMessageHandler = std::make_unique<HttpMessageHandler>();
} }
std::unique_ptr<UnixSocketInterface> UnixSocketInterface::Create() std::unique_ptr<UnixSocketInterface> UnixSocketInterface::Create()
@ -20,10 +23,61 @@ std::unique_ptr<UnixSocketInterface> UnixSocketInterface::Create()
return std::make_unique<UnixSocketInterface>(); return std::make_unique<UnixSocketInterface>();
} }
void UnixSocketInterface::InitializeSocket(const SocketPtr& socketPtr) UnixSocketInterface::~UnixSocketInterface()
{ {
auto handle = socket(AF_INET, SOCK_STREAM, 0);
}
void UnixSocketInterface::InitializeSocket(const SocketPtr& socketPtr, const std::string& address)
{
auto handle = ::socket(AF_INET, SOCK_STREAM, 0);
socketPtr->SetHandle(handle); socketPtr->SetHandle(handle);
if (!address.empty())
{
socketPtr->setAddress(address);
}
}
void UnixSocketInterface::Write(const SocketPtr& socket, const std::string& message)
{
if(socket->GetHandle() < 0)
{
std::cerr << "Error opening socket" << std::endl;
return;
}
const auto port = static_cast<int>(socket->GetPort());
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
inet_aton(socket->getAddress().c_str(), &serv_addr.sin_addr);
serv_addr.sin_port = htons(port);
int result = connect(socket->GetHandle(), (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if(result< 0)
{
std::cerr << "Error connecting to socket" << std::endl;
return;
}
auto n = write(socket->GetHandle(), message.c_str(), message.length());
if (n < 0)
{
std::cerr << "Error on write" << std::endl;
return;
}
char buffer[mBufferSize] = {0};
int res = read(socket->GetHandle(), buffer, mBufferSize);
if (res < 0)
{
std::cerr << "Error on read" << std::endl;
return;
}
socket->SetMessage(buffer);
std::cout << "Here is the message: " << buffer << std::endl;
} }
void UnixSocketInterface::Listen(const SocketPtr& socket) void UnixSocketInterface::Listen(const SocketPtr& socket)
@ -34,7 +88,7 @@ void UnixSocketInterface::Listen(const SocketPtr& socket)
return; return;
} }
int port = static_cast<int>(socket->GetPort()); const auto port = static_cast<int>(socket->GetPort());
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)); memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; serv_addr.sin_family = AF_INET;
@ -63,8 +117,7 @@ void UnixSocketInterface::Run(const SocketPtr& socket)
socklen_t clilen = sizeof(cli_addr); socklen_t clilen = sizeof(cli_addr);
while(true) while(true)
{ {
auto new_socket_handle = accept(socket->GetHandle(), const auto new_socket_handle = accept(socket->GetHandle(), (struct sockaddr *) &cli_addr, &clilen);
(struct sockaddr *) &cli_addr, &clilen);
if (new_socket_handle < 0) if (new_socket_handle < 0)
{ {
std::cerr << "Error on accept" << std::endl; std::cerr << "Error on accept" << std::endl;
@ -81,11 +134,8 @@ void UnixSocketInterface::Run(const SocketPtr& socket)
socket->SetMessage(buffer); socket->SetMessage(buffer);
std::cout << "Here is the message: " << buffer << std::endl; std::cout << "Here is the message: " << buffer << std::endl;
HttpResponse response; const auto response = mMessageHandler->onMessage(buffer);
response.SetBody("Hello world!"); n = write(new_socket_handle, response.c_str(), response.length());
auto response_message = response.ToString();
n = write(new_socket_handle, response_message.c_str(), response_message.length());
if (n < 0) if (n < 0)
{ {
std::cerr << "Error on write" << std::endl; std::cerr << "Error on write" << std::endl;

View file

@ -6,6 +6,8 @@
#include <memory> #include <memory>
#include <map> #include <map>
class ISocketMessageHandler;
class UnixSocketInterface : public ISocketInterface class UnixSocketInterface : public ISocketInterface
{ {
@ -13,19 +15,22 @@ public:
UnixSocketInterface(); UnixSocketInterface();
virtual ~UnixSocketInterface() = default; virtual ~UnixSocketInterface();
static std::unique_ptr<UnixSocketInterface> Create(); static std::unique_ptr<UnixSocketInterface> Create();
void InitializeSocket(const SocketPtr& socket) override; void InitializeSocket(const SocketPtr& socket, const std::string& address = {}) override;
void Listen(const SocketPtr& socket) override; void Listen(const SocketPtr& socket) override;
void Write(const SocketPtr& socket, const std::string& message) override;
void Run(const SocketPtr& socket) override; void Run(const SocketPtr& socket) override;
private: private:
std::size_t mBufferSize { 0 }; std::size_t mBufferSize { 0 };
std::unique_ptr<ISocketMessageHandler> mMessageHandler;
}; };
using UnixSocketInterfacePtr = std::unique_ptr<UnixSocketInterface>; using UnixSocketInterfacePtr = std::unique_ptr<UnixSocketInterface>;

View file

@ -0,0 +1,17 @@
#include "HttpMessageHandler.h"
#include "HttpRequest.h"
#include "HttpResponse.h"
std::string HttpMessageHandler::onMessage(const std::string& message)
{
HttpRequest request;
request.parseMessage(message);
HttpResponse response;
response.SetBody("Hello world!");
const auto response_message = response.ToString();
return response_message;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "ISocketMessageHandler.h"
class HttpMessageHandler : public ISocketMessageHandler
{
public:
std::string onMessage(const std::string& message) override;
};

View file

@ -11,10 +11,36 @@ list(APPEND platform_INCLUDES
ui_interfaces/x11/XcbLayerInterface.cpp ui_interfaces/x11/XcbLayerInterface.cpp
ui_interfaces/x11/XcbTextInterface.cpp ui_interfaces/x11/XcbTextInterface.cpp
ui_interfaces/x11/XcbKeyboard.cpp ui_interfaces/x11/XcbKeyboard.cpp
ui_interfaces/x11/GlxInterface.cpp) ui_interfaces/x11/GlxInterface.cpp
ui_interfaces/wayland/WaylandWindowInterface.cpp
)
list(APPEND platform_LIBS list(APPEND platform_LIBS
X11 X11-xcb xcb ) X11 X11-xcb xcb )
find_path(
WAYLAND_CLIENT_INCLUDE_DIR
NAMES wayland-client.h
)
find_path(
WAYLAND_EXTENSIONS_INCLUDE_DIR
NAMES xdg-shell-client-protocol.h
HINTS ENV WAYLAND_EXTENSION_DIR
)
find_library(
WAYLAND_CLIENT_LIBRARY
NAMES wayland-client libwayland-client
)
list(APPEND platform_INCLUDES
ui_interfaces/win32/Win32UIInterface.h
${WAYLAND_EXTENSIONS_INCLUDE_DIR}/xdg-shell-protocol.cpp
)
else() else()
list(APPEND platform_INCLUDES list(APPEND platform_INCLUDES
ui_interfaces/win32/Win32UIInterface.h ui_interfaces/win32/Win32UIInterface.h
@ -38,15 +64,18 @@ target_include_directories(windows PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/managers" "${CMAKE_CURRENT_SOURCE_DIR}/managers"
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/x11" "${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/x11"
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/wayland"
"${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32" "${CMAKE_CURRENT_SOURCE_DIR}/ui_interfaces/win32"
"${PROJECT_SOURCE_DIR}/src/core" "${PROJECT_SOURCE_DIR}/src/core"
"${PROJECT_SOURCE_DIR}/src/geometry" "${PROJECT_SOURCE_DIR}/src/geometry"
"${PROJECT_SOURCE_DIR}/src/graphics" "${PROJECT_SOURCE_DIR}/src/graphics"
"${PROJECT_SOURCE_DIR}/src/ui_elements" "${PROJECT_SOURCE_DIR}/src/ui_elements"
"${PROJECT_SOURCE_DIR}/src/ui_elements/widgets" "${PROJECT_SOURCE_DIR}/src/ui_elements/widgets"
${WAYLAND_CLIENT_INCLUDE_DIR}
${WAYLAND_EXTENSIONS_INCLUDE_DIR}
) )
target_link_libraries(windows PUBLIC ${platform_LIBS} core geometry graphics ui_elements) target_link_libraries(windows PUBLIC ${platform_LIBS} core geometry graphics ui_elements ${WAYLAND_CLIENT_LIBRARY})
set_property(TARGET windows PROPERTY FOLDER src) set_property(TARGET windows PROPERTY FOLDER src)
set_target_properties( windows PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) set_target_properties( windows PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )

View file

@ -0,0 +1 @@
#include "WaylandWindowInterface.h"

View file

@ -0,0 +1,263 @@
#pragma once
#include "wayland-client.h"
#include "xdg-shell-client-protocol.h"
#include "Window.h"
#include "SharedMemory.h"
#include <iostream>
#include <cstring>
#include <sys/mman.h>
#include <unistd.h>
#include <memory>
class WaylandWindowInterface
{
public:
WaylandWindowInterface()
{
auto registry_handle_global = [](void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version)
{
auto thisClass = static_cast<WaylandWindowInterface*>(data);
printf("interface: '%s', version: %d, name: %d\n", interface, version, name);
if (strcmp(interface, wl_compositor_interface.name) == 0)
{
thisClass->setCompositor(static_cast<wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 4)));
}
else if (strcmp(interface, wl_shm_interface.name) == 0)
{
thisClass->setSharedMemory(static_cast<wl_shm*>(wl_registry_bind(registry, name, &wl_shm_interface, 1)));
}
else if (strcmp(interface, xdg_wm_base_interface.name) == 0)
{
thisClass->setXdgBase(static_cast<xdg_wm_base*>(wl_registry_bind(registry, name, &xdg_wm_base_interface, 1)));
}
};
auto registry_handle_global_remove = [](void *data, struct wl_registry *registry,
uint32_t name)
{
// This space deliberately left blank;
};
mRegistryListener.global = registry_handle_global;
mRegistryListener.global_remove = registry_handle_global_remove;
}
void setXdgBase(xdg_wm_base* xdg_base)
{
mXdgBase = xdg_base;
auto xdg_ping_handler = [](void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
{
auto thisClass = static_cast<WaylandWindowInterface*>(data);
thisClass->doXdgPong(serial);
};
mXdgBaseListener.ping = xdg_ping_handler;
xdg_wm_base_add_listener(mXdgBase, &mXdgBaseListener, this);
}
void doXdgPong(uint32_t serial)
{
xdg_wm_base_pong(mXdgBase, serial);
}
void setCompositor(wl_compositor* compositor)
{
mCompositor = compositor;
}
void setSharedMemory(wl_shm* shared_memory)
{
mWlSharedMemory = shared_memory;
}
void connect()
{
mDisplay = wl_display_connect(nullptr);
if (!mDisplay)
{
std::cout << "Display connect error" << std::endl;
}
auto registry = wl_display_get_registry(mDisplay);
if (!registry)
{
std::cout << "Failed to get registry" << std::endl;
}
wl_registry_add_listener(registry, &mRegistryListener, this);
wl_display_roundtrip(mDisplay);
}
void createSurface()
{
mSurface = wl_compositor_create_surface(mCompositor);
mXdgSurface = xdg_wm_base_get_xdg_surface(mXdgBase, mSurface);
auto xdg_surface_configure = [](void *data, struct xdg_surface *xdg_surface, uint32_t serial)
{
auto thisClass = static_cast<WaylandWindowInterface*>(data);
thisClass->onXdgSurfaceConfigure(data, xdg_surface, serial);
};
mXdgSurfaceListener.configure = xdg_surface_configure;
xdg_surface_add_listener(mXdgSurface, &mXdgSurfaceListener, this);
mXdgTopLevel = xdg_surface_get_toplevel(mXdgSurface);
xdg_toplevel_set_title(mXdgTopLevel, "Example client");
wl_surface_commit(mSurface);
}
void onXdgSurfaceConfigure(void *data, struct xdg_surface *xdg_surface, uint32_t serial)
{
xdg_surface_ack_configure(xdg_surface, serial);
auto buffer = draw_frame();
wl_surface_attach(mSurface, buffer, 0, 0);
//wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX);
wl_surface_commit(mSurface);
}
wl_buffer* draw_frame()
{
const auto width = mWindow->GetWidth();
const auto height = mWindow->GetHeight();
const int bitDepth = 4;
const int stride = width * bitDepth;
//const int numBuffers = 2; // i.e. front/back
const int numBuffers = 1;
const int shm_pool_size = height * stride * numBuffers;
initializeSharedBuffer(shm_pool_size);
if (!mSharedMemory->isValid())
{
std::cout << "Failed to allocate shared memory" << std::endl;
return nullptr;
}
if (!mPoolData)
{
std::cout << "Failed to mmap pool" << std::endl;
return nullptr;
}
auto pool = wl_shm_create_pool(mWlSharedMemory, mSharedMemory->getFileDescriptor(), shm_pool_size);
int index = 0;
// int offset = height * stride * index; // Two buffers, offset to starting point of second
int offset = 0;
mWorkingBuffer = wl_shm_pool_create_buffer(pool, offset, width, height, stride, WL_SHM_FORMAT_XRGB8888);
wl_shm_pool_destroy(pool);
close(mSharedMemory->getFileDescriptor());
drawCheckerboard(width, height, offset);
munmap(mPoolData, shm_pool_size);
auto wl_buffer_release = [](void *data, struct wl_buffer *wl_buffer)
{
wl_buffer_destroy(wl_buffer);
};
mBufferListener.release = wl_buffer_release;
wl_buffer_add_listener(mWorkingBuffer, &mBufferListener, nullptr);
return mWorkingBuffer;
}
void drawCheckerboard(int width, int height, int offset)
{
uint32_t *pixels = (uint32_t *)&mPoolData[offset];
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
if ((x + y / 8 * 8) % 16 < 8)
{
pixels[y * width + x] = 0xFF666666;
}
else
{
pixels[y * width + x] = 0xFFEEEEEE;
}
}
}
}
void disconnect()
{
if (mDisplay)
{
wl_display_disconnect(mDisplay);
}
}
void run()
{
while (wl_display_dispatch(mDisplay) != -1) {
/* This space deliberately left blank */
}
}
void initializeSharedBuffer(int size)
{
mSharedMemory = std::make_unique<SharedMemory>();
mSharedMemory->allocate("/wl_shm-XXXXXX", size);
if (!mSharedMemory->isValid())
{
return;
}
mPoolData = static_cast<uint8_t*>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, mSharedMemory->getFileDescriptor(), 0));
if (mPoolData == MAP_FAILED)
{
close(mSharedMemory->getFileDescriptor());
mPoolData = nullptr;
}
}
void addWindow(mt::Window* window)
{
mWindow = window;
}
private:
mt::Window* mWindow{nullptr};
wl_display* mDisplay{nullptr};
wl_compositor* mCompositor{nullptr};
wl_registry_listener mRegistryListener;
xdg_wm_base* mXdgBase{nullptr};
xdg_wm_base_listener mXdgBaseListener;
wl_surface* mSurface{nullptr};
xdg_surface* mXdgSurface{nullptr};
xdg_surface_listener mXdgSurfaceListener{nullptr};
xdg_toplevel* mXdgTopLevel{nullptr};
wl_shm* mWlSharedMemory{nullptr};
std::unique_ptr<SharedMemory> mSharedMemory;
uint8_t* mPoolData{nullptr};
wl_shm_pool* mPool{nullptr};
wl_buffer* mWorkingBuffer{nullptr};
wl_buffer_listener mBufferListener;
};

View file

@ -15,8 +15,11 @@ list(APPEND TestFiles
graphics/TestRasterizer.cpp graphics/TestRasterizer.cpp
ipc/TestDbus.cpp ipc/TestDbus.cpp
image/TestPngWriter.cpp image/TestPngWriter.cpp
network/TestNetworkManagerClient.cpp
network/TestNetworkManagerServer.cpp
publishing/TestPdfWriter.cpp publishing/TestPdfWriter.cpp
video/TestVideoDecoder.cpp video/TestVideoDecoder.cpp
windows/TestWaylandWindow.cpp
web/TestMarkdownParser.cpp web/TestMarkdownParser.cpp
web/TestXmlParser.cpp) web/TestXmlParser.cpp)
@ -28,8 +31,11 @@ list(APPEND TestNames
TestRasterizer TestRasterizer
TestDbus TestDbus
TestPngWriter TestPngWriter
TestNetworkManagerClient
TestNetworkManagerServer
TestPdfWriter TestPdfWriter
TestVideoDecoder TestVideoDecoder
TestWaylandWindow
TestMarkdownParser TestMarkdownParser
TestXmlParser) TestXmlParser)

View file

@ -1,6 +1,8 @@
#include "Image.h" #include "Image.h"
#include "PngWriter.h" #include "PngWriter.h"
#include <iostream>
int main() int main()
{ {
unsigned width = 200; unsigned width = 200;

View file

@ -0,0 +1,12 @@
#include "NetworkManager.h"
#include <iostream>
int main()
{
std::cout << "into main" << std::endl;
auto network_manager = NetworkManager::Create();
network_manager->RunHttpClient();
return 0;
}

View file

@ -0,0 +1,12 @@
#include "NetworkManager.h"
#include <iostream>
int main()
{
std::cout << "into main" << std::endl;
auto network_manager = NetworkManager::Create();
network_manager->RunHttpServer();
return 0;
}

View file

@ -0,0 +1,23 @@
#include "WaylandWindowInterface.h"
#include "Window.h"
int main()
{
WaylandWindowInterface window_interface;
window_interface.connect();
auto window = mt::Window::Create();
window->SetSize(800, 600);
window_interface.addWindow(window.get());
window_interface.createSurface();
window_interface.run();
window_interface.disconnect();
return 0;
}