Add cairo interface.

This commit is contained in:
jmsgrogan 2021-04-17 13:57:14 +01:00
parent a03eb9599f
commit 9bcc0ae88e
63 changed files with 1247 additions and 450 deletions

View file

@ -7,6 +7,7 @@ target_include_directories(sample_gui PUBLIC
target_link_libraries(sample_gui PUBLIC client windows console core target_link_libraries(sample_gui PUBLIC client windows console core
network database geometry audio web) network database geometry audio web)
if(WIN32)
add_executable(sample_gui_win WIN32 gui-main-win.cpp) add_executable(sample_gui_win WIN32 gui-main-win.cpp)
target_include_directories(sample_gui PUBLIC target_include_directories(sample_gui PUBLIC
"${PROJECT_SOURCE_DIR}/src/console" "${PROJECT_SOURCE_DIR}/src/console"
@ -14,6 +15,8 @@ target_include_directories(sample_gui PUBLIC
) )
target_link_libraries(sample_gui_win PUBLIC client windows console core target_link_libraries(sample_gui_win PUBLIC client windows console core
network database geometry audio web) network database geometry audio web)
set_property(TARGET sample_gui_win PROPERTY FOLDER apps)
endif()
# Sample Console # Sample Console
add_executable(sample_console console-main.cpp) add_executable(sample_console console-main.cpp)
@ -33,5 +36,4 @@ target_link_libraries(xml_practice PUBLIC core web)
set_property(TARGET sample_console PROPERTY FOLDER apps) set_property(TARGET sample_console PROPERTY FOLDER apps)
set_property(TARGET sample_gui PROPERTY FOLDER apps) set_property(TARGET sample_gui PROPERTY FOLDER apps)
set_property(TARGET sample_gui_win PROPERTY FOLDER apps)
set_property(TARGET xml_practice PROPERTY FOLDER apps) set_property(TARGET xml_practice PROPERTY FOLDER apps)

View file

@ -9,3 +9,4 @@ add_subdirectory(graphics)
add_subdirectory(windows) add_subdirectory(windows)
add_subdirectory(web) add_subdirectory(web)
add_subdirectory(ui_elements) add_subdirectory(ui_elements)
add_subdirectory(visual_elements)

View file

@ -20,7 +20,7 @@ std::unique_ptr<AudioManager> AudioManager::Create()
void AudioManager::AddAudioDevice(AudioDevicePtr device) void AudioManager::AddAudioDevice(AudioDevicePtr device)
{ {
mAudioDevices.push_back(device); mAudioDevices.push_back(std::move(device));
} }
IAudioInterface* AudioManager::GetAudioInterface() IAudioInterface* AudioManager::GetAudioInterface()
@ -28,7 +28,26 @@ IAudioInterface* AudioManager::GetAudioInterface()
return mAudioInterface.get(); return mAudioInterface.get();
} }
std::vector<AudioDevicePtr> AudioManager::GetAudioDevices() unsigned AudioManager::GetNumAudioDevices() const
{ {
return mAudioDevices; return mAudioDevices.size();
}
AudioDevice* AudioManager::GetAudioDevice(unsigned idx) const
{
if (idx < mAudioDevices.size())
{
return mAudioDevices[idx].get();
}
return nullptr;
}
void AudioManager::Play()
{
if (mAudioDevices.size() == 0)
{
mAudioDevices.push_back(AudioDevice::Create());
}
mAudioInterface->OpenDevice(mAudioDevices[0]);
mAudioInterface->Play(mAudioDevices[0]);
} }

View file

@ -24,9 +24,13 @@ public:
void AddAudioDevice(AudioDevicePtr device); void AddAudioDevice(AudioDevicePtr device);
std::vector<AudioDevicePtr> GetAudioDevices(); unsigned GetNumAudioDevices() const;
AudioDevice* GetAudioDevice(unsigned idx) const;
IAudioInterface* GetAudioInterface(); IAudioInterface* GetAudioInterface();
void Play();
}; };
using AudioManagerUPtr = std::unique_ptr<AudioManager>; using AudioManagerUPtr = std::unique_ptr<AudioManager>;

View file

@ -1,5 +1,9 @@
find_package(ALSA REQUIRED)
list(APPEND linux_HEADERS list(APPEND linux_HEADERS
audio_interfaces/AlsaInterface.h audio_interfaces/AlsaInterface.h
${ALSA_INCLUDE_DIRS}
) )
list(APPEND audio_HEADERS list(APPEND audio_HEADERS
@ -37,7 +41,7 @@ target_include_directories(audio PUBLIC
) )
list(APPEND linux_LIBS list(APPEND linux_LIBS
asound ${ALSA_LIBRARIES}
) )
target_link_libraries(audio PUBLIC core ${linux_LIBS}) target_link_libraries(audio PUBLIC core ${linux_LIBS})

View file

@ -14,9 +14,9 @@ AlsaInterface::~AlsaInterface()
} }
std::shared_ptr<AlsaInterface> AlsaInterface::Create() std::unique_ptr<AlsaInterface> AlsaInterface::Create()
{ {
return std::make_shared<AlsaInterface>(); return std::make_unique<AlsaInterface>();
} }
void AlsaInterface::OpenDevice(const AudioDevicePtr& device) void AlsaInterface::OpenDevice(const AudioDevicePtr& device)
@ -51,7 +51,7 @@ void AlsaInterface::OpenDevice(const AudioDevicePtr& device)
} }
} }
void AlsaInterface::SetAccessType(AudioDevicePtr device) void AlsaInterface::SetAccessType(const AudioDevicePtr& device)
{ {
if (snd_pcm_hw_params_set_access(mHandle, mHardwareParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { if (snd_pcm_hw_params_set_access(mHandle, mHardwareParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
MLOG_ERROR("Error setting device access."); MLOG_ERROR("Error setting device access.");
@ -59,7 +59,7 @@ void AlsaInterface::SetAccessType(AudioDevicePtr device)
} }
} }
void AlsaInterface::SetSampleFormat(AudioDevicePtr device) void AlsaInterface::SetSampleFormat(const AudioDevicePtr& device)
{ {
/* Set sample format */ /* Set sample format */
if (snd_pcm_hw_params_set_format(mHandle, mHardwareParams, SND_PCM_FORMAT_S16_LE) < 0) { if (snd_pcm_hw_params_set_format(mHandle, mHardwareParams, SND_PCM_FORMAT_S16_LE) < 0) {
@ -68,7 +68,7 @@ void AlsaInterface::SetSampleFormat(AudioDevicePtr device)
} }
} }
void AlsaInterface::SetSampleRate(AudioDevicePtr device) void AlsaInterface::SetSampleRate(const AudioDevicePtr& device)
{ {
unsigned rate = device->GetSampleRate(); unsigned rate = device->GetSampleRate();
unsigned exact_rate = rate; unsigned exact_rate = rate;
@ -82,7 +82,7 @@ void AlsaInterface::SetSampleRate(AudioDevicePtr device)
} }
} }
void AlsaInterface::SetPeriod(AudioDevicePtr device) void AlsaInterface::SetPeriod(const AudioDevicePtr& device)
{ {
/* Set number of periods. Periods used to be called fragments. */ /* Set number of periods. Periods used to be called fragments. */
if (snd_pcm_hw_params_set_periods(mHandle, mHardwareParams, device->GetPeriod(), 0) < 0) if (snd_pcm_hw_params_set_periods(mHandle, mHardwareParams, device->GetPeriod(), 0) < 0)
@ -92,7 +92,7 @@ void AlsaInterface::SetPeriod(AudioDevicePtr device)
} }
} }
void AlsaInterface::SetBufferSize(AudioDevicePtr device) void AlsaInterface::SetBufferSize(const AudioDevicePtr& device)
{ {
int periods = static_cast<int>(device->GetPeriod()); int periods = static_cast<int>(device->GetPeriod());
@ -105,7 +105,7 @@ void AlsaInterface::SetBufferSize(AudioDevicePtr device)
} }
} }
void AlsaInterface::SetChannelNumber(AudioDevicePtr device) void AlsaInterface::SetChannelNumber(const AudioDevicePtr& device)
{ {
/* Set number of channels */ /* Set number of channels */
if (snd_pcm_hw_params_set_channels(mHandle, mHardwareParams, device->GetNumChannels()) < 0) if (snd_pcm_hw_params_set_channels(mHandle, mHardwareParams, device->GetNumChannels()) < 0)

View file

@ -19,21 +19,21 @@ public:
~AlsaInterface(); ~AlsaInterface();
static std::shared_ptr<AlsaInterface> Create(); static std::unique_ptr<AlsaInterface> Create();
void OpenDevice(const AudioDevicePtr& device) override; void OpenDevice(const AudioDevicePtr& device) override;
void SetAccessType(AudioDevicePtr device); void SetAccessType(const AudioDevicePtr& device);
void SetSampleFormat(AudioDevicePtr device); void SetSampleFormat(const AudioDevicePtr& device);
void SetSampleRate(AudioDevicePtr device); void SetSampleRate(const AudioDevicePtr& device);
void SetPeriod(AudioDevicePtr device); void SetPeriod(const AudioDevicePtr& device);
void SetBufferSize(AudioDevicePtr device); void SetBufferSize(const AudioDevicePtr& device);
void SetChannelNumber(AudioDevicePtr device); void SetChannelNumber(const AudioDevicePtr& device);
void Play(const AudioDevicePtr& device) override; void Play(const AudioDevicePtr& device) override;
}; };

