238 lines
6.5 KiB
C++
238 lines
6.5 KiB
C++
#include "XcbInterface.h"
|
|
|
|
#include "DesktopManager.h"
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xlib-xcb.h> /* for XGetXCBConnection, link with libX11-xcb */
|
|
#include <xcb/xcb.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 "XcbGlInterface.h"
|
|
#include "FileLogger.h"
|
|
|
|
|
|
XcbInterface::XcbInterface(DesktopManager* desktopManager, bool useHardware)
|
|
: AbstractUIInterface(desktopManager, useHardware),
|
|
mEventInterface(XcbEventInterface::Create())
|
|
{
|
|
|
|
}
|
|
|
|
XcbInterface::~XcbInterface()
|
|
{
|
|
shutDown();
|
|
}
|
|
|
|
void XcbInterface::initialize()
|
|
{
|
|
connect();
|
|
updateScreen();
|
|
createGraphicsContext();
|
|
if (mUseHardwareRendering)
|
|
{
|
|
initializeHardwareRendering();
|
|
}
|
|
mDesktopManager->setKeyboard(XcbKeyboard::Create());
|
|
|
|
const auto num_windows = mDesktopManager->getWindowManager()->getNumWindows();
|
|
for(std::size_t idx=0; idx< num_windows; idx++)
|
|
{
|
|
addWindow(mDesktopManager->getWindowManager()->getWindow(idx));
|
|
}
|
|
|
|
mDesktopManager->getWindowManager()->getMainWindow()->show();
|
|
}
|
|
|
|
void XcbInterface::connect()
|
|
{
|
|
if (mUseHardwareRendering)
|
|
{
|
|
mX11Display = XOpenDisplay(0);
|
|
if (!mX11Display)
|
|
{
|
|
MLOG_ERROR("Can't open X11 display");
|
|
return;
|
|
}
|
|
mConnection = XGetXCBConnection(mX11Display);
|
|
if (!mConnection)
|
|
{
|
|
XCloseDisplay(mX11Display);
|
|
MLOG_ERROR("Can't get xcb connection from display");
|
|
return;
|
|
}
|
|
XSetEventQueueOwner(mX11Display, XCBOwnsEventQueue);
|
|
}
|
|
else
|
|
{
|
|
mConnection = xcb_connect(nullptr, nullptr);
|
|
}
|
|
}
|
|
|
|
void XcbInterface::updateScreen()
|
|
{
|
|
if (!mConnection)
|
|
{
|
|
return;
|
|
}
|
|
auto screen_iter = xcb_setup_roots_iterator(xcb_get_setup(mConnection));
|
|
if (mUseHardwareRendering)
|
|
{
|
|
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));
|
|
}
|
|
auto xcb_screen = XcbScreen::Create(screen_iter.data);
|
|
auto screen = mt::Screen::Create();
|
|
screen->SetPlatformScreen(std::move(xcb_screen));
|
|
mDesktopManager->addScreen(std::move(screen));
|
|
}
|
|
|
|
void XcbInterface::initializeHardwareRendering()
|
|
{
|
|
const auto default_screen = DefaultScreen(mX11Display);
|
|
mGlInterface = XcbGlInterface::Create(mX11Display, default_screen);
|
|
}
|
|
|
|
void XcbInterface::createGraphicsContext()
|
|
{
|
|
if (!mConnection || mDesktopManager->getDefaultScreen())
|
|
{
|
|
return;
|
|
}
|
|
auto xcb_screen = dynamic_cast<XcbScreen*>(mDesktopManager->getDefaultScreen()->GetPlatformScreen());
|
|
if (!xcb_screen)
|
|
{
|
|
return;
|
|
}
|
|
|
|
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, gc, window, mask, values);
|
|
xcb_screen->SetGraphicsContext(gc);
|
|
}
|
|
|
|
void XcbInterface::mapWindow(mt::Window* window)
|
|
{
|
|
window->map();
|
|
}
|
|
|
|
void XcbInterface::showWindow(mt::Window* window)
|
|
{
|
|
window->show();
|
|
}
|
|
|
|
uint32_t XcbInterface::getEventMask()
|
|
{
|
|
return XCB_EVENT_MASK_KEY_RELEASE |
|
|
XCB_EVENT_MASK_BUTTON_PRESS |
|
|
XCB_EVENT_MASK_BUTTON_RELEASE |
|
|
XCB_EVENT_MASK_EXPOSURE;
|
|
}
|
|
|
|
void XcbInterface::addWindow(mt::Window* window)
|
|
{
|
|
auto screen = mDesktopManager->getDefaultScreen();
|
|
XcbWindow::add(window, mConnection, screen, getEventMask(), mGlInterface.get());
|
|
}
|
|
|
|
void XcbInterface::onPaint()
|
|
{
|
|
mDesktopManager->onUiEvent(PaintEvent::Create());
|
|
|
|
auto mainWindow = mDesktopManager->getWindowManager()->getMainWindow();
|
|
auto defaultScreen = mDesktopManager->getDefaultScreen();
|
|
|
|
mainWindow->doPaint(defaultScreen);
|
|
}
|
|
|
|
void XcbInterface::onExposeEvent(xcb_expose_event_t* event)
|
|
{
|
|
//auto window = mWindows[event->window];
|
|
//window->SetSize(event->width, event->height);
|
|
|
|
onPaint();
|
|
}
|
|
|
|
void XcbInterface::loop()
|
|
{
|
|
initialize();
|
|
|
|
xcb_generic_event_t *event;
|
|
while ((event = xcb_wait_for_event(mConnection)))
|
|
{
|
|
switch (event->response_type & ~0x80)
|
|
{
|
|
case XCB_EXPOSE:{
|
|
auto expose_event = reinterpret_cast<xcb_expose_event_t*>(event);
|
|
onExposeEvent(expose_event);
|
|
break;
|
|
}
|
|
case XCB_KEY_PRESS: {
|
|
auto kp = reinterpret_cast<xcb_key_press_event_t*>(event);
|
|
auto ui_event = mEventInterface->ConvertKeyPress(kp, mDesktopManager->getKeyboard());
|
|
mDesktopManager->onUiEvent(std::move(ui_event));
|
|
break;
|
|
}
|
|
case XCB_KEY_RELEASE: {
|
|
auto kr = reinterpret_cast<xcb_key_release_event_t*>(event);
|
|
auto ui_event = mEventInterface->ConvertKeyRelease(kr, mDesktopManager->getKeyboard());
|
|
mDesktopManager->onUiEvent(std::move(ui_event));
|
|
break;
|
|
}
|
|
case XCB_BUTTON_PRESS: {
|
|
auto press = reinterpret_cast<xcb_button_press_event_t*>(event);
|
|
auto ui_event = mEventInterface->ConvertButtonPress(press);
|
|
mDesktopManager->onUiEvent(std::move(ui_event));
|
|
break;
|
|
}
|
|
case XCB_BUTTON_RELEASE: {
|
|
auto release = reinterpret_cast<xcb_button_release_event_t*>(event);
|
|
auto ui_event = mEventInterface->ConvertButtonRelease(release);
|
|
mDesktopManager->onUiEvent(std::move(ui_event));
|
|
break;
|
|
}
|
|
default:
|
|
/* Unknown event type, ignore it */
|
|
break;
|
|
}
|
|
onEventsDispatched();
|
|
free(event);
|
|
}
|
|
}
|
|
|
|
void XcbInterface::onEventsDispatched()
|
|
{
|
|
if (mDesktopManager->isModified())
|
|
{
|
|
mDesktopManager->setIsModified(false);
|
|
auto mainWindow = mDesktopManager->getWindowManager()->getMainWindow();
|
|
mainWindow->clear();
|
|
}
|
|
}
|
|
|
|
void XcbInterface::shutDown()
|
|
{
|
|
mDesktopManager->getWindowManager()->clearPlatformWindows();
|
|
|
|
if (!mConnection)
|
|
{
|
|
return;
|
|
}
|
|
MLOG_INFO("starting shutdown");
|
|
xcb_disconnect(mConnection);
|
|
MLOG_INFO("Ending shutdown");
|
|
}
|