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

@ -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

View file

@ -1,7 +1,5 @@
#include "DesktopManager.h"
#include <iostream>
DesktopManager::DesktopManager()
: mScreens(),
mWindowManager(WindowManager::Create()),
@ -69,7 +67,7 @@ void DesktopManager::OnUiEvent(UiEventUPtr eventUPtr)
{
auto mouseEvent = dynamic_cast<const MouseEvent*>(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);

View file

@ -15,13 +15,6 @@
class DesktopManager
{
std::vector<ScreenPtr> 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<ScreenPtr> mScreens;
WindowManagerUPtr mWindowManager;
KeyboardUPtr mKeyboard;
EventManagerUPtr mEventManager;
AbstractDesktopAppPtr mMainApplication;
bool mModified;
};
using DesktopManagerUPtr = std::unique_ptr<DesktopManager>;

View file

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

View file

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

View file

@ -1,113 +1,107 @@
#include "GlxInterface.h"
#include <GL/gl.h>
#include <iostream>
#include "OpenGlInterface.h"
#include "FileLogger.h"
#include <GL/gl.h>
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> 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)
{
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);
}

View file

@ -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<GlxInterface> 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<GlxInterface> Create();
void Draw();
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 "DesktopManager.h"
#include <iostream>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */
#include <xcb/xcb.h>
#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<XcbWindow*>(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<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 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<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;
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<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)
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<xcb_expose_event_t*>(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<xcb_key_press_event_t*>(event);
OnKeyPress(kr, desktopManager);
auto kp = reinterpret_cast<xcb_key_press_event_t*>(event);
auto ui_event = mXcbEventInterface->ConvertKeyPress(kp, desktopManager->GetKeyboard());
desktopManager->OnUiEvent(std::move(ui_event));
break;
}
case XCB_KEY_RELEASE: {
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;
}
case XCB_BUTTON_PRESS: {
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;
}
case XCB_BUTTON_RELEASE: {
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;
}
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");
}

View file

@ -1,86 +1,70 @@
#pragma once
#include "Window.h"
#include <memory>
#include <map>
#include "Window.h"
#include "VisualLayer.h"
class DesktopManager;
using DesktopManagerPtr = std::shared_ptr<DesktopManager>;
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_key_press_event_t;
struct xcb_button_press_event_t;
struct xcb_expose_event_t;
struct _XDisplay;
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:
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};
};

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>;