aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-07-29 22:01:36 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-29 22:01:36 +0200
commitf926cc9b8bbf0d33a8a6d4682fc4d5356cac8d55 (patch)
treecc2a2ec201a65fb2d7cb76a2a1cfc838b197e7fe
parent76a01f8da44497e1379f8503a6abf7bfd97e6a6b (diff)
Fix cursor warping and position
-rw-r--r--README.md4
-rw-r--r--include/window_manager.h6
-rw-r--r--src/main.cpp13
-rw-r--r--src/window_manager.c117
4 files changed, 94 insertions, 46 deletions
diff --git a/README.md b/README.md
index 0b2c8e4..8472d34 100644
--- a/README.md
+++ b/README.md
@@ -25,10 +25,8 @@ Alt+Mouse move = Move the view left/right
# Known issues
Switching tty kills the VR view.\
-Holding mouse button down and moving it doesn't work to for example selecting text in text editors.\
Not all windows show up in vr yet, such as rofi and floating description windows.\
-Not all windows can receive input correct, such as gtk applications.\
-Keyboard input doesn't always work for all windows...
+Can't move cursor while mouse button is being held down.
# TODO
Show the window manager inside games by creating the vr window manager as an openvr overlay. The overlay texture will be automatically
diff --git a/include/window_manager.h b/include/window_manager.h
index 86f4f46..a8713bc 100644
--- a/include/window_manager.h
+++ b/include/window_manager.h
@@ -18,6 +18,8 @@ typedef enum {
CURSOR_WRAP_RIGHT
} CursorWrapSide;
+enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+
typedef void (*WindowManagerAddWindowCallback)(Window window, void *userdata);
/* Return the new focused window. All other windows will be hidden to not interfer with input (but they will still be visible in vr) */
typedef Window (*WindowManagerRemoveWindowCallback)(Window window, void *userdata);
@@ -40,8 +42,12 @@ typedef struct {
void *userdata;
int window_width;
int window_height;
+ int cursor_prev_x;
+ int cursor_prev_y;
+ Window focused_window;
pthread_t thread;
int running;
+ Cursor cursor[CurLast];
} WindowManager;
/*
diff --git a/src/main.cpp b/src/main.cpp
index ce25bc7..6f4250f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -549,7 +549,6 @@ void CMainApplication::ButtonCallback(Display *display, int type, unsigned int s
if(button != Button1)
return;
- /* TODO: Check if other mod keys are not pressed (take numlock into consideration) */
if(state & Mod1Mask)
holding_alt_key = (type == ButtonPress);
else if(holding_alt_key && type == ButtonRelease)
@@ -1809,10 +1808,10 @@ void CMainApplication::RenderScene( vr::Hmd_Eye nEye )
float window_rotation = (float)window_rotation_offset;
#if 1
float rot = -window_rotation / (float)(m_nRenderWidth*2);
- float cursor_offset_x = 0.0f;
+ float screen_cursor_offset_x = 0.0f;
for(auto &window_data : window_data_list) {
float m[2];
- m[0] = eye_cursor_offset + cursor_offset_x + mx / (float)(m_nRenderWidth*2);
+ m[0] = eye_cursor_offset + screen_cursor_offset_x + mx / (float)(m_nRenderWidth*2);
m[1] = my / (float)m_nRenderHeight;
m[0] += (-cursor_offset_x * arrow_drawn_scale_x) / (float)(m_nRenderWidth*2);
@@ -1829,7 +1828,7 @@ void CMainApplication::RenderScene( vr::Hmd_Eye nEye )
glDrawArrays( GL_TRIANGLES, 0, m_uiVertcount );
rot += projection_angle_x;
- cursor_offset_x += 1.0f;
+ screen_cursor_offset_x += 1.0f;
}
#else
@@ -1838,10 +1837,10 @@ void CMainApplication::RenderScene( vr::Hmd_Eye nEye )
glm::vec3 offset(0.0f, 0.0f, zoom);
float rot = -window_rotation / (float)(m_nRenderWidth*2);
- float cursor_offset_x = 0.0f;
+ float screen_cursor_offset_x = 0.0f;
for(auto &window_data : window_data_list) {
float m[2];
- m[0] = eye_cursor_offset + cursor_offset_x + mx / (float)(m_nRenderWidth*2);
+ m[0] = eye_cursor_offset + screen_cursor_offset_x + mx / (float)(m_nRenderWidth*2);
m[1] = my / (float)m_nRenderHeight;
m[0] += (-cursor_offset_x * arrow_drawn_scale_x) / (float)(m_nRenderWidth*2);
@@ -1864,7 +1863,7 @@ void CMainApplication::RenderScene( vr::Hmd_Eye nEye )
offset.x += (-plane_width * 0.5f * cosf(rot));
offset.z += (plane_width * 0.5f * sinf(rot));
- cursor_offset_x += 1.0f;
+ screen_cursor_offset_x += 1.0f;
}
#endif
glActiveTexture(GL_TEXTURE0);
diff --git a/src/window_manager.c b/src/window_manager.c
index 954bbf2..b49c5af 100644
--- a/src/window_manager.c
+++ b/src/window_manager.c
@@ -2,10 +2,10 @@
#include <X11/keysym.h>
#include <X11/XF86keysym.h>
+#include <X11/cursorfont.h>
/*
#include <X11/Xproto.h>
#include <X11/Xatom.h>
-#include <X11/cursorfont.h>
*/
/* TODO: Check xrandr version */
@@ -23,6 +23,9 @@
#include <signal.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
static char *const menu_args[] = { "rofi", "-modi", "window,drun,combi", "-show", "combi", "-combi-modi", "window,drun", "-show-icons", NULL };
@@ -81,6 +84,7 @@ static int window_manager_show_window(WindowManager *self, Window window, Displa
self->window_data[window_index].visible = 1;
XMoveResizeWindow(display, window, 0, 0, self->window_width, self->window_height);
XRaiseWindow(display, window);
+ XSetInputFocus(display, window, RevertToPointerRoot, CurrentTime);
return 1;
}
return 0;
@@ -92,6 +96,7 @@ static int window_manager_hide_window(WindowManager *self, Window window, Displa
self->window_data[window_index].visible = 0;
XMoveResizeWindow(display, window, -self->window_width - 100, 0, self->window_width, self->window_height);
XLowerWindow(display, window);
+ XSetInputFocus(display, DefaultRootWindow(display), RevertToPointerRoot, CurrentTime);
return 1;
}
return 0;
@@ -116,6 +121,40 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee) {
return 0;
}
+static void window_manager_on_cursor_move(WindowManager *window_manager, Display *dpy, Window root, int root_x, int root_y, XIRawEvent *raw_ev) {
+ int diff_x = root_x - window_manager->cursor_prev_x;
+ int diff_y = root_y - window_manager->cursor_prev_y;
+ double diff_x_raw = diff_x;
+ if(raw_ev)
+ diff_x_raw = raw_ev->raw_values[0];
+
+ /* TODO: Detect fast cursor movement and move it that distance from the edge?. It it needed? */
+ int new_cursor_x = root_x;
+ CursorWrapSide cursor_wrap_side = CURSOR_WRAP_NONE;
+ if(new_cursor_x <= 0 && diff_x_raw < 0.0) {
+ new_cursor_x = window_manager->window_width;
+ cursor_wrap_side = CURSOR_WRAP_LEFT;
+ } else if(new_cursor_x >= window_manager->window_width - 1 && diff_x_raw > 0.0) {
+ new_cursor_x = 0;
+ cursor_wrap_side = CURSOR_WRAP_RIGHT;
+ }
+
+ window_manager->cursor_prev_x = new_cursor_x;
+ window_manager->cursor_prev_y = root_y;
+
+ if(cursor_wrap_side != CURSOR_WRAP_NONE) {
+ XWarpPointer(dpy, root, root, 0, 0, window_manager->window_width, window_manager->window_height, new_cursor_x, root_y);
+ XSync(dpy, False);
+ }
+
+ Window new_focused_window = window_manager->callback.move_cursor_callback(dpy, diff_x, diff_y, cursor_wrap_side, window_manager->userdata);
+ if(new_focused_window != window_manager->focused_window) {
+ window_manager_hide_window(window_manager, window_manager->focused_window, dpy);
+ window_manager_show_window(window_manager, new_focused_window, dpy);
+ window_manager->focused_window = new_focused_window;
+ }
+}
+
/* TODO: XRRSetCrtcTransform, XRRSetCrtcConfig (see ~/xrandr-test.c) */
static void* thread_main(void *userdata) {
@@ -152,8 +191,10 @@ static void* thread_main(void *userdata) {
root = DefaultRootWindow(dpy);
+#if 0
XSelectInput(dpy, root, SubstructureRedirectMask | SubstructureNotifyMask /*| ResizeRedirectMask*/);
XSync(dpy, False);
+#endif
KeyCode q_key = XKeysymToKeycode(dpy, XStringToKeysym("q"));
KeyCode f1_key = XKeysymToKeycode(dpy, XStringToKeysym("F1"));
@@ -166,8 +207,8 @@ static void* thread_main(void *userdata) {
GrabModeAsync,
GrabModeAsync, None, None);
- int cursor_prev_x = 0;
- int cursor_prev_y = 0;
+ window_manager->cursor_prev_x = 0;
+ window_manager->cursor_prev_y = 0;
Window dummy_w;
int dummy_int;
unsigned int dummy_m;
@@ -192,12 +233,26 @@ static void* thread_main(void *userdata) {
fd_set in_fds;
struct timeval tv;
+ int pointer_grabbed = 0;
+
+ window_manager->cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
+ window_manager->cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
+ window_manager->cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
+
+ XSetWindowAttributes wa;
+ wa.cursor = window_manager->cursor[CurNormal];
+ wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
+ |ButtonPressMask|PointerMotionMask|EnterWindowMask
+ |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
+ XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
+ XSelectInput(dpy, root, wa.event_mask);
+
while(window_manager->running) {
FD_ZERO(&in_fds);
FD_SET(x11_fd, &in_fds);
- /* Wake up thread every 100 ms */
- tv.tv_usec = 1000 * 100;
+ /* Wake up thread every 500ms ms if no events are received */
+ tv.tv_usec = 1000 * 500;
tv.tv_sec = 0;
int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv);
@@ -229,43 +284,26 @@ static void* thread_main(void *userdata) {
&win_x_return, &win_y_return,
&mask_return);
if(retval) {
- int diff_x = root_x_return - cursor_prev_x;
- int diff_y = root_y_return - cursor_prev_y;
-
- /* TODO: Detect fast cursor movement and move it that distance from the edge?. It it needed? */
- int new_cursor_x = root_x_return;
- CursorWrapSide cursor_wrap_side = CURSOR_WRAP_NONE;
- if(new_cursor_x <= 0) {
- new_cursor_x = window_manager->window_width;
- cursor_wrap_side = CURSOR_WRAP_LEFT;
- } else if(new_cursor_x >= window_manager->window_width) {
- new_cursor_x = 0;
- cursor_wrap_side = CURSOR_WRAP_RIGHT;
- }
-
- fprintf(stderr, "move cursor!\n");
- fflush(stderr);
-
- cursor_prev_x = new_cursor_x;
- cursor_prev_y = root_y_return;
-
- if(cursor_wrap_side != CURSOR_WRAP_NONE) {
- //XWarpPointer(dpy, root, root, 0, 0, window_manager->window_width, window_manager->window_height, new_cursor_x, root_y_return);
- //XSync(dpy, False);
- }
-
- Window new_focused_window = window_manager->callback.move_cursor_callback(dpy, diff_x, diff_y, cursor_wrap_side, window_manager->userdata);
- if(new_focused_window != focused_window) {
- window_manager_hide_window(window_manager, focused_window, dpy);
- window_manager_show_window(window_manager, new_focused_window, dpy);
- focused_window = new_focused_window;
- }
+ window_manager_on_cursor_move(window_manager, dpy, root, root_x_return, root_y_return, raw_ev);
}
}
if(got_event_data)
XFreeEventData(dpy, cookie);
+ if(ev.type == MotionNotify) {
+ while(XCheckTypedWindowEvent(dpy, ev.xmotion.window, MotionNotify, &ev));
+ window_manager_on_cursor_move(window_manager, dpy, root, ev.xmotion.x_root, ev.xmotion.y_root, NULL);
+ }
+
if(ev.type == ButtonPress || ev.type == ButtonRelease) {
+ if(ev.xbutton.state & Mod1Mask) {
+ if(ev.type == ButtonPress)
+ pointer_grabbed = XGrabPointer(dpy, root, False, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ }
+ if(ev.type == ButtonRelease) {
+ XUngrabPointer(dpy, CurrentTime);
+ pointer_grabbed = 0;
+ }
window_manager->callback.button_callback(dpy, ev.xbutton.type, ev.xbutton.state, ev.xbutton.button, window_manager->userdata);
}
@@ -294,6 +332,13 @@ static void* thread_main(void *userdata) {
XSync(dpy, False);
XSetErrorHandler(prev_err_handler);
XUngrabServer(dpy);
+
+ Window new_focused_window = window_manager->callback.move_cursor_callback(dpy, 0, 0, CURSOR_WRAP_NONE, window_manager->userdata);
+ if(new_focused_window != focused_window) {
+ window_manager_hide_window(window_manager, focused_window, dpy);
+ window_manager_show_window(window_manager, new_focused_window, dpy);
+ focused_window = new_focused_window;
+ }
} else {
/*window_manager->callback.key_callback(dpy, ev.xkey.type, ev.xkey.state, ev.xkey.keycode, window_manager->userdata);*/
}