View file

@ -77,13 +77,13 @@ void GuiApplication::Run()
mDesktopManager->SetKeyboard(XcbKeyboard::Create()); mDesktopManager->SetKeyboard(XcbKeyboard::Create());
bool useOpenGl = false; bool useOpenGl = true;
XcbInterface window_interface; XcbInterface window_interface;
window_interface.SetUseOpenGl(useOpenGl); window_interface.SetUseOpenGl(useOpenGl);
window_interface.Initialize(); window_interface.Initialize(mDesktopManager.get());
window_interface.AddWindow(mainWindow); window_interface.AddWindow(mainWindow, mDesktopManager.get());
window_interface.ShowWindow(mainWindow); window_interface.ShowWindow(mainWindow);
if(useOpenGl) if (useOpenGl)
{ {
window_interface.CreateOpenGlDrawable(mainWindow); window_interface.CreateOpenGlDrawable(mainWindow);
} }

View file

@ -15,9 +15,10 @@ target_include_directories(console PUBLIC
"${PROJECT_SOURCE_DIR}/src/audio" "${PROJECT_SOURCE_DIR}/src/audio"
"${PROJECT_SOURCE_DIR}/src/audio/midi" "${PROJECT_SOURCE_DIR}/src/audio/midi"
"${PROJECT_SOURCE_DIR}/src/audio/audio_interfaces" "${PROJECT_SOURCE_DIR}/src/audio/audio_interfaces"
"${PROJECT_SOURCE_DIR}/src/graphics"
"${PROJECT_SOURCE_DIR}/src/web" "${PROJECT_SOURCE_DIR}/src/web"
"${SQLite3_INCLUDE_DIR}" "${SQLite3_INCLUDE_DIR}"
) )
set_property(TARGET console PROPERTY FOLDER src) set_property(TARGET console PROPERTY FOLDER src)
target_link_libraries(console PUBLIC core audio network database web) target_link_libraries(console PUBLIC core audio network database web graphics)
set_target_properties( console PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) set_target_properties( console PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )

View file

