#include #include #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