135 lines
2.8 KiB
C++
135 lines
2.8 KiB
C++
|
|
#include <Spectre/System/Event.h>
|
|
#include <Spectre/System/Log.h>
|
|
#include "Xlib.h"
|
|
#include "X11Window.h"
|
|
#include "X11Mouse.h"
|
|
|
|
#define XBUTTON1BIT (1<<0)
|
|
#define XBUTTON2BIT (1<<1)
|
|
|
|
namespace sp {
|
|
|
|
namespace _priv {
|
|
|
|
// Variable to handle extra button state (not queryable in xlib)
|
|
unsigned int xstate = 0;
|
|
}
|
|
|
|
X11Mouse::X11Mouse() :
|
|
m_btn_state(0)
|
|
{
|
|
}
|
|
|
|
void X11Mouse::init()
|
|
{
|
|
updateFocusedWindow();
|
|
}
|
|
|
|
Vector2f X11Mouse::getPosition() const
|
|
{
|
|
return m_position;
|
|
}
|
|
|
|
Vector2f X11Mouse::getAbsPosition() const
|
|
{
|
|
return m_abs_position;
|
|
}
|
|
|
|
bool X11Mouse::isButtonDown(Mouse::Button button) const
|
|
{
|
|
// Only signal that a button is down
|
|
// if we have focus on a window.
|
|
if (!m_win) {
|
|
return false;
|
|
}
|
|
|
|
switch(button) {
|
|
case Mouse::Button::Left :
|
|
return m_btn_state & Button1Mask;
|
|
case Mouse::Button::Right :
|
|
return m_btn_state & Button3Mask;
|
|
case Mouse::Button::Middle :
|
|
return m_btn_state & Button2Mask;
|
|
case Mouse::Button::XButton1 :
|
|
return _priv::xstate & XBUTTON1BIT;
|
|
case Mouse::Button::XButton2 :
|
|
return _priv::xstate & XBUTTON2BIT;
|
|
default :
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void X11Mouse::update(InputModule *input)
|
|
{
|
|
::Display* disp = Xlib::getDisplay();
|
|
::Window root, child;
|
|
int rx, ry, x = 0, y = 0;
|
|
|
|
updateFocusedWindow();
|
|
|
|
// Query position and button state.
|
|
XQueryPointer(disp,
|
|
m_win ? m_win : ::XDefaultRootWindow(disp),
|
|
&root, &child,
|
|
&rx, &ry,
|
|
&x, &y, &m_btn_state);
|
|
|
|
// Update abs position (relative to root).
|
|
m_abs_position.x = rx;
|
|
m_abs_position.y = ry;
|
|
|
|
// Update window position.
|
|
if (m_win) {
|
|
m_position.x = x;
|
|
m_position.y = y;
|
|
}
|
|
}
|
|
|
|
void X11Mouse::updateFocusedWindow()
|
|
{
|
|
X11Window *focus = X11Window::getFocused();
|
|
m_win = focus ? (::Window) focus->getHandle() : 0;
|
|
}
|
|
|
|
#define SETXSTATE(bit) \
|
|
_priv::xstate = (xevent->type == ButtonPress) \
|
|
? _priv::xstate | (bit) \
|
|
: _priv::xstate & ~(bit)
|
|
|
|
bool X11Mouse::handleMessage(XEvent* xevent, Event& event)
|
|
{
|
|
if (xevent->type == MotionNotify) {
|
|
event.type = Event::MouseMove;
|
|
event.mouseMove.x = xevent->xmotion.x;
|
|
event.mouseMove.y = xevent->xmotion.y;
|
|
return true;
|
|
}
|
|
|
|
if (xevent->type == ButtonPress || xevent->type == ButtonRelease) {
|
|
|
|
Mouse::Button trans = Mouse::Button::Unknown;
|
|
|
|
switch(xevent->xbutton.button) {
|
|
case Button1 : trans = Mouse::Button::Left; break;
|
|
case Button2 : trans = Mouse::Button::Middle; break;
|
|
case Button3 : trans = Mouse::Button::Right; break;
|
|
// Xlib do not support querying of button 8 and 9.
|
|
// so we have to fake it.
|
|
case 8 : trans = Mouse::Button::XButton1; SETXSTATE(XBUTTON1BIT); break;
|
|
case 9 : trans = Mouse::Button::XButton2; SETXSTATE(XBUTTON2BIT); break;
|
|
}
|
|
|
|
if (trans != Mouse::Button::Unknown) {
|
|
event.type = Event::MouseButton;
|
|
event.mouseButton.pressed = xevent->type == ButtonPress;
|
|
event.mouseButton.button = trans;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // namespace sp
|