linux - raw motion

This commit is contained in:
Mikulas Florek 2021-04-14 20:19:25 +02:00
parent e2e261574d
commit 6f16e68d88
5 changed files with 68 additions and 16 deletions

View file

@ -92,6 +92,7 @@ jobs:
sudo apt-get install libasound2-dev
sudo apt-get install libgl1-mesa-dev
sudo apt-get install libgl1-mesa-glx
sudo apt-get install libxi-dev
- name: Download 3rdparties
run: |
cd projects

View file

@ -593,7 +593,7 @@ if has_plugin("renderer") then
linkLib "freetype"
linkOpenGL()
configuration { "linux" }
links { "GL", "X11" }
links { "GL", "X11", "Xi" }
configuration {}
useLua()
@ -788,7 +788,7 @@ if build_app then
kind "WindowedApp"
configuration { "linux" }
links { "GL", "X11", "dl", "rt" }
links { "GL", "X11", "dl", "rt", "Xi" }
configuration {}
@ -913,7 +913,7 @@ if build_studio then
if not _OPTIONS["dynamic-plugins"] then
configuration { "linux" }
links { "dl", "GL", "X11", "rt" }
links { "dl", "GL", "X11", "rt", "Xi" }
if _ACTION == "gmake" then
linkoptions { "-Wl,-rpath '-Wl,$$ORIGIN'" }
end

View file

@ -28,6 +28,9 @@
#include <unistd.h>
#define GLX_GLXEXT_LEGACY
#include <GL/glx.h>
#include <X11/extensions/XInput2.h>
#include <X11/cursorfont.h>
#include <X11/Xmd.h>
#define _NET_WM_STATE_ADD 1
@ -52,13 +55,15 @@ static struct {
Display* display = nullptr;
XIC ic;
XIM im;
IVec2 mouse_screen_pos = {};
IVec2 mouse_screen_pos = {}; // only valid if has_raw_inputs == false
bool key_states[256] = {};
Atom net_wm_state_atom;
Atom net_wm_state_maximized_vert_atom;
Atom net_wm_state_maximized_horz_atom;
Atom wm_protocols_atom;
Atom wm_delete_window_atom;
int xinput_opcode = 0;
bool has_raw_inputs = false;
} G;
bool getAppDataDir(Span<char> path) {
@ -277,6 +282,25 @@ void init() {
G.net_wm_state_maximized_vert_atom = XInternAtom(G.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
G.wm_protocols_atom = XInternAtom(G.display, "WM_PROTOCOLS", False);
G.wm_delete_window_atom = XInternAtom(G.display, "WM_DELETE_WINDOW", False);
int first, error;
if (XQueryExtension(G.display, "XInputExtension", &G.xinput_opcode, &first, &error) == False) {
logError("Missing XInputExtension, mouse input will be broken.");
}
else {
unsigned char mask_bytes[XIMaskLen(XI_RawMotion)];
XISetMask(mask_bytes, XI_RawMotion);
XIEventMask mask;
mask.deviceid = XIAllMasterDevices;
mask.mask_len = sizeof(mask_bytes);
mask.mask = mask_bytes;
Window root = DefaultRootWindow(G.display);
XISelectEvents(G.display, root, &mask, 1);
G.has_raw_inputs = true;
}
}
InputFile::InputFile() {
@ -433,6 +457,35 @@ next:
if (XFilterEvent(&xevent, None)) return false;
if ((xevent.xcookie.type == GenericEvent) && (xevent.xcookie.extension == G.xinput_opcode)) {
XGetEventData(G.display, &xevent.xcookie);
bool handled = false;
if (xevent.xcookie.evtype == XI_RawMotion) {
XIRawEvent* re = (XIRawEvent*)xevent.xcookie.data;
if (re->valuators.mask_len) {
const double* values = re->raw_values;
e.window = INVALID_WINDOW;
e.type = Event::Type::MOUSE_MOVE;
if (XIMaskIsSet(re->valuators.mask, 0)) {
e.mouse_move.xrel = *values;
values++;
}
if (XIMaskIsSet(re->valuators.mask, 1)) {
e.mouse_move.yrel = *values;
}
handled = true;
}
}
XFreeEventData(G.display, &xevent.xcookie);
if(handled) return true;
}
switch (xevent.type) {
default: goto next;
case KeyPress: {
@ -513,9 +566,12 @@ next:
return true;
}
case MotionNotify:
if (G.has_raw_inputs) goto next;
const IVec2 mp(xevent.xmotion.x, xevent.xmotion.y);
const IVec2 rel = mp - G.mouse_screen_pos;
G.mouse_screen_pos = mp;
e.window = (WindowHandle)xevent.xmotion.window;
e.type = Event::Type::MOUSE_MOVE;
e.mouse_move.xrel = rel.x;
@ -962,10 +1018,13 @@ bool makePath(const char* path) {
void grabMouse(WindowHandle window) {
// const u32 mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
// X11_XGrabPointer(G.display, window, True, mask, GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
// ASSERT(false);
// TODO
if (window == INVALID_WINDOW) {
XUngrabPointer(G.display, CurrentTime);
}
else {
const u32 mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
XGrabPointer(G.display, (Window)window, True, mask, GrabModeAsync, GrabModeAsync, (Window)window, None, CurrentTime);
}
}

View file

@ -360,10 +360,6 @@ void GameView::onWindowGUI()
}
if (m_is_mouse_captured) {
os::setMouseScreenPos(m_captured_mouse_x, m_captured_mouse_y);
}
if (m_is_mouse_captured && os::getFocused() != ImGui::GetWindowViewport()->PlatformHandle) captureMouse(false);
ImGui::End();
ImGui::PopStyleVar();

View file

@ -1495,10 +1495,6 @@ void SceneView::onWindowGUI()
m_view->m_draw_cmds.clear();
}
if (m_is_mouse_captured) {
os::setMouseScreenPos(m_captured_mouse_x, m_captured_mouse_y);
}
if (m_is_mouse_captured && os::getFocused() != ImGui::GetWindowViewport()->PlatformHandle) {
captureMouse(false);
}