diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 84edc8e..8c335f3 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -7,6 +7,7 @@ target_include_directories(sample_gui PUBLIC target_link_libraries(sample_gui PUBLIC client windows console core network database geometry audio web) +if(WIN32) add_executable(sample_gui_win WIN32 gui-main-win.cpp) target_include_directories(sample_gui PUBLIC "${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 network database geometry audio web) +set_property(TARGET sample_gui_win PROPERTY FOLDER apps) +endif() # Sample Console 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_gui PROPERTY FOLDER apps) -set_property(TARGET sample_gui_win PROPERTY FOLDER apps) set_property(TARGET xml_practice PROPERTY FOLDER apps) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 10c3941..294fd2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,4 +8,5 @@ add_subdirectory(client) add_subdirectory(graphics) add_subdirectory(windows) add_subdirectory(web) -add_subdirectory(ui_elements) \ No newline at end of file +add_subdirectory(ui_elements) +add_subdirectory(visual_elements) \ No newline at end of file diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index 81a40e4..204d233 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -20,7 +20,7 @@ std::unique_ptr AudioManager::Create() void AudioManager::AddAudioDevice(AudioDevicePtr device) { - mAudioDevices.push_back(device); + mAudioDevices.push_back(std::move(device)); } IAudioInterface* AudioManager::GetAudioInterface() @@ -28,7 +28,26 @@ IAudioInterface* AudioManager::GetAudioInterface() return mAudioInterface.get(); } -std::vector 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]); } diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index de13da2..2140c50 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -24,9 +24,13 @@ public: void AddAudioDevice(AudioDevicePtr device); - std::vector GetAudioDevices(); + unsigned GetNumAudioDevices() const; + + AudioDevice* GetAudioDevice(unsigned idx) const; IAudioInterface* GetAudioInterface(); + + void Play(); }; using AudioManagerUPtr = std::unique_ptr; diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 026b168..a3f641e 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -1,5 +1,9 @@ + +find_package(ALSA REQUIRED) + list(APPEND linux_HEADERS audio_interfaces/AlsaInterface.h + ${ALSA_INCLUDE_DIRS} ) list(APPEND audio_HEADERS @@ -37,7 +41,7 @@ target_include_directories(audio PUBLIC ) list(APPEND linux_LIBS - asound + ${ALSA_LIBRARIES} ) target_link_libraries(audio PUBLIC core ${linux_LIBS}) diff --git a/src/audio/audio_interfaces/AlsaInterface.cpp b/src/audio/audio_interfaces/AlsaInterface.cpp index 2f71027..6375a4c 100644 --- a/src/audio/audio_interfaces/AlsaInterface.cpp +++ b/src/audio/audio_interfaces/AlsaInterface.cpp @@ -14,9 +14,9 @@ AlsaInterface::~AlsaInterface() } -std::shared_ptr AlsaInterface::Create() +std::unique_ptr AlsaInterface::Create() { - return std::make_shared(); + return std::make_unique(); } 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) { 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 */ 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 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. */ 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(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 */ if (snd_pcm_hw_params_set_channels(mHandle, mHardwareParams, device->GetNumChannels()) < 0) diff --git a/src/audio/audio_interfaces/AlsaInterface.h b/src/audio/audio_interfaces/AlsaInterface.h index 2a733f7..f78645d 100644 --- a/src/audio/audio_interfaces/AlsaInterface.h +++ b/src/audio/audio_interfaces/AlsaInterface.h @@ -19,21 +19,21 @@ public: ~AlsaInterface(); - static std::shared_ptr Create(); + static std::unique_ptr Create(); 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; }; diff --git a/src/client/GuiApplication.cpp b/src/client/GuiApplication.cpp index 598ce8e..45f6d4e 100644 --- a/src/client/GuiApplication.cpp +++ b/src/client/GuiApplication.cpp @@ -77,13 +77,13 @@ void GuiApplication::Run() mDesktopManager->SetKeyboard(XcbKeyboard::Create()); - bool useOpenGl = false; + bool useOpenGl = true; XcbInterface window_interface; window_interface.SetUseOpenGl(useOpenGl); - window_interface.Initialize(); - window_interface.AddWindow(mainWindow); + window_interface.Initialize(mDesktopManager.get()); + window_interface.AddWindow(mainWindow, mDesktopManager.get()); window_interface.ShowWindow(mainWindow); - if(useOpenGl) + if (useOpenGl) { window_interface.CreateOpenGlDrawable(mainWindow); } diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt index 3baae5b..90e50bf 100644 --- a/src/console/CMakeLists.txt +++ b/src/console/CMakeLists.txt @@ -15,9 +15,10 @@ target_include_directories(console PUBLIC "${PROJECT_SOURCE_DIR}/src/audio" "${PROJECT_SOURCE_DIR}/src/audio/midi" "${PROJECT_SOURCE_DIR}/src/audio/audio_interfaces" + "${PROJECT_SOURCE_DIR}/src/graphics" "${PROJECT_SOURCE_DIR}/src/web" "${SQLite3_INCLUDE_DIR}" ) 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 ) \ No newline at end of file diff --git a/src/console/MainApplication.cpp b/src/console/MainApplication.cpp index 01e604f..8e41a55 100644 --- a/src/console/MainApplication.cpp +++ b/src/console/MainApplication.cpp @@ -3,6 +3,12 @@ #include "MidiReader.h" #include "File.h" #include "DocumentConverter.h" +#include "DrawingManager.h" +#include "DrawingSurface.h" +#include "DrawingContext.h" + +#include "TextElement.h" +#include "DiscretePoint.h" #include MainApplication::MainApplication() @@ -69,6 +75,15 @@ void MainApplication::Run() { 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 { MLOG_ERROR("Unknown program type: " + program_type); @@ -84,9 +99,7 @@ void MainApplication::PlayAudio() { //MidiReader reader; //reader.Read("/home/james/sample.mid"); - auto device = AudioDevice::Create(); - mAudioManager->GetAudioInterface()->OpenDevice(device); - mAudioManager->GetAudioInterface()->Play(device); + mAudioManager->Play(); } void MainApplication::ConvertDocument(const std::string& inputPath, const std::string& outputPath) diff --git a/src/core/loggers/FileLogger.cpp b/src/core/loggers/FileLogger.cpp index 052cdaa..e93b32b 100644 --- a/src/core/loggers/FileLogger.cpp +++ b/src/core/loggers/FileLogger.cpp @@ -10,38 +10,38 @@ FileLogger::~FileLogger() void FileLogger::SetWorkDirectory(const std::string& workDir) { - mWorkDirectory = workDir; + mWorkDirectory = workDir; } void FileLogger::SetFileName(const std::string& fileName) { - mFileName = fileName; + mFileName = fileName; } void FileLogger::Open() { - mFileStream.open(mWorkDirectory + "/" + mFileName); + mFileStream.open(mWorkDirectory + "/" + mFileName); } void FileLogger::Close() { - mFileStream.close(); + mFileStream.close(); } void FileLogger::LogLine(const std::string& line) { - mFileStream << line << std::endl; + mFileStream << line << std::endl; } void FileLogger::LogLine(const std::string& logType, const std::string& line, const std::string& fileName, const std::string& functionName, int lineNumber) { - std::time_t t = std::time(nullptr); - const std::string cleanedFileName = fileName.substr(fileName.find_last_of("/\\") + 1); - std::tm time_buf = { 0 }; + std::time_t t = std::time(nullptr); + const std::string cleanedFileName = fileName.substr(fileName.find_last_of("/\\") + 1); + std::tm time_buf = { 0 }; #ifdef WIN32 - gmtime_s(&time_buf, &t); + gmtime_s(&time_buf, &t); #else - gmtime_r(&t, &time_buf); + gmtime_r(&t, &time_buf); #endif - mFileStream << logType << "|" << std::put_time(&time_buf, "%T") << "|" << cleanedFileName << "::" << functionName << "::" << lineNumber << "|" << line << std::endl; + mFileStream << logType << "|" << std::put_time(&time_buf, "%T") << "|" << cleanedFileName << "::" << functionName << "::" << lineNumber << "|" << line << std::endl; } diff --git a/src/core/loggers/FileLogger.h b/src/core/loggers/FileLogger.h index 2f9294a..bc149d6 100644 --- a/src/core/loggers/FileLogger.h +++ b/src/core/loggers/FileLogger.h @@ -8,19 +8,17 @@ class FileLogger { - std::string mWorkDirectory; + std::string mWorkDirectory; + std::string mFileName; + std::ofstream mFileStream; - std::string mFileName; + FileLogger() + :mWorkDirectory(), + mFileName("MT_Log.txt"), + mFileStream() + { - std::ofstream mFileStream; - - FileLogger() - :mWorkDirectory(), - mFileName("MT_Log.txt"), - mFileStream() - { - - } + } public: @@ -30,22 +28,22 @@ public: return instance; } - FileLogger(FileLogger const&) = delete; + FileLogger(FileLogger const&) = delete; void operator=(FileLogger const&) = delete; - ~FileLogger(); + ~FileLogger(); - void SetWorkDirectory(const std::string& workDir); + void SetWorkDirectory(const std::string& workDir); - void SetFileName(const std::string& fileName); + void SetFileName(const std::string& fileName); - void Open(); + void Open(); - void Close(); + void Close(); - void LogLine(const std::string& line); + void LogLine(const std::string& line); - void LogLine(const std::string& logType, const std::string& line, const std::string& fileName = "", const std::string& functionName = "", int lineNumber=-1); + void LogLine(const std::string& logType, const std::string& line, const std::string& fileName = "", const std::string& functionName = "", int lineNumber=-1); }; diff --git a/src/geometry/CMakeLists.txt b/src/geometry/CMakeLists.txt index 53e9e69..59e92a8 100644 --- a/src/geometry/CMakeLists.txt +++ b/src/geometry/CMakeLists.txt @@ -1,6 +1,8 @@ list(APPEND geometry_LIB_INCLUDES DiscretePoint.cpp - Point.cpp) + Point.cpp + Rectangle.cpp) + # add the library add_library(geometry SHARED ${geometry_LIB_INCLUDES}) diff --git a/src/graphics/CMakeLists.txt b/src/graphics/CMakeLists.txt index 07ac0b5..7bd17cd 100644 --- a/src/graphics/CMakeLists.txt +++ b/src/graphics/CMakeLists.txt @@ -1,8 +1,46 @@ -list(APPEND graphics_LIB_INCLUDES OpenGlInterface.cpp) -list(APPEND graphics_HEADERS OpenGlInterface.h) +list(APPEND graphics_LIB_INCLUDES + DrawingContext.cpp + DrawingManager.cpp + DrawingSurface.cpp + opengl/OpenGlInterface.cpp + cairo/CairoInterface.cpp + cairo/CairoDrawingSurface.cpp + cairo/CairoDrawingContext.cpp) + +list(APPEND graphics_HEADERS + opengl/OpenGlInterface.h + cairo/CairoInterface.h + INativeDrawingSurface.h + INativeDrawingContext.h) -add_library(graphics SHARED ${graphics_LIB_INCLUDES} ${graphics_HEADERS}) +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 GL) +target_link_libraries(graphics PUBLIC visual_elements GL ${CAIRO_LIBRARIES}) set_property(TARGET graphics PROPERTY FOLDER src) \ No newline at end of file diff --git a/src/graphics/DrawingContext.cpp b/src/graphics/DrawingContext.cpp new file mode 100644 index 0000000..11fc990 --- /dev/null +++ b/src/graphics/DrawingContext.cpp @@ -0,0 +1,18 @@ +#include "DrawingContext.h" + +#include "INativeDrawingContext.h" + +std::unique_ptr DrawingContext::Create() +{ + return std::make_unique(); +} + +void DrawingContext::SetNativeContext(std::unique_ptr context) +{ + mNativeDrawingContext = std::move(context); +} + +INativeDrawingContext* DrawingContext::GetNativeContext() +{ + return mNativeDrawingContext.get(); +} diff --git a/src/graphics/DrawingContext.h b/src/graphics/DrawingContext.h new file mode 100644 index 0000000..ecc411a --- /dev/null +++ b/src/graphics/DrawingContext.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +class INativeDrawingContext; + +class DrawingContext +{ +public: + DrawingContext() = default; + + static std::unique_ptr Create(); + + void SetNativeContext(std::unique_ptr context); + + INativeDrawingContext* GetNativeContext(); + +private: + + std::unique_ptr mNativeDrawingContext; +}; + +using DrawingContextPtr = std::unique_ptr; diff --git a/src/graphics/DrawingManager.cpp b/src/graphics/DrawingManager.cpp new file mode 100644 index 0000000..b36c9c1 --- /dev/null +++ b/src/graphics/DrawingManager.cpp @@ -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::Create() +{ + return std::make_unique(); +} + +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); + } +} diff --git a/src/graphics/DrawingManager.h b/src/graphics/DrawingManager.h new file mode 100644 index 0000000..0515b84 --- /dev/null +++ b/src/graphics/DrawingManager.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "INativeDrawingContext.h" +#include "INativeDrawingSurface.h" +#include "CairoInterface.h" + +class TextElement; + +class DrawingSurface; +using DrawingSurfacePtr = std::unique_ptr; +class DrawingContext; +using DrawingContextPtr = std::unique_ptr; + +class DrawingManager +{ +public: + DrawingManager(); + static std::unique_ptr 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; diff --git a/src/graphics/DrawingSurface.cpp b/src/graphics/DrawingSurface.cpp new file mode 100644 index 0000000..3f1e254 --- /dev/null +++ b/src/graphics/DrawingSurface.cpp @@ -0,0 +1,40 @@ +#include "DrawingSurface.h" + + +std::unique_ptr DrawingSurface::Create() +{ + return std::make_unique(); +} + +INativeDrawingSurface* DrawingSurface::GetNativeSurface() +{ + if (mNativeDrawingSurface) + { + return mNativeDrawingSurface.get(); + } + else + { + return nullptr; + } +} + +void DrawingSurface::SetNativeSurface(std::unique_ptr 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; +} diff --git a/src/graphics/DrawingSurface.h b/src/graphics/DrawingSurface.h new file mode 100644 index 0000000..ea08136 --- /dev/null +++ b/src/graphics/DrawingSurface.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "INativeDrawingSurface.h" + +class DrawingSurface +{ +public: + DrawingSurface() = default; + + static std::unique_ptr Create(); + + INativeDrawingSurface* GetNativeSurface(); + + void SetNativeSurface(std::unique_ptr surface); + + void SetSize(unsigned width, unsigned height); + + unsigned GetWidth() const; + + unsigned GetHeight() const; + +private: + + unsigned mWidth = 0; + unsigned mHeight = 0; + std::unique_ptr mNativeDrawingSurface; +}; diff --git a/src/graphics/INativeDrawingContext.h b/src/graphics/INativeDrawingContext.h new file mode 100644 index 0000000..c0eb1ce --- /dev/null +++ b/src/graphics/INativeDrawingContext.h @@ -0,0 +1,8 @@ +#pragma once + +class INativeDrawingContext +{ +public: + + virtual ~INativeDrawingContext() = default; +}; diff --git a/src/graphics/INativeDrawingSurface.h b/src/graphics/INativeDrawingSurface.h new file mode 100644 index 0000000..e5f1780 --- /dev/null +++ b/src/graphics/INativeDrawingSurface.h @@ -0,0 +1,9 @@ +#pragma once + +class INativeDrawingSurface +{ +public: + virtual ~INativeDrawingSurface() = default; + + virtual void DestroyNativeSurface() = 0; +}; diff --git a/src/graphics/cairo/CairoDrawingContext.cpp b/src/graphics/cairo/CairoDrawingContext.cpp new file mode 100644 index 0000000..fa2cca4 --- /dev/null +++ b/src/graphics/cairo/CairoDrawingContext.cpp @@ -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::Create(cairo_t* context) + { + return std::make_unique(context); + } + + void CairoDrawingContext::DestroyNativeContext() + { + if (mNativeContext) + { + cairo_destroy (mNativeContext); + mNativeContext = nullptr; + } + } diff --git a/src/graphics/cairo/CairoDrawingContext.h b/src/graphics/cairo/CairoDrawingContext.h new file mode 100644 index 0000000..6286a5c --- /dev/null +++ b/src/graphics/cairo/CairoDrawingContext.h @@ -0,0 +1,27 @@ +#pragma once + +#include "INativeDrawingContext.h" + +#include +#include + +class CairoDrawingContext : public INativeDrawingContext +{ +public: + + CairoDrawingContext(cairo_t* context); + + virtual ~CairoDrawingContext(); + + static std::unique_ptr Create(cairo_t* context); + + cairo_t* GetNativeContext(); + + void DestroyNativeContext(); + +private: + cairo_t* mNativeContext; +}; + +using CairoDrawingContextPtr = std::unique_ptr; + diff --git a/src/graphics/cairo/CairoDrawingSurface.cpp b/src/graphics/cairo/CairoDrawingSurface.cpp new file mode 100644 index 0000000..28f31e0 --- /dev/null +++ b/src/graphics/cairo/CairoDrawingSurface.cpp @@ -0,0 +1,31 @@ +#include "CairoDrawingSurface.h" + +CairoDrawingSurface::CairoDrawingSurface(cairo_surface_t* surface) + : mNativeSurface(surface) +{ + +} + +CairoDrawingSurface::~CairoDrawingSurface() +{ + DestroyNativeSurface(); +} + +std::unique_ptr CairoDrawingSurface::Create(cairo_surface_t* surface) +{ + return std::make_unique(surface); +} + +cairo_surface_t* CairoDrawingSurface::GetNativeSurface() +{ + return mNativeSurface; +} + +void CairoDrawingSurface::DestroyNativeSurface() +{ + if (mNativeSurface) + { + cairo_surface_destroy (mNativeSurface); + mNativeSurface = nullptr; + } +} diff --git a/src/graphics/cairo/CairoDrawingSurface.h b/src/graphics/cairo/CairoDrawingSurface.h new file mode 100644 index 0000000..c6cfa79 --- /dev/null +++ b/src/graphics/cairo/CairoDrawingSurface.h @@ -0,0 +1,27 @@ +#pragma once + +#include "INativeDrawingSurface.h" + +#include + +#include + +class CairoDrawingSurface : public INativeDrawingSurface +{ +public: + + CairoDrawingSurface(cairo_surface_t* surface); + + virtual ~CairoDrawingSurface(); + + static std::unique_ptr Create(cairo_surface_t* surface); + + cairo_surface_t* GetNativeSurface(); + + void DestroyNativeSurface() override; + +private: + cairo_surface_t* mNativeSurface; +}; + +using CairoDrawingSurfacePtr = std::unique_ptr; diff --git a/src/graphics/cairo/CairoInterface.cpp b/src/graphics/cairo/CairoInterface.cpp new file mode 100644 index 0000000..344f96d --- /dev/null +++ b/src/graphics/cairo/CairoInterface.cpp @@ -0,0 +1,51 @@ +#include "CairoInterface.h" + +#include "DrawingSurface.h" +#include "DrawingContext.h" +#include "CairoDrawingSurface.h" +#include "CairoDrawingContext.h" +#include "TextElement.h" + +#include + + +std::unique_ptr CairoInterface::Create() +{ + return std::make_unique(); +} + +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(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(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(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()); +} diff --git a/src/graphics/cairo/CairoInterface.h b/src/graphics/cairo/CairoInterface.h new file mode 100644 index 0000000..96b8374 --- /dev/null +++ b/src/graphics/cairo/CairoInterface.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class DrawingSurface; +class DrawingContext; +class TextElement; + +class CairoInterface +{ +public: + CairoInterface() = default; + + static std::unique_ptr 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; diff --git a/src/graphics/OpenGlInterface.cpp b/src/graphics/opengl/OpenGlInterface.cpp similarity index 100% rename from src/graphics/OpenGlInterface.cpp rename to src/graphics/opengl/OpenGlInterface.cpp diff --git a/src/graphics/OpenGlInterface.h b/src/graphics/opengl/OpenGlInterface.h similarity index 100% rename from src/graphics/OpenGlInterface.h rename to src/graphics/opengl/OpenGlInterface.h diff --git a/src/ui_elements/CMakeLists.txt b/src/ui_elements/CMakeLists.txt index 3effec0..8c77056 100644 --- a/src/ui_elements/CMakeLists.txt +++ b/src/ui_elements/CMakeLists.txt @@ -1,6 +1,8 @@ list(APPEND ui_elements_LIB_INCLUDES desktop_elements/Keyboard.cpp + desktop_elements/IPlatformScreen.h desktop_elements/Screen.cpp + desktop_elements/IPlatformWindow.h desktop_elements/Window.cpp ui_events/KeyboardEvent.cpp ui_events/MouseEvent.cpp @@ -13,23 +15,21 @@ list(APPEND ui_elements_LIB_INCLUDES widgets/VerticalSpacer.cpp widgets/StackWidget.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}) target_include_directories(ui_elements PUBLIC "${PROJECT_SOURCE_DIR}/src/core/" "${PROJECT_SOURCE_DIR}/src/geometry/" + "${PROJECT_SOURCE_DIR}/src/visual_elements" "${CMAKE_CURRENT_SOURCE_DIR}/" "${CMAKE_CURRENT_SOURCE_DIR}/widgets" "${CMAKE_CURRENT_SOURCE_DIR}/widgets/elements" "${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) diff --git a/src/ui_elements/desktop_elements/IPlatformScreen.h b/src/ui_elements/desktop_elements/IPlatformScreen.h new file mode 100644 index 0000000..d42284e --- /dev/null +++ b/src/ui_elements/desktop_elements/IPlatformScreen.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +class IPlatformScreen +{ +public: + virtual ~IPlatformScreen() = default; +}; + +using IPlatformScreenPtr = std::unique_ptr; diff --git a/src/ui_elements/desktop_elements/IPlatformWindow.h b/src/ui_elements/desktop_elements/IPlatformWindow.h new file mode 100644 index 0000000..4b419da --- /dev/null +++ b/src/ui_elements/desktop_elements/IPlatformWindow.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +class IPlatformWindow +{ +public: + virtual ~IPlatformWindow() = default; +}; + +using IPlatformWindowPtr = std::unique_ptr; diff --git a/src/ui_elements/desktop_elements/Screen.cpp b/src/ui_elements/desktop_elements/Screen.cpp index 00411ba..7553c3c 100644 --- a/src/ui_elements/desktop_elements/Screen.cpp +++ b/src/ui_elements/desktop_elements/Screen.cpp @@ -1,5 +1,7 @@ #include "Screen.h" +#include "IPlatformScreen.h" + namespace mt{ Screen::Screen() { @@ -11,8 +13,22 @@ Screen::~Screen() } -std::shared_ptr Screen::Create() +std::unique_ptr Screen::Create() { - return std::make_shared(); + return std::make_unique(); +} + +IPlatformScreen* Screen::GetPlatformScreen() const +{ + if (mPlatformScreen) + { + return mPlatformScreen.get(); + } + return nullptr; +} + +void Screen::SetPlatformScreen(IPlatformScreenPtr screen) +{ + mPlatformScreen = std::move(screen); } } diff --git a/src/ui_elements/desktop_elements/Screen.h b/src/ui_elements/desktop_elements/Screen.h index 4af5ca8..c8ae55b 100644 --- a/src/ui_elements/desktop_elements/Screen.h +++ b/src/ui_elements/desktop_elements/Screen.h @@ -1,17 +1,29 @@ #pragma once #include + +class IPlatformScreen; +using IPlatformScreenPtr = std::unique_ptr; + namespace mt{ class Screen { public: - Screen(); + Screen(); - ~Screen(); + ~Screen(); - static std::shared_ptr Create(); + static std::unique_ptr Create(); + + IPlatformScreen* GetPlatformScreen() const; + + void SetPlatformScreen(IPlatformScreenPtr screen); + +private: + + IPlatformScreenPtr mPlatformScreen {nullptr}; }; } -using ScreenPtr = std::shared_ptr; +using ScreenPtr = std::unique_ptr; diff --git a/src/ui_elements/desktop_elements/Window.cpp b/src/ui_elements/desktop_elements/Window.cpp index 596f7b2..4a32aee 100644 --- a/src/ui_elements/desktop_elements/Window.cpp +++ b/src/ui_elements/desktop_elements/Window.cpp @@ -1,6 +1,14 @@ #include "Window.h" -namespace mt{ +#include "IPlatformWindow.h" +#include "PaintEvent.h" +#include "MouseEvent.h" +#include "VisualLayer.h" +#include "KeyboardEvent.h" + +namespace mt +{ + Window::Window() :mWidth(400), mHeight(300), @@ -21,7 +29,7 @@ std::unique_ptr Window::Create() std::vector Window::GetLayers() { - return mLayers; + return mWidget->GetLayers(); } void Window::OnMouseEvent(const MouseEvent* event) @@ -36,12 +44,8 @@ void Window::OnKeyboardEvent(const KeyboardEvent* event) void Window::OnPaint(const PaintEvent* event) { - mLayers.clear(); mWidget->SetBounds(mWidth, mHeight); mWidget->OnPaintEvent(event); - - auto layers = mWidget->GetLayers(); - mLayers.insert(mLayers.end(), layers.begin(), layers.end()); } void Window::AddWidget(WidgetUPtr widget) @@ -69,4 +73,19 @@ void Window::SetSize(unsigned width, unsigned height) mWidth = width; mHeight = height; } + +IPlatformWindow* Window::GetPlatformWindow() const +{ + if (mPlatformWindow) + { + return mPlatformWindow.get(); + } + return nullptr; +} + +void Window::SetPlatformWindow(IPlatformWindowPtr window) +{ + mPlatformWindow = std::move(window); +} + } diff --git a/src/ui_elements/desktop_elements/Window.h b/src/ui_elements/desktop_elements/Window.h index 0ed42ab..7f1cf49 100644 --- a/src/ui_elements/desktop_elements/Window.h +++ b/src/ui_elements/desktop_elements/Window.h @@ -1,13 +1,16 @@ #pragma once +#include "Widget.h" + #include #include -#include "PaintEvent.h" -#include "MouseEvent.h" -#include "KeyboardEvent.h" -#include "VisualLayer.h" -#include "Widget.h" +class PaintEvent; +class MouseEvent; +class KeyboardEvent; +class VisualLayer; +class IPlatformWindow; +using IPlatformWindowPtr = std::unique_ptr; namespace mt { @@ -15,13 +18,6 @@ namespace mt class Window { -private: - - WidgetUPtr mWidget; - unsigned mWidth; - unsigned mHeight; - std::vector mLayers; - public: Window(); @@ -47,6 +43,17 @@ public: void OnMouseEvent(const MouseEvent* 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}; }; } diff --git a/src/visual_elements/CMakeLists.txt b/src/visual_elements/CMakeLists.txt new file mode 100644 index 0000000..942296e --- /dev/null +++ b/src/visual_elements/CMakeLists.txt @@ -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 ) \ No newline at end of file diff --git a/src/ui_elements/widgets/elements/GeometryElement.cpp b/src/visual_elements/GeometryElement.cpp similarity index 100% rename from src/ui_elements/widgets/elements/GeometryElement.cpp rename to src/visual_elements/GeometryElement.cpp diff --git a/src/ui_elements/widgets/elements/GeometryElement.h b/src/visual_elements/GeometryElement.h similarity index 100% rename from src/ui_elements/widgets/elements/GeometryElement.h rename to src/visual_elements/GeometryElement.h diff --git a/src/ui_elements/widgets/elements/RectangleElement.cpp b/src/visual_elements/RectangleElement.cpp similarity index 100% rename from src/ui_elements/widgets/elements/RectangleElement.cpp rename to src/visual_elements/RectangleElement.cpp diff --git a/src/ui_elements/widgets/elements/RectangleElement.h b/src/visual_elements/RectangleElement.h similarity index 100% rename from src/ui_elements/widgets/elements/RectangleElement.h rename to src/visual_elements/RectangleElement.h diff --git a/src/ui_elements/widgets/elements/TextElement.cpp b/src/visual_elements/TextElement.cpp similarity index 100% rename from src/ui_elements/widgets/elements/TextElement.cpp rename to src/visual_elements/TextElement.cpp diff --git a/src/ui_elements/widgets/elements/TextElement.h b/src/visual_elements/TextElement.h similarity index 100% rename from src/ui_elements/widgets/elements/TextElement.h rename to src/visual_elements/TextElement.h diff --git a/src/ui_elements/widgets/elements/VisualLayer.cpp b/src/visual_elements/VisualLayer.cpp similarity index 100% rename from src/ui_elements/widgets/elements/VisualLayer.cpp rename to src/visual_elements/VisualLayer.cpp diff --git a/src/ui_elements/widgets/elements/VisualLayer.h b/src/visual_elements/VisualLayer.h similarity index 100% rename from src/ui_elements/widgets/elements/VisualLayer.h rename to src/visual_elements/VisualLayer.h diff --git a/src/windows/CMakeLists.txt b/src/windows/CMakeLists.txt index be9cba7..f1edbfc 100644 --- a/src/windows/CMakeLists.txt +++ b/src/windows/CMakeLists.txt @@ -1,5 +1,9 @@ list(APPEND linux_INCLUDES 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/XcbTextInterface.cpp ui_interfaces/x11/XcbKeyboard.cpp diff --git a/src/windows/managers/DesktopManager.cpp b/src/windows/managers/DesktopManager.cpp index 4aa9089..94c0828 100644 --- a/src/windows/managers/DesktopManager.cpp +++ b/src/windows/managers/DesktopManager.cpp @@ -1,7 +1,5 @@ #include "DesktopManager.h" -#include - DesktopManager::DesktopManager() : mScreens(), mWindowManager(WindowManager::Create()), @@ -69,7 +67,7 @@ void DesktopManager::OnUiEvent(UiEventUPtr eventUPtr) { auto mouseEvent = dynamic_cast(event); OnMouseEvent(mouseEvent); - if(mouseEvent->GetAction() == MouseEvent::Action::Pressed) + if (mouseEvent->GetAction() == MouseEvent::Action::Pressed) { mModified = true; } @@ -109,6 +107,20 @@ AbstractDesktopAppPtr DesktopManager::GetMainApp() 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) { mWindowManager = std::move(windowManager); diff --git a/src/windows/managers/DesktopManager.h b/src/windows/managers/DesktopManager.h index 960527a..ee27ca5 100644 --- a/src/windows/managers/DesktopManager.h +++ b/src/windows/managers/DesktopManager.h @@ -15,13 +15,6 @@ class DesktopManager { - std::vector mScreens; - WindowManagerUPtr mWindowManager; - KeyboardUPtr mKeyboard; - EventManagerUPtr mEventManager; - AbstractDesktopAppPtr mMainApplication; - bool mModified; - public: DesktopManager(); @@ -40,6 +33,10 @@ public: Keyboard* GetKeyboard() const; + void AddScreen(ScreenPtr screen); + + mt::Screen* GetDefaultScreen() const; + bool IsModified() const; void SetIsModified(bool modified); @@ -55,6 +52,14 @@ public: void OnPaintEvent(const PaintEvent* paintEvent); void ClearEvents(); + +private: + std::vector mScreens; + WindowManagerUPtr mWindowManager; + KeyboardUPtr mKeyboard; + EventManagerUPtr mEventManager; + AbstractDesktopAppPtr mMainApplication; + bool mModified; }; using DesktopManagerUPtr = std::unique_ptr; diff --git a/src/windows/managers/EventManager.cpp b/src/windows/managers/EventManager.cpp index afd2817..1ad1a33 100644 --- a/src/windows/managers/EventManager.cpp +++ b/src/windows/managers/EventManager.cpp @@ -1,6 +1,5 @@ #include "EventManager.h" - EventManager::EventManager() : mEvents() { diff --git a/src/windows/managers/EventManager.h b/src/windows/managers/EventManager.h index cd393de..7e9d0cc 100644 --- a/src/windows/managers/EventManager.h +++ b/src/windows/managers/EventManager.h @@ -1,7 +1,9 @@ #pragma once -#include + #include "UiEvent.h" +#include + class EventManager { std::vector mEvents; diff --git a/src/windows/ui_interfaces/x11/GlxInterface.cpp b/src/windows/ui_interfaces/x11/GlxInterface.cpp index ace80b3..f067a2c 100644 --- a/src/windows/ui_interfaces/x11/GlxInterface.cpp +++ b/src/windows/ui_interfaces/x11/GlxInterface.cpp @@ -1,113 +1,107 @@ #include "GlxInterface.h" -#include -#include + #include "OpenGlInterface.h" +#include "FileLogger.h" + +#include GlxInterface::GlxInterface() - : mContext(), - mDrawable(), - mWindow(), - mConfig() + : mContext(), + mDrawable(), + mWindow(), + mConfig() { } static int visual_attribs[] = { - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, True, - //GLX_SAMPLE_BUFFERS , 1, - //GLX_SAMPLES , 4, - None + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_DOUBLEBUFFER, True, + //GLX_SAMPLE_BUFFERS , 1, + //GLX_SAMPLES , 4, + None }; -std::shared_ptr GlxInterface::Create() +std::unique_ptr GlxInterface::Create() { - return std::make_shared(); + return std::make_unique(); } void GlxInterface::SetupContext(Display* display, int default_screen) { - int visualID = 0; + /* Query framebuffer configurations that match visual_attribs */ + GLXFBConfig* fb_configs = nullptr; + int num_fb_configs = 0; + fb_configs = glXChooseFBConfig(display, default_screen, visual_attribs, &num_fb_configs); + if (!fb_configs || num_fb_configs == 0) + { + MLOG_ERROR("glXGetFBConfigs failed"); + return; + } - /* Query framebuffer configurations that match visual_attribs */ - GLXFBConfig *fb_configs = 0; - int num_fb_configs = 0; - fb_configs = glXChooseFBConfig(display, default_screen, visual_attribs, &num_fb_configs); - if(!fb_configs || num_fb_configs == 0) - { - std::cerr << "glXGetFBConfigs failed" << std::endl; - return; - } + /* Select first framebuffer config and query visualID */ + int visualID = 0; + mConfig = fb_configs[0]; + glXGetFBConfigAttrib(display, mConfig, GLX_VISUAL_ID, &visualID); - /* Select first framebuffer config and query visualID */ - mConfig = fb_configs[0]; - glXGetFBConfigAttrib(display, mConfig, GLX_VISUAL_ID , &visualID); - - GLXContext context; - - /* Create OpenGL context */ - mContext = glXCreateNewContext(display, mConfig, GLX_RGBA_TYPE, 0, True); - if(!mContext) - { - std::cerr << "glXCreateNewContext failed" << std::endl; - return; - } + /* Create OpenGL context */ + mContext = glXCreateNewContext(display, mConfig, GLX_RGBA_TYPE, 0, True); + if (!mContext) + { + MLOG_ERROR("glXCreateNewContext failed"); + return; + } } void GlxInterface::SwapBuffers(Display* display) { - glXSwapBuffers(display, mDrawable); + glXSwapBuffers(display, mDrawable); } void GlxInterface::Draw() { - OpenGlInterface::draw(); + OpenGlInterface::draw(); } bool GlxInterface::SetupWindow(Display* display, xcb_window_t window) { - /* Create GLX Window */ - //GLXDrawable drawable = 0; + /* Create GLX Window */ + mWindow = glXCreateWindow(display, mConfig, window, 0); + if (!mWindow) + { + glXDestroyContext(display, mContext); + MLOG_ERROR("glXCreateWindow failed"); + return false; + } - mWindow = glXCreateWindow(display, mConfig, window, 0); + mDrawable = mWindow; - if(!mWindow) - { - //xcb_destroy_window(connection, window); - glXDestroyContext(display, mContext); - std::cerr << "glXCreateWindow failed" << std::endl; - return false; - } - - mDrawable = mWindow; - - /* make OpenGL context current */ - if(!glXMakeContextCurrent(display, mDrawable, mDrawable, mContext)) - { - // - glXDestroyContext(display, mContext); - std::cerr << "glXMakeContextCurrent failed" << std::endl; - return false; - } - return true; + /* make OpenGL context current */ + if (!glXMakeContextCurrent(display, mDrawable, mDrawable, mContext)) + { + glXDestroyContext(display, mContext); + MLOG_ERROR("glXMakeContextCurrent failed"); + return false; + } + return true; } void GlxInterface::DestroyWindow(Display* display) { - glXDestroyWindow(display, mWindow); + glXDestroyWindow(display, mWindow); } void GlxInterface::DestroyContext(Display* display) { - glXDestroyContext(display, mContext); + glXDestroyContext(display, mContext); } diff --git a/src/windows/ui_interfaces/x11/GlxInterface.h b/src/windows/ui_interfaces/x11/GlxInterface.h index 632298f..29b7406 100644 --- a/src/windows/ui_interfaces/x11/GlxInterface.h +++ b/src/windows/ui_interfaces/x11/GlxInterface.h @@ -5,28 +5,29 @@ class GlxInterface { - GLXContext mContext; - GLXDrawable mDrawable; - GLXWindow mWindow; - GLXFBConfig mConfig; - public: - GlxInterface(); + GlxInterface(); - void SetupContext(Display* display, int default_screen); + static std::unique_ptr Create(); - bool SetupWindow(Display* display, xcb_window_t window); + void SetupContext(Display* display, int default_screen); - void DestroyWindow(Display* display); + bool SetupWindow(Display* display, xcb_window_t window); - void DestroyContext(Display* display); + void DestroyWindow(Display* display); - void SwapBuffers(Display* display); + void DestroyContext(Display* display); - void Draw(); + void SwapBuffers(Display* display); - static std::shared_ptr Create(); + void Draw(); + +private: + GLXContext mContext; + GLXDrawable mDrawable; + GLXWindow mWindow; + GLXFBConfig mConfig; }; -using GlxInterfacePtr = std::shared_ptr; +using GlxInterfacePtr = std::unique_ptr; diff --git a/src/windows/ui_interfaces/x11/XcbEventInterface.cpp b/src/windows/ui_interfaces/x11/XcbEventInterface.cpp new file mode 100644 index 0000000..c7ae938 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbEventInterface.cpp @@ -0,0 +1,59 @@ +#include "XcbEventInterface.h" + +#include "KeyboardEvent.h" +#include "DiscretePoint.h" +#include "MouseEvent.h" +#include "PaintEvent.h" +#include "Keyboard.h" + +#include + +std::unique_ptr XcbEventInterface::Create() +{ + return std::make_unique(); +} + +std::unique_ptr 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 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 XcbEventInterface::ConvertButtonPress(xcb_button_press_event_t* event) const +{ + auto ui_event = MouseEvent::Create(); + auto x = static_cast(event->event_x); + auto y = static_cast(event->event_y); + ui_event->SetClientLocation(DiscretePoint(x, y)); + + auto screen_x = static_cast(event->root_x); + auto screen_y = static_cast(event->root_y); + ui_event->SetScreenLocation(DiscretePoint(x, y)); + ui_event->SetAction(MouseEvent::Action::Pressed); + return ui_event; +} + +std::unique_ptr XcbEventInterface::ConvertButtonRelease(xcb_button_press_event_t* event) const +{ + auto ui_event = MouseEvent::Create(); + auto x = static_cast(event->event_x); + auto y = static_cast(event->event_y); + ui_event->SetClientLocation(DiscretePoint(x, y)); + + auto screen_x = static_cast(event->root_x); + auto screen_y = static_cast(event->root_y); + ui_event->SetScreenLocation(DiscretePoint(x, y)); + + ui_event->SetAction(MouseEvent::Action::Released); + return ui_event; +} diff --git a/src/windows/ui_interfaces/x11/XcbEventInterface.h b/src/windows/ui_interfaces/x11/XcbEventInterface.h new file mode 100644 index 0000000..fe412e4 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbEventInterface.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +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 Create(); + + std::unique_ptr ConvertKeyPress(xcb_key_press_event_t* event, Keyboard* keyboard) const; + + std::unique_ptr ConvertKeyRelease(xcb_key_press_event_t* event, Keyboard* keyboard) const; + + std::unique_ptr ConvertButtonPress(xcb_button_press_event_t* event) const; + + std::unique_ptr ConvertButtonRelease(xcb_button_press_event_t* event) const; +}; + +using XcbEventInterfacePtr = std::unique_ptr; diff --git a/src/windows/ui_interfaces/x11/XcbInterface.cpp b/src/windows/ui_interfaces/x11/XcbInterface.cpp index 8e1133f..516a3ea 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.cpp +++ b/src/windows/ui_interfaces/x11/XcbInterface.cpp @@ -1,30 +1,32 @@ #include "XcbInterface.h" + #include "DesktopManager.h" -#include #include #include /* for XGetXCBConnection, link with libX11-xcb */ #include -#include "KeyboardEvent.h" -#include "MouseEvent.h" #include "PaintEvent.h" +#include "Screen.h" +#include "XcbScreen.h" #include "UiEvent.h" +#include "VisualLayer.h" #include "XcbKeyboard.h" +#include "XcbWindow.h" #include "XcbLayerInterface.h" +#include "XcbEventInterface.h" +#include "XcbWindowInterface.h" #include "GlxInterface.h" +#include "FileLogger.h" XcbInterface::XcbInterface() : mUseOpenGl(true), mConnection(nullptr), - mScreen(nullptr), - mWindows(), - mHandles(), - mDefaultWindow(-1), - mGraphicsContext(-1), mX11Display(), - mGlxInterface() + mGlxInterface(), + mXcbEventInterface(XcbEventInterface::Create()), + mXcbWindowInterface(XcbWindowInterface::Create()) { } @@ -39,13 +41,12 @@ void XcbInterface::SetUseOpenGl(bool use) mUseOpenGl = use; } -void XcbInterface::Initialize() +void XcbInterface::Initialize(DesktopManager* desktopManager) { Connect(); - UpdateScreen(); - CreateGraphicsContext(); - - if(mUseOpenGl) + UpdateScreen(desktopManager); + CreateGraphicsContext(desktopManager); + if (mUseOpenGl) { InitializeOpenGl(); } @@ -53,31 +54,21 @@ void XcbInterface::Initialize() void XcbInterface::Connect() { - if(mUseOpenGl) + if (mUseOpenGl) { - /* Open Xlib Display */ mX11Display = XOpenDisplay(0); - if(!mX11Display) + if (!mX11Display) { - std::cerr << "Can't open X11 display" << std::endl; + MLOG_ERROR("Can't open X11 display"); return; } - else - { - std::cout << "Got display" << std::endl; - } - - /* Get the XCB connection from the display */ mConnection = XGetXCBConnection(mX11Display); - if(!mConnection) + if (!mConnection) { XCloseDisplay(mX11Display); - std::cerr << "Can't get xcb connection from display" << std::endl; + MLOG_ERROR("Can't get xcb connection from display"); return; } - std::cout << "Got connection" << std::endl; - - /* Acquire event queue ownership */ XSetEventQueueOwner(mX11Display, XCBOwnsEventQueue); } else @@ -86,225 +77,130 @@ void XcbInterface::Connect() } } -void XcbInterface::UpdateScreen() +void XcbInterface::UpdateScreen(DesktopManager* desktopManager) { - if(!mConnection) return; - - auto screen_iter = xcb_setup_roots_iterator(xcb_get_setup(mConnection)); - if(mUseOpenGl) + if (!mConnection) { - if(!mX11Display) return; - int default_screen = DefaultScreen(mX11Display); - for(int screen_num = default_screen; - screen_iter.rem && screen_num > 0; + return; + } + auto screen_iter = xcb_setup_roots_iterator(xcb_get_setup(mConnection)); + 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)); } - 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() { mGlxInterface = GlxInterface::Create(); - int default_screen = DefaultScreen(mX11Display); + const auto default_screen = DefaultScreen(mX11Display); mGlxInterface->SetupContext(mX11Display, default_screen); } void XcbInterface::CreateOpenGlDrawable(mt::Window* window) { - if(!mUseOpenGl or !window) + if (!mUseOpenGl or !window or !window->GetPlatformWindow()) { return; } - auto hwnd = mHandles[window]; - bool result = mGlxInterface->SetupWindow(mX11Display, hwnd); - if(!result) + auto xcb_window = dynamic_cast(window->GetPlatformWindow()); + if (!xcb_window) { - 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; - mGraphicsContext = xcb_generate_id(mConnection); + if (!mConnection || desktopManager->GetDefaultScreen()) + { + return; + } + auto xcb_screen = dynamic_cast(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 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) { - if(!mConnection or !window) return; - xcb_map_window(mConnection, mHandles[window]); - xcb_flush(mConnection); + mXcbWindowInterface->Map(window, mConnection); } void XcbInterface::ShowWindow(mt::Window* window) { - MapWindow(window); + mXcbWindowInterface->Show(window, mConnection); } 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_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 hwnd = xcb_generate_id(mConnection); - - 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; + auto screen = desktopManager->GetDefaultScreen(); + mXcbWindowInterface->Add(window, mConnection, screen, GetEventMask()); } void XcbInterface::onPaint(DesktopManager* desktopManager) { desktopManager->OnUiEvent(PaintEvent::Create()); - PaintWindow(desktopManager->GetWindowManager()->GetMainWindow()); + auto mainWindow = desktopManager->GetWindowManager()->GetMainWindow(); + auto defaultScreen = desktopManager->GetDefaultScreen(); + auto xcb_screen = dynamic_cast(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; - - const auto hwnd = mHandles[window]; - for(const auto& layer : window->GetLayers()) + // Update the window + if (mUseOpenGl) { - XcbLayerInterface::AddLayer(mConnection, mScreen, - hwnd, mGraphicsContext, layer); + mGlxInterface->Draw(); + mGlxInterface->SwapBuffers(mX11Display); } -} - -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(event->event_x); - auto y = static_cast(event->event_y); - ui_event->SetClientLocation(DiscretePoint(x, y)); - - auto screen_x = static_cast(event->root_x); - auto screen_y = static_cast(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(event->event_x); - auto y = static_cast(event->event_y); - ui_event->SetClientLocation(DiscretePoint(x, y)); - - auto screen_x = static_cast(event->root_x); - auto screen_y = static_cast(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) + else { - /* 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->SwapBuffers(mX11Display); - std::cout << "end expose" << std::endl; - break; - default: - std::cout << "got something else" << std::endl; - break; - } - - free(event); + //auto window = mWindows[event->window]; + //window->SetSize(event->width, event->height); + onPaint(desktopManager); + xcb_flush(mConnection); } - mGlxInterface->DestroyWindow(mX11Display); - //xcb_destroy_window(mConnection, window); - 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); } void XcbInterface::Loop(DesktopManager* desktopManager) { - if(!mConnection) return; - - if(mUseOpenGl) + if (!mConnection) { - LoopOpenGl(desktopManager); return; } - xcb_generic_event_t *event; while ((event = xcb_wait_for_event(mConnection))) { @@ -312,58 +208,69 @@ void XcbInterface::Loop(DesktopManager* desktopManager) { case XCB_EXPOSE:{ auto expose_event = reinterpret_cast(event); - - // 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); + OnExposeEvent(expose_event, desktopManager); break; } case XCB_KEY_PRESS: { - auto kr = reinterpret_cast(event); - OnKeyPress(kr, desktopManager); + auto kp = reinterpret_cast(event); + auto ui_event = mXcbEventInterface->ConvertKeyPress(kp, desktopManager->GetKeyboard()); + desktopManager->OnUiEvent(std::move(ui_event)); break; } case XCB_KEY_RELEASE: { auto kr = reinterpret_cast(event); - OnKeyRelease(kr, desktopManager); + auto ui_event = mXcbEventInterface->ConvertKeyRelease(kr, desktopManager->GetKeyboard()); + desktopManager->OnUiEvent(std::move(ui_event)); break; } case XCB_BUTTON_PRESS: { auto press = reinterpret_cast(event); - OnButtonPress(press, desktopManager); + auto ui_event = mXcbEventInterface->ConvertButtonPress(press); + desktopManager->OnUiEvent(std::move(ui_event)); break; } case XCB_BUTTON_RELEASE: { auto release = reinterpret_cast(event); - OnButtonRelease(release, desktopManager); + auto ui_event = mXcbEventInterface->ConvertButtonRelease(release); + desktopManager->OnUiEvent(std::move(ui_event)); break; } default: /* Unknown event type, ignore it */ break; } - if(desktopManager->IsModified()) - { - desktopManager->SetIsModified(false); - ClearWindow(desktopManager->GetWindowManager()->GetMainWindow()); - } + onEventsDispatched(desktopManager); + free(event); + } + OnLoopCompleted(desktopManager); +} - free (event); +void XcbInterface::OnLoopCompleted(DesktopManager* desktopManagers) +{ + if (mUseOpenGl) + { + mGlxInterface->DestroyWindow(mX11Display); + mGlxInterface->DestroyContext(mX11Display); + } +} + +void XcbInterface::onEventsDispatched(DesktopManager* desktopManager) +{ + if (desktopManager->IsModified()) + { + desktopManager->SetIsModified(false); + auto mainWindow = desktopManager->GetWindowManager()->GetMainWindow(); + mXcbWindowInterface->Clear(mainWindow, mConnection); } } void XcbInterface::ShutDown() { - if(!mConnection) return; - std::cout << "starting shutdown" << std::endl; - xcb_disconnect(mConnection); - if(mUseOpenGl && mX11Display) + if (!mConnection) { - //XCloseDisplay(mX11Display); + return; } - std::cout << "ending shutdown" << std::endl; + MLOG_INFO("starting shutdown"); + xcb_disconnect(mConnection); + MLOG_INFO("Ending shutdown"); } diff --git a/src/windows/ui_interfaces/x11/XcbInterface.h b/src/windows/ui_interfaces/x11/XcbInterface.h index 7a13a77..bb2fab7 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.h +++ b/src/windows/ui_interfaces/x11/XcbInterface.h @@ -1,86 +1,70 @@ #pragma once +#include "Window.h" + #include #include -#include "Window.h" -#include "VisualLayer.h" - class DesktopManager; -using DesktopManagerPtr = std::shared_ptr; - class GlxInterface; -using GlxInterfacePtr = std::shared_ptr; +using GlxInterfacePtr = std::unique_ptr; + +class XcbEventInterface; +using XcbEventInterfacePtr = std::unique_ptr; + +class XcbWindowInterface; +using XcbWindowInterfacePtr = std::unique_ptr; -struct xcb_screen_t; struct xcb_connection_t; -struct xcb_key_press_event_t; -struct xcb_button_press_event_t; +struct xcb_expose_event_t; struct _XDisplay; class XcbInterface { - -private: - - bool mUseOpenGl; - std::map mWindows; - std::map mHandles; - unsigned mDefaultWindow; - xcb_connection_t* mConnection; - xcb_screen_t* mScreen; - unsigned mGraphicsContext; - _XDisplay* mX11Display; - GlxInterfacePtr mGlxInterface; - public: - XcbInterface(); ~XcbInterface(); void SetUseOpenGl(bool use); - void onPaint(DesktopManager* desktopManager); - void Initialize(); - - void InitializeOpenGl(); - - void CreateOpenGlDrawable(mt::Window* window); + void Initialize(DesktopManager* desktopManager); void Loop(DesktopManager* desktopManager); - void LoopOpenGl(DesktopManager* desktopManager); - void ShutDown(); - void AddWindow(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: + void onPaint(DesktopManager* desktopManager); + + void InitializeOpenGl(); void Connect(); - void UpdateScreen(); + void UpdateScreen(DesktopManager* desktopManager); + + void OnExposeEvent(xcb_expose_event_t* event, DesktopManager* desktopManager); 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 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}; }; diff --git a/src/windows/ui_interfaces/x11/XcbScreen.cpp b/src/windows/ui_interfaces/x11/XcbScreen.cpp new file mode 100644 index 0000000..162e30c --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbScreen.cpp @@ -0,0 +1,29 @@ +#include "XcbScreen.h" + +#include + +XcbScreen::XcbScreen(xcb_screen_t* screen) + : mNativeScreen(screen) +{ + +} + +std::unique_ptr XcbScreen::Create(xcb_screen_t* screen) +{ + return std::make_unique(screen); +} + +xcb_screen_t* XcbScreen::GetNativeScreen() const +{ + return mNativeScreen; +} + +void XcbScreen::SetGraphicsContext(unsigned gc) +{ + mGraphicsContext = gc; +} + +unsigned XcbScreen::GetGraphicsContext() const +{ + return mGraphicsContext; +} diff --git a/src/windows/ui_interfaces/x11/XcbScreen.h b/src/windows/ui_interfaces/x11/XcbScreen.h new file mode 100644 index 0000000..1e04d36 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbScreen.h @@ -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 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; diff --git a/src/windows/ui_interfaces/x11/XcbWindow.cpp b/src/windows/ui_interfaces/x11/XcbWindow.cpp new file mode 100644 index 0000000..4fb6230 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbWindow.cpp @@ -0,0 +1,22 @@ +#include "XcbWindow.h" + +XcbWindow::XcbWindow(int hwnd) + : mHandle(hwnd) +{ + +} + +std::unique_ptr XcbWindow::Create(int hwnd) +{ + return std::make_unique(hwnd); +} + +int XcbWindow::GetHandle() const +{ + return mHandle; +} + +unsigned XcbWindow::GetGraphicsContext() const +{ + return mGraphicsContext; +} diff --git a/src/windows/ui_interfaces/x11/XcbWindow.h b/src/windows/ui_interfaces/x11/XcbWindow.h new file mode 100644 index 0000000..0df187a --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbWindow.h @@ -0,0 +1,22 @@ +#pragma once + +#include "IPlatformWindow.h" + +class XcbWindow : public IPlatformWindow +{ +public: + XcbWindow(int hwnd); + virtual ~XcbWindow() = default; + + static std::unique_ptr Create(int hwnd); + + int GetHandle() const; + unsigned GetGraphicsContext() const; + +private: + int mHandle{-1}; + unsigned mGraphicsContext {0}; +}; + +using XcbWindowPtr = std::unique_ptr; + diff --git a/src/windows/ui_interfaces/x11/XcbWindowInterface.cpp b/src/windows/ui_interfaces/x11/XcbWindowInterface.cpp new file mode 100644 index 0000000..00cd0c5 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbWindowInterface.cpp @@ -0,0 +1,80 @@ +#include "XcbWindowInterface.h" + +#include "Window.h" +#include "XcbWindow.h" +#include "Screen.h" +#include "XcbScreen.h" +#include "XcbLayerInterface.h" + +#include + +std::unique_ptr XcbWindowInterface::Create() +{ + return std::make_unique(); +} + +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(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(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(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(window->GetPlatformWindow()); + xcb_map_window(connection, xcb_window->GetHandle()); + xcb_flush(connection); +} diff --git a/src/windows/ui_interfaces/x11/XcbWindowInterface.h b/src/windows/ui_interfaces/x11/XcbWindowInterface.h new file mode 100644 index 0000000..cfa71f5 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbWindowInterface.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +namespace mt +{ +class Window; +class Screen; +} +struct xcb_connection_t; +struct xcb_screen_t; + +class XcbWindowInterface +{ +public: + + static std::unique_ptr 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;