X11Window: implement event handling and modifiers

BUG=angleproject:892

Change-Id: I65f251abdd28b273e2d3d574825f20bba8bb2532
Reviewed-on: https://chromium-review.googlesource.com/270452
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2015-05-12 10:37:01 -04:00
Родитель ac3ab8828f
Коммит 43b0c221cc
2 изменённых файлов: 264 добавлений и 27 удалений

Просмотреть файл

@ -9,7 +9,8 @@
#include "x11/X11Window.h"
X11Window::X11Window()
: mDisplay(nullptr),
: WM_DELETE_WINDOW(None),
mDisplay(nullptr),
mWindow(0)
{
}
@ -29,26 +30,55 @@ bool X11Window::initialize(const std::string &name, size_t width, size_t height)
return false;
}
int screen = DefaultScreen(mDisplay);
Window root = RootWindow(mDisplay, screen);
Colormap colormap = XCreateColormap(mDisplay, root, DefaultVisual(mDisplay, screen), AllocNone);
int depth = DefaultDepth(mDisplay, screen);
Visual *visual = DefaultVisual(mDisplay, screen);
{
int screen = DefaultScreen(mDisplay);
Window root = RootWindow(mDisplay, screen);
XSetWindowAttributes attributes;
unsigned long attributeMask = CWBorderPixel | CWColormap | CWEventMask;
Colormap colormap = XCreateColormap(mDisplay, root, DefaultVisual(mDisplay, screen), AllocNone);
int depth = DefaultDepth(mDisplay, screen);
Visual *visual = DefaultVisual(mDisplay, screen);
// TODO(cwallez) change when input is implemented
attributes.event_mask = 0;
attributes.border_pixel = 0;
attributes.colormap = colormap;
XSetWindowAttributes attributes;
unsigned long attributeMask = CWBorderPixel | CWColormap | CWEventMask;
mWindow = XCreateWindow(mDisplay, root, 0, 0, width, height, 0, depth, InputOutput,
visual, attributeMask, &attributes);
attributes.event_mask = StructureNotifyMask | PointerMotionMask | ButtonPressMask |
ButtonReleaseMask | FocusChangeMask | EnterWindowMask |
LeaveWindowMask;
attributes.border_pixel = 0;
attributes.colormap = colormap;
mWindow = XCreateWindow(mDisplay, root, 0, 0, width, height, 0, depth, InputOutput,
visual, attributeMask, &attributes);
XFreeColormap(mDisplay, colormap);
}
if (!mWindow)
{
XFreeColormap(mDisplay, colormap);
destroy();
return false;
}
// Tell the window manager to notify us when the user wants to close the
// window so we can do it ourselves.
WM_DELETE_WINDOW = XInternAtom(mDisplay, "WM_DELETE_WINDOW", False);
WM_PROTOCOLS = XInternAtom(mDisplay, "WM_PROTOCOLS", False);
if (WM_DELETE_WINDOW == None || WM_PROTOCOLS == None)
{
destroy();
return false;
}
if(XSetWMProtocols(mDisplay, mWindow, &WM_DELETE_WINDOW, 1) == 0)
{
destroy();
return false;
}
// Create an atom to identify our test event
TEST_EVENT = XInternAtom(mDisplay, "ANGLE_TEST_EVENT", False);
if (TEST_EVENT == None)
{
destroy();
return false;
}
@ -74,6 +104,8 @@ void X11Window::destroy()
XCloseDisplay(mDisplay);
mDisplay = nullptr;
}
WM_DELETE_WINDOW = None;
WM_PROTOCOLS = None;
}
EGLNativeWindowType X11Window::getNativeWindow() const
@ -88,12 +120,18 @@ EGLNativeDisplayType X11Window::getNativeDisplay() const
void X11Window::messageLoop()
{
//TODO
int eventCount = XPending(mDisplay);
while (eventCount--)
{
XEvent event;
XNextEvent(mDisplay, &event);
processEvent(event);
}
}
void X11Window::setMousePosition(int x, int y)
{
//TODO
XWarpPointer(mDisplay, None, mWindow, 0, 0, 0, 0, x, y);
}
OSWindow *CreateOSWindow()
@ -103,13 +141,15 @@ OSWindow *CreateOSWindow()
bool X11Window::setPosition(int x, int y)
{
//TODO
XMoveWindow(mDisplay, mWindow, x, y);
XFlush(mDisplay);
return true;
}
bool X11Window::resize(int width, int height)
{
//TODO
XResizeWindow(mDisplay, mWindow, width, height);
XFlush(mDisplay);
return true;
}
@ -126,12 +166,205 @@ void X11Window::setVisible(bool isVisible)
XFlush(mDisplay);
}
void X11Window::pushEvent(Event event)
{
//TODO
}
void X11Window::signalTestEvent()
{
//TODO
XEvent event;
event.type = ClientMessage;
event.xclient.message_type = TEST_EVENT;
// Format needs to be valid or a BadValue is generated
event.xclient.format = 32;
// Hijack StructureNotifyMask as we know we will be listening for it.
XSendEvent(mDisplay, mWindow, False, StructureNotifyMask, &event);
}
void X11Window::processEvent(const XEvent &xEvent)
{
// TODO(cwallez) handle key presses and text events
switch (xEvent.type)
{
case ButtonPress:
{
Event event;
MouseButton button = MOUSEBUTTON_UNKNOWN;
int wheelX = 0;
int wheelY = 0;
// The mouse wheel updates are sent via button events.
switch (xEvent.xbutton.button)
{
case Button4:
wheelY = 1;
break;
case Button5:
wheelY = -1;
break;
case 6:
wheelX = 1;
break;
case 7:
wheelX = -1;
break;
case Button1:
button = MOUSEBUTTON_LEFT;
break;
case Button2:
button = MOUSEBUTTON_MIDDLE;
break;
case Button3:
button = MOUSEBUTTON_RIGHT;
break;
case 8:
button = MOUSEBUTTON_BUTTON4;
break;
case 9:
button = MOUSEBUTTON_BUTTON5;
break;
default:
break;
}
if (wheelY != 0)
{
event.Type = Event::EVENT_MOUSE_WHEEL_MOVED;
event.MouseWheel.Delta = wheelY;
pushEvent(event);
}
if (button != MOUSEBUTTON_UNKNOWN)
{
event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
event.MouseButton.Button = button;
event.MouseButton.X = xEvent.xbutton.x;
event.MouseButton.Y = xEvent.xbutton.y;
pushEvent(event);
}
}
break;
case ButtonRelease:
{
Event event;
MouseButton button = MOUSEBUTTON_UNKNOWN;
switch (xEvent.xbutton.button)
{
case Button1:
button = MOUSEBUTTON_LEFT;
break;
case Button2:
button = MOUSEBUTTON_MIDDLE;
break;
case Button3:
button = MOUSEBUTTON_RIGHT;
break;
case 8:
button = MOUSEBUTTON_BUTTON4;
break;
case 9:
button = MOUSEBUTTON_BUTTON5;
break;
default:
break;
}
if (button != MOUSEBUTTON_UNKNOWN)
{
event.Type = Event::EVENT_MOUSE_BUTTON_RELEASED;
event.MouseButton.Button = button;
event.MouseButton.X = xEvent.xbutton.x;
event.MouseButton.Y = xEvent.xbutton.y;
pushEvent(event);
}
}
break;
case EnterNotify:
{
Event event;
event.Type = Event::EVENT_MOUSE_ENTERED;
pushEvent(event);
}
break;
case LeaveNotify:
{
Event event;
event.Type = Event::EVENT_MOUSE_LEFT;
pushEvent(event);
}
break;
case MotionNotify:
{
Event event;
event.Type = Event::EVENT_MOUSE_MOVED;
event.MouseMove.X = xEvent.xmotion.x;
event.MouseMove.Y = xEvent.xmotion.y;
pushEvent(event);
}
break;
case ConfigureNotify:
{
if (xEvent.xconfigure.width != mWidth || xEvent.xconfigure.height != mHeight)
{
Event event;
event.Type = Event::EVENT_RESIZED;
event.Size.Width = xEvent.xconfigure.width;
event.Size.Height = xEvent.xconfigure.height;
pushEvent(event);
}
if (xEvent.xconfigure.x != mX || xEvent.xconfigure.y != mY)
{
Event event;
event.Type = Event::EVENT_MOVED;
event.Move.X = xEvent.xconfigure.x;
event.Move.Y = xEvent.xconfigure.y;
pushEvent(event);
}
}
break;
case FocusIn:
if (xEvent.xfocus.mode == NotifyNormal || xEvent.xfocus.mode == NotifyWhileGrabbed)
{
Event event;
event.Type = Event::EVENT_GAINED_FOCUS;
pushEvent(event);
}
break;
case FocusOut:
if (xEvent.xfocus.mode == NotifyNormal || xEvent.xfocus.mode == NotifyWhileGrabbed)
{
Event event;
event.Type = Event::EVENT_LOST_FOCUS;
pushEvent(event);
}
break;
case DestroyNotify:
// We already received WM_DELETE_WINDOW
break;
case ClientMessage:
if (xEvent.xclient.message_type == WM_PROTOCOLS &&
static_cast<Atom>(xEvent.xclient.data.l[0]) == WM_DELETE_WINDOW)
{
Event event;
event.Type = Event::EVENT_CLOSED;
pushEvent(event);
}
else if (xEvent.xclient.message_type == TEST_EVENT)
{
Event event;
event.Type = Event::EVENT_TEST;
pushEvent(event);
}
break;
}
}

Просмотреть файл

@ -30,8 +30,6 @@ class X11Window : public OSWindow
void messageLoop() override;
void pushEvent(Event event) override;
void setMousePosition(int x, int y) override;
bool setPosition(int x, int y) override;
bool resize(int width, int height) override;
@ -40,6 +38,12 @@ class X11Window : public OSWindow
void signalTestEvent() override;
private:
void processEvent(const XEvent &event);
Atom WM_DELETE_WINDOW;
Atom WM_PROTOCOLS;
Atom TEST_EVENT;
Display *mDisplay;
Window mWindow;
};