@ -3,6 +3,12 @@
#include "MidiReader.h" #include "MidiReader.h"
#include "File.h" #include "File.h"
#include "DocumentConverter.h" #include "DocumentConverter.h"
#include "DrawingManager.h"
#include "DrawingSurface.h"
#include "DrawingContext.h"
#include "TextElement.h"
#include "DiscretePoint.h"
#include <filesystem> #include <filesystem>
MainApplication::MainApplication() MainApplication::MainApplication()
@ -69,6 +75,15 @@ void MainApplication::Run()
{ {
ConvertDocument(input_path, output_path); ConvertDocument(input_path, output_path);
} }
else if(program_type == "-draw")
{
auto drawing_manager = DrawingManager::Create();
drawing_manager->InitalizeSurface(400, 400);
auto text = TextElement::Create("Hello World", DiscretePoint(20, 20));
drawing_manager->AddText(text.get());
drawing_manager->RenderToFile("test.png");
}
else else
{ {
MLOG_ERROR("Unknown program type: " + program_type); MLOG_ERROR("Unknown program type: " + program_type);
@ -84,9 +99,7 @@ void MainApplication::PlayAudio()
{ {
//MidiReader reader; //MidiReader reader;
//reader.Read("/home/james/sample.mid"); //reader.Read("/home/james/sample.mid");
auto device = AudioDevice::Create(); mAudioManager->Play();
mAudioManager->GetAudioInterface()->OpenDevice(device);
mAudioManager->GetAudioInterface()->Play(device);
} }
void MainApplication::ConvertDocument(const std::string& inputPath, const std::string& outputPath) void MainApplication::ConvertDocument(const std::string& inputPath, const std::string& outputPath)

View file

@ -9,9 +9,7 @@
class FileLogger class FileLogger
{ {
std::string mWorkDirectory; std::string mWorkDirectory;
std::string mFileName; std::string mFileName;
std::ofstream mFileStream; std::ofstream mFileStream;
FileLogger() FileLogger()

View file

@ -1,6 +1,8 @@
list(APPEND geometry_LIB_INCLUDES list(APPEND geometry_LIB_INCLUDES
DiscretePoint.cpp DiscretePoint.cpp
Point.cpp) Point.cpp
Rectangle.cpp)
# add the library # add the library
add_library(geometry SHARED ${geometry_LIB_INCLUDES}) add_library(geometry SHARED ${geometry_LIB_INCLUDES})

View file

@ -1,8 +1,46 @@
list(APPEND graphics_LIB_INCLUDES OpenGlInterface.cpp) list(APPEND graphics_LIB_INCLUDES
list(APPEND graphics_HEADERS OpenGlInterface.h) DrawingContext.cpp
DrawingManager.cpp
DrawingSurface.cpp
opengl/OpenGlInterface.cpp
cairo/CairoInterface.cpp
cairo/CairoDrawingSurface.cpp
cairo/CairoDrawingContext.cpp)
add_library(graphics SHARED ${graphics_LIB_INCLUDES} ${graphics_HEADERS}) list(APPEND graphics_HEADERS
opengl/OpenGlInterface.h
cairo/CairoInterface.h
INativeDrawingSurface.h
INativeDrawingContext.h)
target_link_libraries(graphics PUBLIC GL) find_package(PkgConfig)
PKG_CHECK_MODULES(PC_CAIRO cairo)
FIND_PATH(CAIRO_INCLUDE_DIRS
NAMES cairo.h
HINTS ${PC_CAIRO_INCLUDEDIR}
${PC_CAIRO_INCLUDE_DIRS}
PATH_SUFFIXES cairo
)
FIND_LIBRARY(CAIRO_LIBRARIES
NAMES cairo
HINTS ${PC_CAIRO_LIBDIR}
${PC_CAIRO_LIBRARY_DIRS}
)
add_library(graphics SHARED
${graphics_LIB_INCLUDES}
${graphics_HEADERS})
target_include_directories(graphics PUBLIC
${CAIRO_INCLUDE_DIRS}
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/cairo"
"${CMAKE_CURRENT_SOURCE_DIR}/opengl"
"${PROJECT_SOURCE_DIR}/src/geometry/"
"${PROJECT_SOURCE_DIR}/src/visual_elements/"
)
target_link_libraries(graphics PUBLIC visual_elements GL ${CAIRO_LIBRARIES})
set_property(TARGET graphics PROPERTY FOLDER src) set_property(TARGET graphics PROPERTY FOLDER src)

View file

@ -0,0 +1,18 @@
#include "DrawingContext.h"
#include "INativeDrawingContext.h"
std::unique_ptr<DrawingContext> DrawingContext::Create()
{
return std::make_unique<DrawingContext>();
}
void DrawingContext::SetNativeContext(std::unique_ptr<INativeDrawingContext> context)
{
mNativeDrawingContext = std::move(context);
}
INativeDrawingContext* DrawingContext::GetNativeContext()
{
return mNativeDrawingContext.get();
}

View file

@ -0,0 +1,23 @@
#pragma once
#include <memory>
class INativeDrawingContext;
class DrawingContext
{
public:
DrawingContext() = default;
static std::unique_ptr<DrawingContext> Create();
void SetNativeContext(std::unique_ptr<INativeDrawingContext> context);
INativeDrawingContext* GetNativeContext();
private:
std::unique_ptr<INativeDrawingContext> mNativeDrawingContext;
};
using DrawingContextPtr = std::unique_ptr<DrawingContext>;

View file

@ -0,0 +1,63 @@
#include "DrawingManager.h"
#include "INativeDrawingContext.h"
#include "DrawingSurface.h"
#include "DrawingContext.h"
#include "CairoInterface.h"
DrawingManager::DrawingManager()
{
mCairoInterface = CairoInterface::Create();
}
std::unique_ptr<DrawingManager> DrawingManager::Create()
{
return std::make_unique<DrawingManager>();
}
void DrawingManager::InitalizeSurface(unsigned width, unsigned height)
{
mDrawingSurface = DrawingSurface::Create();
mDrawingSurface->SetSize(width, height);
if (mCairoInterface)
{
mCairoInterface->InitializeSurface(mDrawingSurface.get());
}
}
void DrawingManager::InitializeContext()
{
mDrawingContext = DrawingContext::Create();
if (mCairoInterface && mDrawingSurface)
{
mCairoInterface->InitializeContext(mDrawingContext.get(), mDrawingSurface.get());
}
}
void DrawingManager::AddText(TextElement* text)
{
if (!mDrawingContext)
{
InitializeContext();
}
if (!mDrawingContext)
{
return;
}
if (mCairoInterface)
{
mCairoInterface->AddText(text, mDrawingContext.get());
}
}
void DrawingManager::RenderToFile(const std::string& path)
{
if (mDrawingSurface && mCairoInterface)
{
mCairoInterface->RenderToFile(mDrawingSurface.get(), path);
}
}

View file

@ -0,0 +1,31 @@
#pragma once
#include <memory>
#include "INativeDrawingContext.h"
#include "INativeDrawingSurface.h"
#include "CairoInterface.h"
class TextElement;
class DrawingSurface;
using DrawingSurfacePtr = std::unique_ptr<DrawingSurface>;
class DrawingContext;
using DrawingContextPtr = std::unique_ptr<DrawingContext>;
class DrawingManager
{
public:
DrawingManager();
static std::unique_ptr<DrawingManager> Create();
void InitalizeSurface(unsigned width, unsigned height);
void InitializeContext();
void AddText(TextElement* text);
void RenderToFile(const std::string& path);
private:
DrawingSurfacePtr mDrawingSurface {nullptr};
DrawingContextPtr mDrawingContext {nullptr};
CairoInterfacePtr mCairoInterface {nullptr};
};
using DrawingManagerPtr = std::unique_ptr<DrawingManager>;

View file

@ -0,0 +1,40 @@
#include "DrawingSurface.h"
std::unique_ptr<DrawingSurface> DrawingSurface::Create()
{
return std::make_unique<DrawingSurface>();
}
INativeDrawingSurface* DrawingSurface::GetNativeSurface()
{
if (mNativeDrawingSurface)
{
return mNativeDrawingSurface.get();
}
else
{
return nullptr;
}
}
void DrawingSurface::SetNativeSurface(std::unique_ptr<INativeDrawingSurface> surface)
{
mNativeDrawingSurface = std::move(surface);
}
void DrawingSurface::SetSize(unsigned width, unsigned height)
{
mWidth = width;
mHeight = height;
}
unsigned DrawingSurface::GetWidth() const
{
return mWidth;
}
unsigned DrawingSurface::GetHeight() const
{
return mHeight;
}

View file

@ -0,0 +1,29 @@
#pragma once
#include <memory>
#include "INativeDrawingSurface.h"
class DrawingSurface
{
public:
DrawingSurface() = default;
static std::unique_ptr<DrawingSurface> Create();
INativeDrawingSurface* GetNativeSurface();
void SetNativeSurface(std::unique_ptr<INativeDrawingSurface> surface);
void SetSize(unsigned width, unsigned height);
unsigned GetWidth() const;
unsigned GetHeight() const;
private:
unsigned mWidth = 0;
unsigned mHeight = 0;
std::unique_ptr<INativeDrawingSurface> mNativeDrawingSurface;
};

View file

@ -0,0 +1,8 @@
#pragma once
class INativeDrawingContext
{
public:
virtual ~INativeDrawingContext() = default;
};

View file

@ -0,0 +1,9 @@
#pragma once
class INativeDrawingSurface
{
public:
virtual ~INativeDrawingSurface() = default;
virtual void DestroyNativeSurface() = 0;
};

View file

@ -0,0 +1,31 @@
#include "CairoDrawingContext.h"
cairo_t* CairoDrawingContext::GetNativeContext()
{
return mNativeContext;
}
CairoDrawingContext::CairoDrawingContext(cairo_t* context)
: mNativeContext(context)
{
}
CairoDrawingContext::~CairoDrawingContext()
{
DestroyNativeContext();
}
std::unique_ptr<CairoDrawingContext> CairoDrawingContext::Create(cairo_t* context)
{
return std::make_unique<CairoDrawingContext>(context);
}
void CairoDrawingContext::DestroyNativeContext()
{
if (mNativeContext)
{
cairo_destroy (mNativeContext);
mNativeContext = nullptr;
}
}

View file

@ -0,0 +1,27 @@
#pragma once
#include "INativeDrawingContext.h"
#include <memory>
#include <cairo.h>
class CairoDrawingContext : public INativeDrawingContext
{
public:
CairoDrawingContext(cairo_t* context);
virtual ~CairoDrawingContext();
static std::unique_ptr<CairoDrawingContext> Create(cairo_t* context);
cairo_t* GetNativeContext();
void DestroyNativeContext();
private:
cairo_t* mNativeContext;
};
using CairoDrawingContextPtr = std::unique_ptr<CairoDrawingContext>;

View file

@ -0,0 +1,31 @@
#include "CairoDrawingSurface.h"
CairoDrawingSurface::CairoDrawingSurface(cairo_surface_t* surface)
: mNativeSurface(surface)
{
}
CairoDrawingSurface::~CairoDrawingSurface()
{
DestroyNativeSurface();
}
std::unique_ptr<CairoDrawingSurface> CairoDrawingSurface::Create(cairo_surface_t* surface)
{
return std::make_unique<CairoDrawingSurface>(surface);
}
cairo_surface_t* CairoDrawingSurface::GetNativeSurface()
{
return mNativeSurface;
}
void CairoDrawingSurface::DestroyNativeSurface()
{
if (mNativeSurface)
{
cairo_surface_destroy (mNativeSurface);
mNativeSurface = nullptr;
}
}

View file

@ -0,0 +1,27 @@
#pragma once
#include "INativeDrawingSurface.h"
#include <cairo.h>
#include <memory>
class CairoDrawingSurface : public INativeDrawingSurface
{
public:
CairoDrawingSurface(cairo_surface_t* surface);
virtual ~CairoDrawingSurface();
static std::unique_ptr<CairoDrawingSurface> Create(cairo_surface_t* surface);
cairo_surface_t* GetNativeSurface();
void DestroyNativeSurface() override;
private:
cairo_surface_t* mNativeSurface;
};
using CairoDrawingSurfacePtr = std::unique_ptr<CairoDrawingSurface>;

View file

@ -0,0 +1,51 @@
#include "CairoInterface.h"
#include "DrawingSurface.h"
#include "DrawingContext.h"
#include "CairoDrawingSurface.h"
#include "CairoDrawingContext.h"
#include "TextElement.h"
#include <cairo.h>
std::unique_ptr<CairoInterface> CairoInterface::Create()
{
return std::make_unique<CairoInterface>();
}
void CairoInterface::InitializeSurface(DrawingSurface* surface)
{
auto native_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
surface->GetWidth(), surface->GetHeight());
auto cairo_surface = CairoDrawingSurface::Create(native_surface);
surface->SetNativeSurface(std::move(cairo_surface));
}
void CairoInterface::InitializeContext(DrawingContext* context, DrawingSurface* surface)
{
auto cairo_surface = dynamic_cast<CairoDrawingSurface*>(surface->GetNativeSurface());
auto native_context = cairo_create(cairo_surface->GetNativeSurface());
auto cairo_context = CairoDrawingContext::Create(native_context);
context->SetNativeContext(std::move(cairo_context));
}
void CairoInterface::RenderToFile(DrawingSurface* surface, const std::string& path)
{
auto cairo_surface = dynamic_cast<CairoDrawingSurface*>(surface->GetNativeSurface());
cairo_surface_write_to_png (cairo_surface->GetNativeSurface(), path.c_str());
}
void CairoInterface::AddText(TextElement* text, DrawingContext* context)
{
auto cairo_context = dynamic_cast<CairoDrawingContext*>(context->GetNativeContext());
auto native_context = cairo_context->GetNativeContext();
cairo_select_font_face (native_context, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (native_context, 32.0);
cairo_set_source_rgb (native_context, 0.0, 0.0, 1.0);
cairo_move_to(native_context, 10.0, 50.0);
cairo_show_text(native_context, text->GetContent().c_str());
}

View file

@ -0,0 +1,26 @@
#pragma once
#include <memory>
#include <string>
class DrawingSurface;
class DrawingContext;
class TextElement;
class CairoInterface
{
public:
CairoInterface() = default;
static std::unique_ptr<CairoInterface> Create();
void InitializeSurface(DrawingSurface* surface);
void InitializeContext(DrawingContext* context, DrawingSurface* surface);
void AddText(TextElement* text, DrawingContext* context);
void RenderToFile(DrawingSurface* surface, const std::string& path);
};
using CairoInterfacePtr = std::unique_ptr<CairoInterface>;

View file

@ -1,6 +1,8 @@
list(APPEND ui_elements_LIB_INCLUDES list(APPEND ui_elements_LIB_INCLUDES
desktop_elements/Keyboard.cpp desktop_elements/Keyboard.cpp
desktop_elements/IPlatformScreen.h
desktop_elements/Screen.cpp desktop_elements/Screen.cpp
desktop_elements/IPlatformWindow.h
desktop_elements/Window.cpp desktop_elements/Window.cpp
ui_events/KeyboardEvent.cpp ui_events/KeyboardEvent.cpp
ui_events/MouseEvent.cpp ui_events/MouseEvent.cpp
@ -13,23 +15,21 @@ list(APPEND ui_elements_LIB_INCLUDES
widgets/VerticalSpacer.cpp widgets/VerticalSpacer.cpp
widgets/StackWidget.cpp widgets/StackWidget.cpp
widgets/TextBox.cpp widgets/TextBox.cpp
widgets/elements/GeometryElement.cpp )
widgets/elements/RectangleElement.cpp
widgets/elements/TextElement.cpp
widgets/elements/VisualLayer.cpp)
add_library(ui_elements SHARED ${ui_elements_LIB_INCLUDES}) add_library(ui_elements SHARED ${ui_elements_LIB_INCLUDES})
target_include_directories(ui_elements PUBLIC target_include_directories(ui_elements PUBLIC
"${PROJECT_SOURCE_DIR}/src/core/" "${PROJECT_SOURCE_DIR}/src/core/"
"${PROJECT_SOURCE_DIR}/src/geometry/" "${PROJECT_SOURCE_DIR}/src/geometry/"
"${PROJECT_SOURCE_DIR}/src/visual_elements"
"${CMAKE_CURRENT_SOURCE_DIR}/" "${CMAKE_CURRENT_SOURCE_DIR}/"
"${CMAKE_CURRENT_SOURCE_DIR}/widgets" "${CMAKE_CURRENT_SOURCE_DIR}/widgets"
"${CMAKE_CURRENT_SOURCE_DIR}/widgets/elements" "${CMAKE_CURRENT_SOURCE_DIR}/widgets/elements"
"${CMAKE_CURRENT_SOURCE_DIR}/ui_events" "${CMAKE_CURRENT_SOURCE_DIR}/ui_events"
"${CMAKE_CURRENT_SOURCE_DIR}/desktop_elements" "${CMAKE_CURRENT_SOURCE_DIR}/desktop_elements"
) )
target_link_libraries(ui_elements PUBLIC core geometry) target_link_libraries(ui_elements PUBLIC core geometry visual_elements)
set_property(TARGET ui_elements PROPERTY FOLDER src) set_property(TARGET ui_elements PROPERTY FOLDER src)

View file

@ -0,0 +1,11 @@
#pragma once
#include <memory>
class IPlatformScreen
{
public:
virtual ~IPlatformScreen() = default;
};
using IPlatformScreenPtr = std::unique_ptr<IPlatformScreen>;

View file

@ -0,0 +1,11 @@
#pragma once
#include <memory>
class IPlatformWindow
{
public:
virtual ~IPlatformWindow() = default;
};
using IPlatformWindowPtr = std::unique_ptr<IPlatformWindow>;

View file

@ -1,5 +1,7 @@
#include "Screen.h" #include "Screen.h"
#include "IPlatformScreen.h"
namespace mt{ namespace mt{
Screen::Screen() Screen::Screen()
{ {
@ -11,8 +13,22 @@ Screen::~Screen()
} }
std::shared_ptr<Screen> Screen::Create() std::unique_ptr<Screen> Screen::Create()
{ {
return std::make_shared<Screen>(); return std::make_unique<Screen>();
}
IPlatformScreen* Screen::GetPlatformScreen() const
{
if (mPlatformScreen)
{
return mPlatformScreen.get();
}
return nullptr;
}
void Screen::SetPlatformScreen(IPlatformScreenPtr screen)
{
mPlatformScreen = std::move(screen);
} }
} }

View file

@ -1,6 +1,10 @@
#pragma once #pragma once
#include <memory> #include <memory>
class IPlatformScreen;
using IPlatformScreenPtr = std::unique_ptr<IPlatformScreen>;
namespace mt{ namespace mt{
class Screen class Screen
{ {
@ -11,7 +15,15 @@ public:
~Screen(); ~Screen();
static std::shared_ptr<Screen> Create(); static std::unique_ptr<Screen> Create();
IPlatformScreen* GetPlatformScreen() const;
void SetPlatformScreen(IPlatformScreenPtr screen);
private:
IPlatformScreenPtr mPlatformScreen {nullptr};
}; };
} }
using ScreenPtr = std::shared_ptr<mt::Screen>; using ScreenPtr = std::unique_ptr<mt::Screen>;

View file

@ -1,6 +1,14 @@
#include "Window.h" #include "Window.h"
namespace mt{ #include "IPlatformWindow.h"
#include "PaintEvent.h"
#include "MouseEvent.h"
#include "VisualLayer.h"
#include "KeyboardEvent.h"
namespace mt
{
Window::Window() Window::Window()
:mWidth(400), :mWidth(400),
mHeight(300), mHeight(300),
@ -21,7 +29,7 @@ std::unique_ptr<Window> Window::Create()
std::vector<VisualLayer*> Window::GetLayers() std::vector<VisualLayer*> Window::GetLayers()
{ {
return mLayers; return mWidget->GetLayers();
} }
void Window::OnMouseEvent(const MouseEvent* event) void Window::OnMouseEvent(const MouseEvent* event)
@ -36,12 +44,8 @@ void Window::OnKeyboardEvent(const KeyboardEvent* event)
void Window::OnPaint(const PaintEvent* event) void Window::OnPaint(const PaintEvent* event)
{ {
mLayers.clear();
mWidget->SetBounds(mWidth, mHeight); mWidget->SetBounds(mWidth, mHeight);
mWidget->OnPaintEvent(event); mWidget->OnPaintEvent(event);
auto layers = mWidget->GetLayers();
mLayers.insert(mLayers.end(), layers.begin(), layers.end());
} }
void Window::AddWidget(WidgetUPtr widget) void Window::AddWidget(WidgetUPtr widget)
@ -69,4 +73,19 @@ void Window::SetSize(unsigned width, unsigned height)
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
} }
IPlatformWindow* Window::GetPlatformWindow() const
{
if (mPlatformWindow)
{
return mPlatformWindow.get();
}
return nullptr;
}
void Window::SetPlatformWindow(IPlatformWindowPtr window)
{
mPlatformWindow = std::move(window);
}
} }

View file

@ -1,13 +1,16 @@
#pragma once #pragma once
#include "Widget.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "PaintEvent.h" class PaintEvent;
#include "MouseEvent.h" class MouseEvent;
#include "KeyboardEvent.h" class KeyboardEvent;
#include "VisualLayer.h" class VisualLayer;
#include "Widget.h" class IPlatformWindow;
using IPlatformWindowPtr = std::unique_ptr<IPlatformWindow>;
namespace mt namespace mt
{ {
@ -15,13 +18,6 @@ namespace mt
class Window class Window
{ {
private:
WidgetUPtr mWidget;
unsigned mWidth;
unsigned mHeight;
std::vector<VisualLayer*> mLayers;
public: public:
Window(); Window();
@ -47,6 +43,17 @@ public:
void OnMouseEvent(const MouseEvent* event); void OnMouseEvent(const MouseEvent* event);
void OnKeyboardEvent(const KeyboardEvent* event); void OnKeyboardEvent(const KeyboardEvent* event);
IPlatformWindow* GetPlatformWindow() const;
void SetPlatformWindow(IPlatformWindowPtr window);
private:
int mHandle {-1};
WidgetUPtr mWidget {nullptr};
unsigned mWidth {800};
unsigned mHeight {600};
IPlatformWindowPtr mPlatformWindow {nullptr};
}; };
} }

View file

@ -0,0 +1,19 @@
list(APPEND visual_elements_LIB_INCLUDES
GeometryElement.cpp
RectangleElement.cpp
TextElement.cpp
VisualLayer.cpp
)
add_library(visual_elements SHARED ${visual_elements_LIB_INCLUDES})
target_include_directories(visual_elements PUBLIC
"${PROJECT_SOURCE_DIR}/src/core/"
"${PROJECT_SOURCE_DIR}/src/geometry/"
)
target_link_libraries(visual_elements PUBLIC core geometry)
set_property(TARGET visual_elements PROPERTY FOLDER src)
set_target_properties( visual_elements PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )

View file

@ -1,5 +1,9 @@
list(APPEND linux_INCLUDES list(APPEND linux_INCLUDES
ui_interfaces/x11/XcbInterface.cpp ui_interfaces/x11/XcbInterface.cpp
ui_interfaces/x11/XcbEventInterface.cpp
ui_interfaces/x11/XcbWindow.cpp
ui_interfaces/x11/XcbScreen.cpp
ui_interfaces/x11/XcbWindowInterface.cpp
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

View file

@ -1,7 +1,5 @@
#include "DesktopManager.h" #include "DesktopManager.h"
#include <iostream>
DesktopManager::DesktopManager() DesktopManager::DesktopManager()
: mScreens(), : mScreens(),
mWindowManager(WindowManager::Create()), mWindowManager(WindowManager::Create()),
@ -69,7 +67,7 @@ void DesktopManager::OnUiEvent(UiEventUPtr eventUPtr)
{ {
auto mouseEvent = dynamic_cast<const MouseEvent*>(event); auto mouseEvent = dynamic_cast<const MouseEvent*>(event);
OnMouseEvent(mouseEvent); OnMouseEvent(mouseEvent);
if(mouseEvent->GetAction() == MouseEvent::Action::Pressed) if (mouseEvent->GetAction() == MouseEvent::Action::Pressed)
{ {
mModified = true; mModified = true;
} }
@ -109,6 +107,20 @@ AbstractDesktopAppPtr DesktopManager::GetMainApp()
return mMainApplication; return mMainApplication;
} }
void DesktopManager::AddScreen(ScreenPtr screen)
{
mScreens.push_back(std::move(screen));
}
mt::Screen* DesktopManager::GetDefaultScreen() const
{
if (mScreens.size() > 0)
{
return mScreens[0].get();
}
return nullptr;
}
void DesktopManager::SetWindowManager(WindowManagerUPtr windowManager) void DesktopManager::SetWindowManager(WindowManagerUPtr windowManager)
{ {
mWindowManager = std::move(windowManager); mWindowManager = std::move(windowManager);

View file

@ -15,13 +15,6 @@
class DesktopManager class DesktopManager
{ {
std::vector<ScreenPtr> mScreens;
WindowManagerUPtr mWindowManager;
KeyboardUPtr mKeyboard;
EventManagerUPtr mEventManager;
AbstractDesktopAppPtr mMainApplication;
bool mModified;
public: public:
DesktopManager(); DesktopManager();
@ -40,6 +33,10 @@ public:
Keyboard* GetKeyboard() const; Keyboard* GetKeyboard() const;
void AddScreen(ScreenPtr screen);
mt::Screen* GetDefaultScreen() const;
bool IsModified() const; bool IsModified() const;
void SetIsModified(bool modified); void SetIsModified(bool modified);
@ -55,6 +52,14 @@ public:
void OnPaintEvent(const PaintEvent* paintEvent); void OnPaintEvent(const PaintEvent* paintEvent);
void ClearEvents(); void ClearEvents();
private:
std::vector<ScreenPtr> mScreens;
WindowManagerUPtr mWindowManager;
KeyboardUPtr mKeyboard;
EventManagerUPtr mEventManager;
AbstractDesktopAppPtr mMainApplication;
bool mModified;
}; };
using DesktopManagerUPtr = std::unique_ptr<DesktopManager>; using DesktopManagerUPtr = std::unique_ptr<DesktopManager>;

View file

@ -1,6 +1,5 @@
#include "EventManager.h" #include "EventManager.h"
EventManager::EventManager() EventManager::EventManager()
: mEvents() : mEvents()
{ {

View file

@ -1,7 +1,9 @@
#pragma once #pragma once
#include <vector>
#include "UiEvent.h" #include "UiEvent.h"
#include <vector>
class EventManager class EventManager
{ {
std::vector<UiEventUPtr> mEvents; std::vector<UiEventUPtr> mEvents;

View file

@ -1,7 +1,9 @@
#include "GlxInterface.h" #include "GlxInterface.h"
#include <GL/gl.h>
#include <iostream>
#include "OpenGlInterface.h" #include "OpenGlInterface.h"
#include "FileLogger.h"
#include <GL/gl.h>
GlxInterface::GlxInterface() GlxInterface::GlxInterface()
: mContext(), : mContext(),
@ -30,36 +32,33 @@ static int visual_attribs[] =
None None
}; };
std::shared_ptr<GlxInterface> GlxInterface::Create() std::unique_ptr<GlxInterface> GlxInterface::Create()
{ {
return std::make_shared<GlxInterface>(); return std::make_unique<GlxInterface>();
} }
void GlxInterface::SetupContext(Display* display, int default_screen) void GlxInterface::SetupContext(Display* display, int default_screen)
{ {
int visualID = 0;
/* Query framebuffer configurations that match visual_attribs */ /* Query framebuffer configurations that match visual_attribs */
GLXFBConfig *fb_configs = 0; GLXFBConfig* fb_configs = nullptr;
int num_fb_configs = 0; int num_fb_configs = 0;
fb_configs = glXChooseFBConfig(display, default_screen, visual_attribs, &num_fb_configs); fb_configs = glXChooseFBConfig(display, default_screen, visual_attribs, &num_fb_configs);
if(!fb_configs || num_fb_configs == 0) if (!fb_configs || num_fb_configs == 0)
{ {
std::cerr << "glXGetFBConfigs failed" << std::endl; MLOG_ERROR("glXGetFBConfigs failed");
return; return;
} }
/* Select first framebuffer config and query visualID */ /* Select first framebuffer config and query visualID */
int visualID = 0;
mConfig = fb_configs[0]; mConfig = fb_configs[0];
glXGetFBConfigAttrib(display, mConfig, GLX_VISUAL_ID , &visualID); glXGetFBConfigAttrib(display, mConfig, GLX_VISUAL_ID, &visualID);
GLXContext context;
/* Create OpenGL context */ /* Create OpenGL context */
mContext = glXCreateNewContext(display, mConfig, GLX_RGBA_TYPE, 0, True); mContext = glXCreateNewContext(display, mConfig, GLX_RGBA_TYPE, 0, True);
if(!mContext) if (!mContext)
{ {
std::cerr << "glXCreateNewContext failed" << std::endl; MLOG_ERROR("glXCreateNewContext failed");
return; return;
} }
} }
@ -77,26 +76,21 @@ void GlxInterface::Draw()
bool GlxInterface::SetupWindow(Display* display, xcb_window_t window) bool GlxInterface::SetupWindow(Display* display, xcb_window_t window)
{ {
/* Create GLX Window */ /* Create GLX Window */
//GLXDrawable drawable = 0;
mWindow = glXCreateWindow(display, mConfig, window, 0); mWindow = glXCreateWindow(display, mConfig, window, 0);
if (!mWindow)
if(!mWindow)
{ {
//xcb_destroy_window(connection, window);
glXDestroyContext(display, mContext); glXDestroyContext(display, mContext);
std::cerr << "glXCreateWindow failed" << std::endl; MLOG_ERROR("glXCreateWindow failed");
return false; return false;
} }
mDrawable = mWindow; mDrawable = mWindow;
/* make OpenGL context current */ /* make OpenGL context current */
if(!glXMakeContextCurrent(display, mDrawable, mDrawable, mContext)) if (!glXMakeContextCurrent(display, mDrawable, mDrawable, mContext))
{ {
//
glXDestroyContext(display, mContext); glXDestroyContext(display, mContext);
std::cerr << "glXMakeContextCurrent failed" << std::endl; MLOG_ERROR("glXMakeContextCurrent failed");
return false; return false;
} }
return true; return true;

View file

@ -5,15 +5,12 @@
class GlxInterface class GlxInterface
{ {
GLXContext mContext;
GLXDrawable mDrawable;
GLXWindow mWindow;
GLXFBConfig mConfig;
public: public:
GlxInterface(); GlxInterface();
static std::unique_ptr<GlxInterface> Create();
void SetupContext(Display* display, int default_screen); void SetupContext(Display* display, int default_screen);
bool SetupWindow(Display* display, xcb_window_t window); bool SetupWindow(Display* display, xcb_window_t window);
@ -26,7 +23,11 @@ public:
void Draw(); void Draw();
static std::shared_ptr<GlxInterface> Create(); private:
GLXContext mContext;
GLXDrawable mDrawable;
GLXWindow mWindow;
GLXFBConfig mConfig;
}; };
using GlxInterfacePtr = std::shared_ptr<GlxInterface>; using GlxInterfacePtr = std::unique_ptr<GlxInterface>;

View file

@ -0,0 +1,59 @@
#include "XcbEventInterface.h"
#include "KeyboardEvent.h"
#include "DiscretePoint.h"
#include "MouseEvent.h"
#include "PaintEvent.h"
#include "Keyboard.h"
#include <xcb/xcb.h>
std::unique_ptr<XcbEventInterface> XcbEventInterface::Create()
{
return std::make_unique<XcbEventInterface>();
}
std::unique_ptr<KeyboardEvent> XcbEventInterface::ConvertKeyPress(xcb_key_press_event_t* event, Keyboard* keyboard) const
{
auto ui_event = KeyboardEvent::Create();
ui_event->SetAction(KeyboardEvent::Action::Pressed);
ui_event->SetKeyString(keyboard->GetKeyString(event->detail));
return ui_event;
}
std::unique_ptr<KeyboardEvent> XcbEventInterface::ConvertKeyRelease(xcb_key_press_event_t* event, Keyboard* keyboard) const
{
auto ui_event = KeyboardEvent::Create();
ui_event->SetAction(KeyboardEvent::Action::Released);
ui_event->SetKeyString(keyboard->GetKeyString(event->detail));
return ui_event;
}
std::unique_ptr<MouseEvent> XcbEventInterface::ConvertButtonPress(xcb_button_press_event_t* event) const
{
auto ui_event = MouseEvent::Create();
auto x = static_cast<unsigned>(event->event_x);
auto y = static_cast<unsigned>(event->event_y);
ui_event->SetClientLocation(DiscretePoint(x, y));
auto screen_x = static_cast<unsigned>(event->root_x);
auto screen_y = static_cast<unsigned>(event->root_y);
ui_event->SetScreenLocation(DiscretePoint(x, y));
ui_event->SetAction(MouseEvent::Action::Pressed);
return ui_event;
}
std::unique_ptr<MouseEvent> XcbEventInterface::ConvertButtonRelease(xcb_button_press_event_t* event) const
{
auto ui_event = MouseEvent::Create();
auto x = static_cast<unsigned>(event->event_x);
auto y = static_cast<unsigned>(event->event_y);
ui_event->SetClientLocation(DiscretePoint(x, y));
auto screen_x = static_cast<unsigned>(event->root_x);
auto screen_y = static_cast<unsigned>(event->root_y);
ui_event->SetScreenLocation(DiscretePoint(x, y));
ui_event->SetAction(MouseEvent::Action::Released);
return ui_event;
}

View file

@ -0,0 +1,28 @@
#pragma once
#include <memory>
class Keyboard;
class MouseEvent;
class KeyboardEvent;
class PaintEvent;
struct xcb_key_press_event_t;
struct xcb_button_press_event_t;
class XcbEventInterface
{
public:
static std::unique_ptr<XcbEventInterface> Create();
std::unique_ptr<KeyboardEvent> ConvertKeyPress(xcb_key_press_event_t* event, Keyboard* keyboard) const;
std::unique_ptr<KeyboardEvent> ConvertKeyRelease(xcb_key_press_event_t* event, Keyboard* keyboard) const;
std::unique_ptr<MouseEvent> ConvertButtonPress(xcb_button_press_event_t* event) const;
std::unique_ptr<MouseEvent> ConvertButtonRelease(xcb_button_press_event_t* event) const;
};
using XcbEventInterfacePtr = std::unique_ptr<XcbEventInterface>;

View file

@ -1,30 +1,32 @@
#include "XcbInterface.h" #include "XcbInterface.h"
#include "DesktopManager.h" #include "DesktopManager.h"
#include <iostream>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */ #include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include "KeyboardEvent.h"
#include "MouseEvent.h"
#include "PaintEvent.h" #include "PaintEvent.h"
#include "Screen.h"
#include "XcbScreen.h"
#include "UiEvent.h" #include "UiEvent.h"
#include "VisualLayer.h"
#include "XcbKeyboard.h" #include "XcbKeyboard.h"
#include "XcbWindow.h"
#include "XcbLayerInterface.h" #include "XcbLayerInterface.h"
#include "XcbEventInterface.h"
#include "XcbWindowInterface.h"
#include "GlxInterface.h" #include "GlxInterface.h"
#include "FileLogger.h"
XcbInterface::XcbInterface() XcbInterface::XcbInterface()
: mUseOpenGl(true), : mUseOpenGl(true),
mConnection(nullptr), mConnection(nullptr),
mScreen(nullptr),
mWindows(),
mHandles(),
mDefaultWindow(-1),
mGraphicsContext(-1),
mX11Display(), mX11Display(),
mGlxInterface() mGlxInterface(),
mXcbEventInterface(XcbEventInterface::Create()),
mXcbWindowInterface(XcbWindowInterface::Create())
{ {
} }
@ -39,13 +41,12 @@ void XcbInterface::SetUseOpenGl(bool use)
mUseOpenGl = use; mUseOpenGl = use;
} }
void XcbInterface::Initialize() void XcbInterface::Initialize(DesktopManager* desktopManager)
{ {
Connect(); Connect();
UpdateScreen(); UpdateScreen(desktopManager);
CreateGraphicsContext(); CreateGraphicsContext(desktopManager);
if (mUseOpenGl)
if(mUseOpenGl)
{ {
InitializeOpenGl(); InitializeOpenGl();
} }
@ -53,31 +54,21 @@ void XcbInterface::Initialize()
void XcbInterface::Connect() void XcbInterface::Connect()
{ {
if(mUseOpenGl) if (mUseOpenGl)
{ {
/* Open Xlib Display */
mX11Display = XOpenDisplay(0); mX11Display = XOpenDisplay(0);
if(!mX11Display) if (!mX11Display)
{ {
std::cerr << "Can't open X11 display" << std::endl; MLOG_ERROR("Can't open X11 display");
return; return;
} }
else
{
std::cout << "Got display" << std::endl;
}
/* Get the XCB connection from the display */
mConnection = XGetXCBConnection(mX11Display); mConnection = XGetXCBConnection(mX11Display);
if(!mConnection) if (!mConnection)
{ {
XCloseDisplay(mX11Display); XCloseDisplay(mX11Display);
std::cerr << "Can't get xcb connection from display" << std::endl; MLOG_ERROR("Can't get xcb connection from display");
return; return;
} }
std::cout << "Got connection" << std::endl;
/* Acquire event queue ownership */
XSetEventQueueOwner(mX11Display, XCBOwnsEventQueue); XSetEventQueueOwner(mX11Display, XCBOwnsEventQueue);
} }
else else
@ -86,225 +77,130 @@ void XcbInterface::Connect()
} }
} }
void XcbInterface::UpdateScreen() void XcbInterface::UpdateScreen(DesktopManager* desktopManager)
{ {
if(!mConnection) return; if (!mConnection)
auto screen_iter = xcb_setup_roots_iterator(xcb_get_setup(mConnection));
if(mUseOpenGl)
{ {
if(!mX11Display) return; return;
int default_screen = DefaultScreen(mX11Display); }
for(int screen_num = default_screen; auto screen_iter = xcb_setup_roots_iterator(xcb_get_setup(mConnection));
screen_iter.rem && screen_num > 0; if (mUseOpenGl)
{
if (!mX11Display)
{
return;
}
const auto default_screen = DefaultScreen(mX11Display);
for(int screen_num = default_screen; screen_iter.rem && screen_num > 0;
--screen_num, xcb_screen_next(&screen_iter)); --screen_num, xcb_screen_next(&screen_iter));
} }
mScreen = screen_iter.data; auto xcb_screen = XcbScreen::Create(screen_iter.data);
auto screen = mt::Screen::Create();
screen->SetPlatformScreen(std::move(xcb_screen));
desktopManager->AddScreen(std::move(screen));
} }
void XcbInterface::InitializeOpenGl() void XcbInterface::InitializeOpenGl()
{ {
mGlxInterface = GlxInterface::Create(); mGlxInterface = GlxInterface::Create();
int default_screen = DefaultScreen(mX11Display); const auto default_screen = DefaultScreen(mX11Display);
mGlxInterface->SetupContext(mX11Display, default_screen); mGlxInterface->SetupContext(mX11Display, default_screen);
} }
void XcbInterface::CreateOpenGlDrawable(mt::Window* window) void XcbInterface::CreateOpenGlDrawable(mt::Window* window)
{ {
if(!mUseOpenGl or !window) if (!mUseOpenGl or !window or !window->GetPlatformWindow())
{ {
return; return;
} }
auto hwnd = mHandles[window]; auto xcb_window = dynamic_cast<XcbWindow*>(window->GetPlatformWindow());
bool result = mGlxInterface->SetupWindow(mX11Display, hwnd); if (!xcb_window)
if(!result)
{ {
xcb_destroy_window(mConnection, hwnd); return;
}
if (!mGlxInterface->SetupWindow(mX11Display, xcb_window->GetHandle()))
{
xcb_destroy_window(mConnection, xcb_window->GetHandle());
} }
} }
void XcbInterface::CreateGraphicsContext() void XcbInterface::CreateGraphicsContext(DesktopManager* desktopManager)
{ {
if(!mConnection || !mScreen) return; if (!mConnection || desktopManager->GetDefaultScreen())
mGraphicsContext = xcb_generate_id(mConnection); {
return;
}
auto xcb_screen = dynamic_cast<XcbScreen*>(desktopManager->GetDefaultScreen()->GetPlatformScreen());
if (!xcb_screen)
{
return;
}
xcb_drawable_t window = mScreen->root; auto gc = xcb_generate_id(mConnection);
xcb_drawable_t window = xcb_screen->GetNativeScreen()->root;
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
uint32_t values[2] = {XcbLayerInterface::GetColor(240, 240, 240), 0}; uint32_t values[2] = {XcbLayerInterface::GetColor(240, 240, 240), 0};
xcb_create_gc(mConnection, mGraphicsContext, window, mask, values); xcb_create_gc(mConnection, gc, window, mask, values);
xcb_screen->SetGraphicsContext(gc);
} }
void XcbInterface::MapWindow(mt::Window* window) void XcbInterface::MapWindow(mt::Window* window)
{ {
if(!mConnection or !window) return; mXcbWindowInterface->Map(window, mConnection);
xcb_map_window(mConnection, mHandles[window]);
xcb_flush(mConnection);
} }
void XcbInterface::ShowWindow(mt::Window* window) void XcbInterface::ShowWindow(mt::Window* window)
{ {
MapWindow(window); mXcbWindowInterface->Show(window, mConnection);
} }
uint32_t XcbInterface::GetEventMask() uint32_t XcbInterface::GetEventMask()
{ {
return XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | return XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION; XCB_EVENT_MASK_EXPOSURE;
} }
void XcbInterface::AddWindow(mt::Window* window) void XcbInterface::AddWindow(mt::Window* window, DesktopManager* desktopManager)
{ {
if(!mConnection || !mScreen || !window) return; auto screen = desktopManager->GetDefaultScreen();
auto hwnd = xcb_generate_id(mConnection); mXcbWindowInterface->Add(window, mConnection, screen, GetEventMask());
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t values[2] = {mScreen->white_pixel, GetEventMask()};
xcb_create_window (mConnection, /* connection */
XCB_COPY_FROM_PARENT, /* depth */
hwnd, /* window Id */
mScreen->root, /* parent window */
0, 0, /* x, y */
window->GetWidth(), window->GetHeight(), /* width, height */
10, /* border_width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
mScreen->root_visual, /* visual */
mask, values ); /* masks */
mWindows[hwnd] = window;
mHandles[window] = hwnd;
mDefaultWindow = hwnd;
} }
void XcbInterface::onPaint(DesktopManager* desktopManager) void XcbInterface::onPaint(DesktopManager* desktopManager)
{ {
desktopManager->OnUiEvent(PaintEvent::Create()); desktopManager->OnUiEvent(PaintEvent::Create());
PaintWindow(desktopManager->GetWindowManager()->GetMainWindow()); auto mainWindow = desktopManager->GetWindowManager()->GetMainWindow();
auto defaultScreen = desktopManager->GetDefaultScreen();
auto xcb_screen = dynamic_cast<XcbScreen*>(defaultScreen->GetPlatformScreen());
mXcbWindowInterface->Paint(mainWindow, mConnection,
xcb_screen->GetNativeScreen(), xcb_screen->GetGraphicsContext());
} }
void XcbInterface::PaintWindow(mt::Window* window) void XcbInterface::OnExposeEvent(xcb_expose_event_t* event, DesktopManager* desktopManager)
{ {
if(!window) return; // Update the window
if (mUseOpenGl)
const auto hwnd = mHandles[window];
for(const auto& layer : window->GetLayers())
{ {
XcbLayerInterface::AddLayer(mConnection, mScreen,
hwnd, mGraphicsContext, layer);
}
}
void XcbInterface::OnKeyPress(xcb_key_press_event_t* event, DesktopManager* desktopManager)
{
auto ui_event = KeyboardEvent::Create();
ui_event->SetAction(KeyboardEvent::Action::Pressed);
std::string keyVal = desktopManager->GetKeyboard()->GetKeyString(event->detail);
ui_event->SetKeyString(keyVal);
desktopManager->OnUiEvent(std::move(ui_event));
}
void XcbInterface::OnKeyRelease(xcb_key_release_event_t* event, DesktopManager* desktopManager)
{
auto ui_event = KeyboardEvent::Create();
ui_event->SetAction(KeyboardEvent::Action::Released);
std::string keyVal = desktopManager->GetKeyboard()->GetKeyString(event->detail);
ui_event->SetKeyString(keyVal);
desktopManager->OnUiEvent(std::move(ui_event));
}
void XcbInterface::OnButtonPress(xcb_button_press_event_t* event, DesktopManager* desktopManager)
{
auto ui_event = MouseEvent::Create();
auto x = static_cast<unsigned>(event->event_x);
auto y = static_cast<unsigned>(event->event_y);
ui_event->SetClientLocation(DiscretePoint(x, y));
auto screen_x = static_cast<unsigned>(event->root_x);
auto screen_y = static_cast<unsigned>(event->root_y);
ui_event->SetScreenLocation(DiscretePoint(x, y));
ui_event->SetAction(MouseEvent::Action::Pressed);
desktopManager->OnUiEvent(std::move(ui_event));
}
void XcbInterface::OnButtonRelease(xcb_button_release_event_t* event, DesktopManager* desktopManager)
{
auto ui_event = MouseEvent::Create();
auto x = static_cast<unsigned>(event->event_x);
auto y = static_cast<unsigned>(event->event_y);
ui_event->SetClientLocation(DiscretePoint(x, y));
auto screen_x = static_cast<unsigned>(event->root_x);
auto screen_y = static_cast<unsigned>(event->root_y);
ui_event->SetScreenLocation(DiscretePoint(x, y));
ui_event->SetAction(MouseEvent::Action::Released);
desktopManager->OnUiEvent(std::move(ui_event));
}
void XcbInterface::LoopOpenGl(DesktopManager* desktopManager)
{
int running = 1;
while(running)
{
/* Wait for event */
xcb_generic_event_t *event = xcb_wait_for_event(mConnection);
if(!event)
{
std::cout << "i/o error in xcb_wait_for_event" << std::endl;
return;
}
switch(event->response_type & ~0x80)
{
case XCB_KEY_PRESS:
/* Quit on key press */
std::cout << "got key" << std::endl;
running = 0;
break;
case XCB_KEY_RELEASE:
/* Quit on key press */
std::cout << "got key" << std::endl;
running = 0;
break;
case XCB_EXPOSE:
std::cout << "got expose" << std::endl;
/* Handle expose event, draw and swap buffers */
mGlxInterface->Draw(); mGlxInterface->Draw();
mGlxInterface->SwapBuffers(mX11Display); mGlxInterface->SwapBuffers(mX11Display);
std::cout << "end expose" << std::endl;
break;
default:
std::cout << "got something else" << std::endl;
break;
} }
else
free(event); {
} //auto window = mWindows[event->window];
mGlxInterface->DestroyWindow(mX11Display); //window->SetSize(event->width, event->height);
//xcb_destroy_window(mConnection, window); onPaint(desktopManager);
mGlxInterface->DestroyContext(mX11Display);
return;
}
void XcbInterface::ClearWindow(mt::Window* window)
{
if(!window) return;
xcb_clear_area(mConnection, 1, mHandles[window], 0, 0,
window->GetWidth(), window->GetHeight());
xcb_flush(mConnection); xcb_flush(mConnection);
}
} }
void XcbInterface::Loop(DesktopManager* desktopManager) void XcbInterface::Loop(DesktopManager* desktopManager)
{ {
if(!mConnection) return; if (!mConnection)
if(mUseOpenGl)
{ {
LoopOpenGl(desktopManager);
return; return;
} }
xcb_generic_event_t *event; xcb_generic_event_t *event;
while ((event = xcb_wait_for_event(mConnection))) while ((event = xcb_wait_for_event(mConnection)))
{ {
@ -312,58 +208,69 @@ void XcbInterface::Loop(DesktopManager* desktopManager)
{ {
case XCB_EXPOSE:{ case XCB_EXPOSE:{
auto expose_event = reinterpret_cast<xcb_expose_event_t*>(event); auto expose_event = reinterpret_cast<xcb_expose_event_t*>(event);
OnExposeEvent(expose_event, desktopManager);
// Update the window
auto window = mWindows[expose_event->window];
window->SetSize(expose_event->width, expose_event->height);
onPaint(desktopManager);
/* flush the request */
xcb_flush(mConnection);
break; break;
} }
case XCB_KEY_PRESS: { case XCB_KEY_PRESS: {
auto kr = reinterpret_cast<xcb_key_press_event_t*>(event); auto kp = reinterpret_cast<xcb_key_press_event_t*>(event);
OnKeyPress(kr, desktopManager); auto ui_event = mXcbEventInterface->ConvertKeyPress(kp, desktopManager->GetKeyboard());
desktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
case XCB_KEY_RELEASE: { case XCB_KEY_RELEASE: {
auto kr = reinterpret_cast<xcb_key_release_event_t*>(event); auto kr = reinterpret_cast<xcb_key_release_event_t*>(event);
OnKeyRelease(kr, desktopManager); auto ui_event = mXcbEventInterface->ConvertKeyRelease(kr, desktopManager->GetKeyboard());
desktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
case XCB_BUTTON_PRESS: { case XCB_BUTTON_PRESS: {
auto press = reinterpret_cast<xcb_button_press_event_t*>(event); auto press = reinterpret_cast<xcb_button_press_event_t*>(event);
OnButtonPress(press, desktopManager); auto ui_event = mXcbEventInterface->ConvertButtonPress(press);
desktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
case XCB_BUTTON_RELEASE: { case XCB_BUTTON_RELEASE: {
auto release = reinterpret_cast<xcb_button_release_event_t*>(event); auto release = reinterpret_cast<xcb_button_release_event_t*>(event);
OnButtonRelease(release, desktopManager); auto ui_event = mXcbEventInterface->ConvertButtonRelease(release);
desktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
default: default:
/* Unknown event type, ignore it */ /* Unknown event type, ignore it */
break; break;
} }
if(desktopManager->IsModified()) onEventsDispatched(desktopManager);
free(event);
}
OnLoopCompleted(desktopManager);
}
void XcbInterface::OnLoopCompleted(DesktopManager* desktopManagers)
{
if (mUseOpenGl)
{
mGlxInterface->DestroyWindow(mX11Display);
mGlxInterface->DestroyContext(mX11Display);
}
}
void XcbInterface::onEventsDispatched(DesktopManager* desktopManager)
{
if (desktopManager->IsModified())
{ {
desktopManager->SetIsModified(false); desktopManager->SetIsModified(false);
ClearWindow(desktopManager->GetWindowManager()->GetMainWindow()); auto mainWindow = desktopManager->GetWindowManager()->GetMainWindow();
} mXcbWindowInterface->Clear(mainWindow, mConnection);
free (event);
} }
} }
void XcbInterface::ShutDown() void XcbInterface::ShutDown()
{ {
if(!mConnection) return; if (!mConnection)
std::cout << "starting shutdown" << std::endl;
xcb_disconnect(mConnection);
if(mUseOpenGl && mX11Display)
{ {
//XCloseDisplay(mX11Display); return;
} }
std::cout << "ending shutdown" << std::endl; MLOG_INFO("starting shutdown");
xcb_disconnect(mConnection);
MLOG_INFO("Ending shutdown");
} }

View file

@ -1,86 +1,70 @@
#pragma once #pragma once
#include "Window.h"
#include <memory> #include <memory>
#include <map> #include <map>
#include "Window.h"
#include "VisualLayer.h"
class DesktopManager; class DesktopManager;
using DesktopManagerPtr = std::shared_ptr<DesktopManager>;
class GlxInterface; class GlxInterface;
using GlxInterfacePtr = std::shared_ptr<GlxInterface>; using GlxInterfacePtr = std::unique_ptr<GlxInterface>;
class XcbEventInterface;
using XcbEventInterfacePtr = std::unique_ptr<XcbEventInterface>;
class XcbWindowInterface;
using XcbWindowInterfacePtr = std::unique_ptr<XcbWindowInterface>;
struct xcb_screen_t;
struct xcb_connection_t; struct xcb_connection_t;
struct xcb_key_press_event_t; struct xcb_expose_event_t;
struct xcb_button_press_event_t;
struct _XDisplay; struct _XDisplay;
class XcbInterface class XcbInterface
{ {
private:
bool mUseOpenGl;
std::map<unsigned, mt::Window*> mWindows;
std::map<mt::Window*, unsigned> mHandles;
unsigned mDefaultWindow;
xcb_connection_t* mConnection;
xcb_screen_t* mScreen;
unsigned mGraphicsContext;
_XDisplay* mX11Display;
GlxInterfacePtr mGlxInterface;
public: public:
XcbInterface(); XcbInterface();
~XcbInterface(); ~XcbInterface();
void SetUseOpenGl(bool use); void SetUseOpenGl(bool use);
void onPaint(DesktopManager* desktopManager);
void Initialize(); void Initialize(DesktopManager* desktopManager);
void InitializeOpenGl();
void CreateOpenGlDrawable(mt::Window* window);
void Loop(DesktopManager* desktopManager); void Loop(DesktopManager* desktopManager);
void LoopOpenGl(DesktopManager* desktopManager);
void ShutDown(); void ShutDown();
void AddWindow(mt::Window* window);
void ShowWindow(mt::Window* window); void ShowWindow(mt::Window* window);
void PaintWindow(mt::Window* window); void AddWindow(mt::Window* window, DesktopManager* desktopManager);
void ClearWindow(mt::Window* window); void CreateOpenGlDrawable(mt::Window* window);
private: private:
void onPaint(DesktopManager* desktopManager);
void InitializeOpenGl();
void Connect(); void Connect();
void UpdateScreen(); void UpdateScreen(DesktopManager* desktopManager);
void OnExposeEvent(xcb_expose_event_t* event, DesktopManager* desktopManager);
uint32_t GetEventMask(); uint32_t GetEventMask();
void OnKeyPress(xcb_key_press_event_t* event, DesktopManager*);
void OnKeyRelease(xcb_key_press_event_t* event, DesktopManager*);
void OnButtonPress(xcb_button_press_event_t* event, DesktopManager*);
void OnButtonRelease(xcb_button_press_event_t* event, DesktopManager*);
void MapWindow(mt::Window* window); void MapWindow(mt::Window* window);
void CreateGraphicsContext(); void CreateGraphicsContext(DesktopManager* desktopManager);
void onEventsDispatched(DesktopManager* desktopManager);
void OnLoopCompleted(DesktopManager* desktopManagers);
private:
bool mUseOpenGl {false};
xcb_connection_t* mConnection;
_XDisplay* mX11Display;
GlxInterfacePtr mGlxInterface;
XcbEventInterfacePtr mXcbEventInterface {nullptr};
XcbWindowInterfacePtr mXcbWindowInterface {nullptr};
}; };

View file

@ -0,0 +1,29 @@
#include "XcbScreen.h"
#include <xcb/xcb.h>
XcbScreen::XcbScreen(xcb_screen_t* screen)
: mNativeScreen(screen)
{
}
std::unique_ptr<XcbScreen> XcbScreen::Create(xcb_screen_t* screen)
{
return std::make_unique<XcbScreen>(screen);
}
xcb_screen_t* XcbScreen::GetNativeScreen() const
{
return mNativeScreen;
}
void XcbScreen::SetGraphicsContext(unsigned gc)
{
mGraphicsContext = gc;
}
unsigned XcbScreen::GetGraphicsContext() const
{
return mGraphicsContext;
}

View file

@ -0,0 +1,28 @@
#pragma
#include "IPlatformScreen.h"
struct xcb_screen_t;
class XcbScreen : public IPlatformScreen
{
public:
XcbScreen(xcb_screen_t* screen);
virtual ~XcbScreen() = default;
static std::unique_ptr<XcbScreen> Create(xcb_screen_t* screen);
xcb_screen_t* GetNativeScreen() const;
void SetGraphicsContext(unsigned gc);
unsigned GetGraphicsContext() const;
private:
unsigned mGraphicsContext {0};
xcb_screen_t* mNativeScreen {nullptr};
};
using XcbScreenPtr = std::unique_ptr<XcbScreen>;

View file

@ -0,0 +1,22 @@
#include "XcbWindow.h"
XcbWindow::XcbWindow(int hwnd)
: mHandle(hwnd)
{
}
std::unique_ptr<XcbWindow> XcbWindow::Create(int hwnd)
{
return std::make_unique<XcbWindow>(hwnd);
}
int XcbWindow::GetHandle() const
{
return mHandle;
}
unsigned XcbWindow::GetGraphicsContext() const
{
return mGraphicsContext;
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "IPlatformWindow.h"
class XcbWindow : public IPlatformWindow
{
public:
XcbWindow(int hwnd);
virtual ~XcbWindow() = default;
static std::unique_ptr<XcbWindow> Create(int hwnd);
int GetHandle() const;
unsigned GetGraphicsContext() const;
private:
int mHandle{-1};
unsigned mGraphicsContext {0};
};
using XcbWindowPtr = std::unique_ptr<XcbWindow>;

View file

@ -0,0 +1,80 @@
#include "XcbWindowInterface.h"
#include "Window.h"
#include "XcbWindow.h"
#include "Screen.h"
#include "XcbScreen.h"
#include "XcbLayerInterface.h"
#include <xcb/xcb.h>
std::unique_ptr<XcbWindowInterface> XcbWindowInterface::Create()
{
return std::make_unique<XcbWindowInterface>();
}
void XcbWindowInterface::Add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask) const
{
if (!connection || !screen || !window)
{
return;
}
auto xcb_screen = dynamic_cast<XcbScreen*>(screen->GetPlatformScreen());
auto hwnd = xcb_generate_id(connection);
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t values[2] = {xcb_screen->GetNativeScreen()->white_pixel, eventMask};
xcb_create_window (connection, /* connection */
XCB_COPY_FROM_PARENT, /* depth */
hwnd, /* window Id */
xcb_screen->GetNativeScreen()->root, /* parent window */
0, 0, /* x, y */
window->GetWidth(), window->GetHeight(), /* width, height */
10, /* border_width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
xcb_screen->GetNativeScreen()->root_visual, /* visual */
mask, values ); /* masks */
auto xcb_window = XcbWindow::Create(hwnd);
window->SetPlatformWindow(std::move(xcb_window));
}
void XcbWindowInterface::Show(mt::Window* window, xcb_connection_t* connection) const
{
Map(window, connection);
}
void XcbWindowInterface::Paint(mt::Window* window, xcb_connection_t* connection, xcb_screen_t* screen, unsigned gc) const
{
if (!window)
{
return;
}
auto xcb_window = dynamic_cast<XcbWindow*>(window->GetPlatformWindow());
for(const auto& layer : window->GetLayers())
{
XcbLayerInterface::AddLayer(connection, screen, xcb_window->GetHandle(), gc, layer);
}
}
void XcbWindowInterface::Clear(mt::Window* window, xcb_connection_t* connection) const
{
if (!window)
{
return;
}
auto xcb_window = dynamic_cast<XcbWindow*>(window->GetPlatformWindow());
xcb_clear_area(connection, 1, xcb_window->GetHandle(), 0, 0, window->GetWidth(), window->GetHeight());
xcb_flush(connection);
}
void XcbWindowInterface::Map(mt::Window* window, xcb_connection_t* connection) const
{
if (!connection or !window)
{
return;
}
auto xcb_window = dynamic_cast<XcbWindow*>(window->GetPlatformWindow());
xcb_map_window(connection, xcb_window->GetHandle());
xcb_flush(connection);
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <memory>
namespace mt
{
class Window;
class Screen;
}
struct xcb_connection_t;
struct xcb_screen_t;
class XcbWindowInterface
{
public:
static std::unique_ptr<XcbWindowInterface> Create();
void Add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask) const;
void Show(mt::Window* window, xcb_connection_t* connection) const;
void Paint(mt::Window* window, xcb_connection_t* connection, xcb_screen_t* screen, unsigned gc) const;
void Clear(mt::Window* window, xcb_connection_t* connection) const;
void Map(mt::Window* window, xcb_connection_t* connection) const;
};
using XcbWindowInterfacePtr = std::unique_ptr<XcbWindowInterface>;