mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-21 16:20:53 +00:00
Implement mouse events and display on Linux/Skia port
This commit is contained in:
parent
706b9a84c6
commit
5e11bebaf0
@ -212,6 +212,7 @@ if(USE_SKIA_BACKEND)
|
||||
skia/skia_window_x11.cpp
|
||||
x11/event_queue.cpp
|
||||
x11/keys.cpp
|
||||
x11/window.cpp
|
||||
x11/x11.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -151,12 +151,7 @@ bool SkiaDisplay::setNativeMouseCursor(const she::Surface* surface,
|
||||
const gfx::Point& focus,
|
||||
const int scale)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
return m_window.setNativeMouseCursor(surface, focus, scale);
|
||||
#else
|
||||
// TODO impl this for Linux
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkiaDisplay::setMousePosition(const gfx::Point& position)
|
||||
|
@ -70,10 +70,8 @@ public:
|
||||
return Capabilities(
|
||||
int(Capabilities::MultipleDisplays) |
|
||||
int(Capabilities::CanResizeDisplay) |
|
||||
int(Capabilities::DisplayScale)
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
| int(Capabilities::CustomNativeMouseCursor)
|
||||
#endif
|
||||
int(Capabilities::DisplayScale) |
|
||||
int(Capabilities::CustomNativeMouseCursor)
|
||||
// TODO enable this when the GPU support is ready
|
||||
#if 0 // SK_SUPPORT_GPU
|
||||
| int(Capabilities::GpuAccelerationSwitch)
|
||||
|
@ -14,17 +14,46 @@
|
||||
#include "she/event.h"
|
||||
#include "she/event_queue.h"
|
||||
#include "she/skia/skia_display.h"
|
||||
#include "she/skia/skia_surface.h"
|
||||
#include "she/x11/x11.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
|
||||
namespace she {
|
||||
|
||||
namespace {
|
||||
|
||||
bool convert_skia_bitmap_to_ximage(const SkBitmap& bitmap, XImage& image)
|
||||
{
|
||||
bitmap.lockPixels();
|
||||
|
||||
memset(&image, 0, sizeof(image));
|
||||
int bpp = 8*bitmap.bytesPerPixel();
|
||||
image.width = bitmap.width();
|
||||
image.height = bitmap.height();
|
||||
image.format = ZPixmap;
|
||||
image.data = (char*)bitmap.getPixels();
|
||||
image.byte_order = LSBFirst;
|
||||
image.bitmap_unit = bpp;
|
||||
image.bitmap_bit_order = LSBFirst;
|
||||
image.bitmap_pad = bpp;
|
||||
image.depth = 24;
|
||||
image.bytes_per_line = bitmap.rowBytes() - 4*bitmap.width();
|
||||
image.bits_per_pixel = bpp;
|
||||
|
||||
bool result = XInitImage(&image);
|
||||
bitmap.unlockPixels();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
SkiaWindow::SkiaWindow(EventQueue* queue, SkiaDisplay* display,
|
||||
int width, int height, int scale)
|
||||
: X11Window(X11::instance()->display(), width, height)
|
||||
: X11Window(X11::instance()->display(), width, height, scale)
|
||||
, m_queue(queue)
|
||||
, m_display(display)
|
||||
, m_clientSize(width, height)
|
||||
, m_scale(scale)
|
||||
{
|
||||
}
|
||||
|
||||
@ -32,22 +61,6 @@ SkiaWindow::~SkiaWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void SkiaWindow::queueEventImpl(Event& ev)
|
||||
{
|
||||
ev.setDisplay(m_display);
|
||||
m_queue->queueEvent(ev);
|
||||
}
|
||||
|
||||
int SkiaWindow::scale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
void SkiaWindow::setScale(int scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
}
|
||||
|
||||
void SkiaWindow::setVisible(bool visible)
|
||||
{
|
||||
}
|
||||
@ -66,39 +79,59 @@ bool SkiaWindow::isMinimized() const
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::Size SkiaWindow::clientSize() const
|
||||
void SkiaWindow::queueEvent(Event& ev)
|
||||
{
|
||||
return m_clientSize;
|
||||
ev.setDisplay(m_display);
|
||||
m_queue->queueEvent(ev);
|
||||
}
|
||||
|
||||
gfx::Size SkiaWindow::restoredSize() const
|
||||
void SkiaWindow::paintGC(const gfx::Rect& rc)
|
||||
{
|
||||
return m_clientSize;
|
||||
SkiaSurface* surface = static_cast<SkiaSurface*>(m_display->getSurface());
|
||||
const SkBitmap& bitmap = surface->bitmap();
|
||||
|
||||
int scale = this->scale();
|
||||
if (scale == 1) {
|
||||
XImage image;
|
||||
if (convert_skia_bitmap_to_ximage(bitmap, image)) {
|
||||
XPutImage(
|
||||
x11display(), handle(), gc(), &image,
|
||||
rc.x, rc.y,
|
||||
rc.x, rc.y,
|
||||
rc.w, rc.h);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SkBitmap scaled;
|
||||
if (scaled.tryAllocPixels(
|
||||
SkImageInfo::Make(rc.w, rc.h,
|
||||
bitmap.info().colorType(),
|
||||
bitmap.info().alphaType()))) {
|
||||
SkPaint paint;
|
||||
paint.setBlendMode(SkBlendMode::kSrc);
|
||||
|
||||
SkCanvas canvas(scaled);
|
||||
SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(rc.x/scale, rc.y/scale, rc.w/scale, rc.h/scale));
|
||||
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, rc.w, rc.h));
|
||||
canvas.drawBitmapRect(bitmap, srcRect, dstRect, &paint,
|
||||
SkCanvas::kStrict_SrcRectConstraint);
|
||||
|
||||
XImage image;
|
||||
if (convert_skia_bitmap_to_ximage(scaled, image)) {
|
||||
XPutImage(
|
||||
x11display(), handle(), gc(), &image,
|
||||
0, 0,
|
||||
rc.x, rc.y,
|
||||
rc.w, rc.h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkiaWindow::captureMouse()
|
||||
{
|
||||
}
|
||||
|
||||
void SkiaWindow::releaseMouse()
|
||||
{
|
||||
}
|
||||
|
||||
void SkiaWindow::setMousePosition(const gfx::Point& position)
|
||||
{
|
||||
}
|
||||
|
||||
bool SkiaWindow::setNativeMouseCursor(NativeCursor cursor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SkiaWindow::updateWindow(const gfx::Rect& bounds)
|
||||
{
|
||||
}
|
||||
|
||||
void SkiaWindow::onExpose()
|
||||
void SkiaWindow::resizeDisplay(const gfx::Size& sz)
|
||||
{
|
||||
m_display->resize(sz);
|
||||
updateWindow(gfx::Rect(sz / scale()));
|
||||
}
|
||||
|
||||
} // namespace she
|
||||
|
@ -20,7 +20,7 @@ namespace she {
|
||||
class EventQueue;
|
||||
class SkiaDisplay;
|
||||
|
||||
class SkiaWindow : public X11Window<SkiaWindow> {
|
||||
class SkiaWindow : public X11Window {
|
||||
public:
|
||||
enum class Backend { NONE, GL };
|
||||
|
||||
@ -28,21 +28,11 @@ public:
|
||||
int width, int height, int scale);
|
||||
~SkiaWindow();
|
||||
|
||||
void queueEventImpl(Event& ev);
|
||||
|
||||
int scale() const;
|
||||
void setScale(int scale);
|
||||
void setVisible(bool visible);
|
||||
void maximize();
|
||||
bool isMaximized() const;
|
||||
bool isMinimized() const;
|
||||
gfx::Size clientSize() const;
|
||||
gfx::Size restoredSize() const;
|
||||
void captureMouse();
|
||||
void releaseMouse();
|
||||
void setMousePosition(const gfx::Point& position);
|
||||
bool setNativeMouseCursor(NativeCursor cursor);
|
||||
void updateWindow(const gfx::Rect& bounds);
|
||||
|
||||
std::string getLayout() { return ""; }
|
||||
void setLayout(const std::string& layout) { }
|
||||
|
||||
@ -51,12 +41,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void onExpose() override;
|
||||
void queueEvent(Event& ev) override;
|
||||
void paintGC(const gfx::Rect& rc) override;
|
||||
void resizeDisplay(const gfx::Size& sz) override;
|
||||
|
||||
EventQueue* m_queue;
|
||||
SkiaDisplay* m_display;
|
||||
gfx::Size m_clientSize;
|
||||
int m_scale;
|
||||
|
||||
DISABLE_COPYING(SkiaWindow);
|
||||
};
|
||||
|
@ -10,10 +10,57 @@
|
||||
|
||||
#include "she/x11/event_queue.h"
|
||||
|
||||
#include "she/x11/window.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
namespace she {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* get_event_name(XEvent& event)
|
||||
{
|
||||
switch (event.type) {
|
||||
case KeyPress: return "KeyPress";
|
||||
case KeyRelease: return "KeyRelease";
|
||||
case ButtonPress: return "ButtonPress";
|
||||
case ButtonRelease: return "ButtonRelease";
|
||||
case MotionNotify: return "MotionNotify";
|
||||
case EnterNotify: return "EnterNotify";
|
||||
case LeaveNotify: return "LeaveNotify";
|
||||
case FocusIn: return "FocusIn";
|
||||
case FocusOut: return "FocusOut";
|
||||
case KeymapNotify: return "KeymapNotify";
|
||||
case Expose: return "Expose";
|
||||
case GraphicsExpose: return "GraphicsExpose";
|
||||
case NoExpose: return "NoExpose";
|
||||
case VisibilityNotify: return "VisibilityNotify";
|
||||
case CreateNotify: return "CreateNotify";
|
||||
case DestroyNotify: return "DestroyNotify";
|
||||
case UnmapNotify: return "UnmapNotify";
|
||||
case MapNotify: return "MapNotify";
|
||||
case MapRequest: return "MapRequest";
|
||||
case ReparentNotify: return "ReparentNotify";
|
||||
case ConfigureNotify: return "ConfigureNotify";
|
||||
case ConfigureRequest: return "ConfigureRequest";
|
||||
case GravityNotify: return "GravityNotify";
|
||||
case ResizeRequest: return "ResizeRequest";
|
||||
case CirculateNotify: return "CirculateNotify";
|
||||
case CirculateRequest: return "CirculateRequest";
|
||||
case PropertyNotify: return "PropertyNotify";
|
||||
case SelectionClear: return "SelectionClear";
|
||||
case SelectionRequest: return "SelectionRequest";
|
||||
case SelectionNotify: return "SelectionNotify";
|
||||
case ColormapNotify: return "ColormapNotify";
|
||||
case ClientMessage: return "ClientMessage";
|
||||
case MappingNotify: return "MappingNotify";
|
||||
case GenericEvent: return "GenericEvent";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void X11EventQueue::getEvent(Event& ev, bool canWait)
|
||||
{
|
||||
::Display* display = X11::instance()->display();
|
||||
@ -40,7 +87,12 @@ void X11EventQueue::getEvent(Event& ev, bool canWait)
|
||||
|
||||
void X11EventQueue::processX11Event(XEvent& event)
|
||||
{
|
||||
// TODO
|
||||
TRACE("XEvent: %s (%d)\n", get_event_name(event), event.type);
|
||||
|
||||
X11Window* window = X11Window::getPointerFromHandle(event.xany.window);
|
||||
ASSERT(window);
|
||||
if (window)
|
||||
window->processX11Event(event);
|
||||
}
|
||||
|
||||
} // namespace she
|
||||
|
229
src/she/x11/window.cpp
Normal file
229
src/she/x11/window.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "she/x11/window.h"
|
||||
|
||||
#include "gfx/rect.h"
|
||||
#include "she/event.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace she {
|
||||
|
||||
namespace {
|
||||
|
||||
// See https://bugs.freedesktop.org/show_bug.cgi?id=12871 for more
|
||||
// information, it looks like the official way to convert a X Window
|
||||
// into our own user data pointer (X11Window instance) is using a map.
|
||||
std::map<::Window, X11Window*> g_activeWindows;
|
||||
|
||||
KeyModifiers get_modifiers_from_xevent(int state)
|
||||
{
|
||||
int modifiers = kKeyNoneModifier;
|
||||
if (state & ShiftMask) modifiers |= kKeyShiftModifier;
|
||||
if (state & LockMask) modifiers |= kKeyAltModifier;
|
||||
if (state & ControlMask) modifiers |= kKeyCtrlModifier;
|
||||
return (KeyModifiers)modifiers;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// static
|
||||
X11Window* X11Window::getPointerFromHandle(Window handle)
|
||||
{
|
||||
auto it = g_activeWindows.find(handle);
|
||||
if (it != g_activeWindows.end())
|
||||
return it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
void X11Window::addWindow(X11Window* window)
|
||||
{
|
||||
ASSERT(g_activeWindows.find(window->handle()) == g_activeWindows.end());
|
||||
g_activeWindows[window->handle()] = window;
|
||||
}
|
||||
|
||||
// static
|
||||
void X11Window::removeWindow(X11Window* window)
|
||||
{
|
||||
auto it = g_activeWindows.find(window->handle());
|
||||
ASSERT(it != g_activeWindows.end());
|
||||
if (it != g_activeWindows.end()) {
|
||||
ASSERT(it->second == window);
|
||||
g_activeWindows.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
X11Window::X11Window(::Display* display, int width, int height, int scale)
|
||||
: m_display(display)
|
||||
, m_scale(scale)
|
||||
, m_clientSize(1, 1)
|
||||
{
|
||||
::Window root = XDefaultRootWindow(m_display);
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.event_mask = (StructureNotifyMask | ExposureMask | PropertyChangeMask |
|
||||
EnterWindowMask | LeaveWindowMask | FocusChangeMask |
|
||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
||||
KeyPressMask | KeyReleaseMask);
|
||||
|
||||
m_window = XCreateWindow(
|
||||
m_display, root,
|
||||
0, 0, width, height, 0,
|
||||
CopyFromParent,
|
||||
InputOutput,
|
||||
CopyFromParent,
|
||||
CWEventMask,
|
||||
&swa);
|
||||
|
||||
XMapWindow(m_display, m_window);
|
||||
|
||||
m_gc = XCreateGC(m_display, m_window, 0, nullptr);
|
||||
|
||||
X11Window::addWindow(this);
|
||||
}
|
||||
|
||||
X11Window::~X11Window()
|
||||
{
|
||||
XFreeGC(m_display, m_gc);
|
||||
XDestroyWindow(m_display, m_window);
|
||||
|
||||
X11Window::removeWindow(this);
|
||||
}
|
||||
|
||||
void X11Window::setScale(const int scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
resizeDisplay(m_clientSize);
|
||||
}
|
||||
|
||||
void X11Window::setTitle(const std::string& title)
|
||||
{
|
||||
XTextProperty prop;
|
||||
prop.value = (unsigned char*)title.c_str();
|
||||
prop.encoding = XA_STRING;
|
||||
prop.format = 8;
|
||||
prop.nitems = std::strlen((char*)title.c_str());
|
||||
XSetWMName(m_display, m_window, &prop);
|
||||
}
|
||||
|
||||
void X11Window::captureMouse()
|
||||
{
|
||||
}
|
||||
|
||||
void X11Window::releaseMouse()
|
||||
{
|
||||
}
|
||||
|
||||
void X11Window::setMousePosition(const gfx::Point& position)
|
||||
{
|
||||
}
|
||||
|
||||
void X11Window::updateWindow(const gfx::Rect& unscaledBounds)
|
||||
{
|
||||
XEvent ev;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.xexpose.type = Expose;
|
||||
ev.xexpose.display = x11display();
|
||||
ev.xexpose.window = handle();
|
||||
ev.xexpose.x = unscaledBounds.x*m_scale;
|
||||
ev.xexpose.y = unscaledBounds.y*m_scale;
|
||||
ev.xexpose.width = unscaledBounds.w*m_scale;
|
||||
ev.xexpose.height = unscaledBounds.h*m_scale;
|
||||
XSendEvent(m_display, m_window, False,
|
||||
ExposureMask, (XEvent*)&ev);
|
||||
}
|
||||
|
||||
bool X11Window::setNativeMouseCursor(NativeCursor cursor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X11Window::setNativeMouseCursor(const she::Surface* surface,
|
||||
const gfx::Point& focus,
|
||||
const int scale)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void X11Window::processX11Event(XEvent& event)
|
||||
{
|
||||
switch (event.type) {
|
||||
|
||||
case ConfigureNotify: {
|
||||
gfx::Size newSize(event.xconfigure.width,
|
||||
event.xconfigure.height);
|
||||
|
||||
if (newSize.w > 0 &&
|
||||
newSize.h > 0 &&
|
||||
m_clientSize != newSize) {
|
||||
m_clientSize = newSize;
|
||||
resizeDisplay(m_clientSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Expose: {
|
||||
gfx::Rect rc(event.xexpose.x, event.xexpose.y,
|
||||
event.xexpose.width, event.xexpose.height);
|
||||
paintGC(rc);
|
||||
break;
|
||||
}
|
||||
|
||||
case ButtonPress: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseDown);
|
||||
ev.setModifiers(get_modifiers_from_xevent(event.xbutton.state));
|
||||
ev.setPosition(gfx::Point(event.xbutton.x / m_scale,
|
||||
event.xbutton.y / m_scale));
|
||||
ev.setButton(
|
||||
event.xbutton.button == 1 ? Event::LeftButton:
|
||||
event.xbutton.button == 2 ? Event::MiddleButton:
|
||||
event.xbutton.button == 3 ? Event::RightButton:
|
||||
event.xbutton.button == 4 ? Event::X1Button:
|
||||
event.xbutton.button == 5 ? Event::X2Button: Event::NoneButton);
|
||||
|
||||
queueEvent(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case ButtonRelease: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseUp);
|
||||
ev.setModifiers(get_modifiers_from_xevent(event.xbutton.state));
|
||||
ev.setPosition(gfx::Point(event.xbutton.x / m_scale,
|
||||
event.xbutton.y / m_scale));
|
||||
ev.setButton(
|
||||
event.xbutton.button == 1 ? Event::LeftButton:
|
||||
event.xbutton.button == 2 ? Event::MiddleButton:
|
||||
event.xbutton.button == 3 ? Event::RightButton:
|
||||
event.xbutton.button == 4 ? Event::X1Button:
|
||||
event.xbutton.button == 5 ? Event::X2Button: Event::NoneButton);
|
||||
|
||||
queueEvent(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionNotify: {
|
||||
Event ev;
|
||||
ev.setType(Event::MouseMove);
|
||||
ev.setModifiers(get_modifiers_from_xevent(event.xmotion.state));
|
||||
ev.setPosition(gfx::Point(event.xmotion.x / m_scale,
|
||||
event.xmotion.y / m_scale));
|
||||
queueEvent(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace she
|
@ -8,72 +8,64 @@
|
||||
#define SHE_X11_WINDOW_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/fwd.h"
|
||||
#include "gfx/size.h"
|
||||
#include "she/native_cursor.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace she {
|
||||
|
||||
class Event;
|
||||
class Surface;
|
||||
|
||||
template<typename T>
|
||||
class X11Window {
|
||||
public:
|
||||
X11Window(::Display* display, int width, int height)
|
||||
: m_display(display) {
|
||||
::Window root = XDefaultRootWindow(m_display);
|
||||
X11Window(::Display* display, int width, int height, int scale);
|
||||
~X11Window();
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.event_mask = (StructureNotifyMask | ExposureMask | PropertyChangeMask |
|
||||
EnterWindowMask | LeaveWindowMask | FocusChangeMask |
|
||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
||||
KeyPressMask | KeyReleaseMask);
|
||||
int scale() const { return m_scale; }
|
||||
void setScale(const int scale);
|
||||
|
||||
m_window = XCreateWindow(
|
||||
m_display, root,
|
||||
0, 0, width, height, 0,
|
||||
CopyFromParent,
|
||||
InputOutput,
|
||||
CopyFromParent,
|
||||
CWEventMask,
|
||||
&swa);
|
||||
void setTitle(const std::string& title);
|
||||
|
||||
XMapWindow(m_display, m_window);
|
||||
XSelectInput(m_display, m_window, StructureNotifyMask);
|
||||
gfx::Size clientSize() const { return m_clientSize; }
|
||||
gfx::Size restoredSize() const { return m_clientSize; }
|
||||
void captureMouse();
|
||||
void releaseMouse();
|
||||
void setMousePosition(const gfx::Point& position);
|
||||
void updateWindow(const gfx::Rect& bounds);
|
||||
bool setNativeMouseCursor(NativeCursor cursor);
|
||||
bool setNativeMouseCursor(const she::Surface* surface,
|
||||
const gfx::Point& focus,
|
||||
const int scale);
|
||||
|
||||
m_gc = XCreateGC(m_display, m_window, 0, nullptr);
|
||||
}
|
||||
|
||||
~X11Window() {
|
||||
XFreeGC(m_display, m_gc);
|
||||
XDestroyWindow(m_display, m_window);
|
||||
}
|
||||
|
||||
void queueEvent(Event& ev) {
|
||||
static_cast<T*>(this)->queueEventImpl(ev);
|
||||
}
|
||||
|
||||
void setTitle(const std::string& title) {
|
||||
XTextProperty prop;
|
||||
prop.value = (unsigned char*)title.c_str();
|
||||
prop.encoding = XA_STRING;
|
||||
prop.format = 8;
|
||||
prop.nitems = std::strlen((char*)title.c_str());
|
||||
XSetWMName(m_display, m_window, &prop);
|
||||
}
|
||||
|
||||
virtual void onExpose() = 0;
|
||||
|
||||
::Display* display() const { return m_display; }
|
||||
::Display* x11display() const { return m_display; }
|
||||
::Window handle() const { return m_window; }
|
||||
::GC gc() const { return m_gc; }
|
||||
|
||||
void processX11Event(XEvent& event);
|
||||
static X11Window* getPointerFromHandle(Window handle);
|
||||
|
||||
protected:
|
||||
virtual void queueEvent(Event& event) = 0;
|
||||
virtual void paintGC(const gfx::Rect& rc) = 0;
|
||||
virtual void resizeDisplay(const gfx::Size& sz) = 0;
|
||||
|
||||
private:
|
||||
static void addWindow(X11Window* window);
|
||||
static void removeWindow(X11Window* window);
|
||||
|
||||
::Display* m_display;
|
||||
::Window m_window;
|
||||
::GC m_gc;
|
||||
int m_scale;
|
||||
gfx::Size m_clientSize;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
Loading…
x
Reference in New Issue
Block a user