Esempio n. 1
0
static inline void post_key_event(uiohook_event * const event) {
	#ifdef USE_XTEST
	// FIXME Currently ignoring EVENT_KEY_TYPED.
	if (event->type == EVENT_KEY_PRESSED) {
		XTestFakeKeyEvent(
			properties_disp,
			scancode_to_keycode(event->data.keyboard.keycode),
			True,
			0);
	}
	else if (event->type == EVENT_KEY_RELEASED) {
		XTestFakeKeyEvent(
			properties_disp,
			scancode_to_keycode(event->data.keyboard.keycode),
			False,
			0);
	}
	#else
	XKeyEvent key_event;

	key_event.serial = 0x00;
	key_event.send_event = False;
	key_event.display = properties_disp;
	key_event.time = CurrentTime;
	key_event.same_screen = True;

	unsigned int mask;
	if (!XQueryPointer(properties_disp, DefaultRootWindow(properties_disp), &(key_event.root), &(key_event.subwindow), &(key_event.x_root), &(key_event.y_root), &(key_event.x), &(key_event.y), &mask)) {
		key_event.root = DefaultRootWindow(properties_disp);
		key_event.window = key_event.root;
		key_event.subwindow = None;

		key_event.x_root = 0;
		key_event.y_root = 0;
		key_event.x = 0;
		key_event.y = 0;
	}

	key_event.state = convert_to_native_mask(event->mask);
	key_event.keycode = XKeysymToKeycode(properties_disp, scancode_to_keycode(event->data.keyboard.keycode));

	// FIXME Currently ignoring typed events.
	if (event->type == EVENT_KEY_PRESSED) {
		key_event.type = KeyPress;
		XSendEvent(properties_disp, InputFocus, False, KeyPressMask, (XEvent *) &key_event);
	}
	else if (event->type == EVENT_KEY_RELEASED) {
		key_event.type = KeyRelease;
		XSendEvent(properties_disp, InputFocus, False, KeyReleaseMask, (XEvent *) &key_event);
	}
	#endif
}
Esempio n. 2
0
UIOHOOK_API void hook_post_event(uiohook_event * const event) {
	#ifdef USE_XTEST
	// XTest does not have modifier support, so we fake it by depressing the
	// appropriate modifier keys.
	for (unsigned int i = 0; i < sizeof(keymask_lookup) / sizeof(KeySym); i++) {
		if (event->mask & 1 << i) {
			XTestFakeKeyEvent(disp, XKeysymToKeycode(disp, keymask_lookup[i]), True, 0);
		}
	}

	for (unsigned int i = 0; i < sizeof(btnmask_lookup) / sizeof(unsigned int); i++) {
		if (event->mask & btnmask_lookup[i]) {
			XTestFakeButtonEvent(disp, i + 1, True, 0);
		}
	}

	switch (event->type) {
		case EVENT_KEY_PRESSED:
			XTestFakeKeyEvent(
				disp,
				scancode_to_keycode(event->data.keyboard.keycode),
				True,
				0);
			break;

		case EVENT_KEY_RELEASED:
			XTestFakeKeyEvent(
				disp,
				scancode_to_keycode(event->data.keyboard.keycode),
				False,
				0);
			break;


		case EVENT_MOUSE_PRESSED:
			XTestFakeButtonEvent(disp, event->data.mouse.button, True, 0);
			break;

		case EVENT_MOUSE_RELEASED:
			XTestFakeButtonEvent(disp, event->data.mouse.button, False, 0);
			break;
			
		case EVENT_MOUSE_WHEEL:
			// Wheel events should be the same as click events on X11.
			// type, amount and rotation
			if (event->data.wheel.rotation < 0) {
				XTestFakeButtonEvent(disp, WheelUp, True, 0);
				XTestFakeButtonEvent(disp, WheelUp, False, 0);
			}
			else {
				XTestFakeButtonEvent(disp, WheelDown, True, 0);
				XTestFakeButtonEvent(disp, WheelDown, False, 0);
			}
			break;

			
		case EVENT_MOUSE_DRAGGED:
			// The button masks are all applied with the modifier masks.

		case EVENT_MOUSE_MOVED:
			XTestFakeMotionEvent(disp, -1, event->data.mouse.x, event->data.mouse.y, 0);
			break;


		case EVENT_MOUSE_CLICKED:
		case EVENT_KEY_TYPED:
			// Ignore clicked and typed events.
			
		case EVENT_HOOK_ENABLED:
		case EVENT_HOOK_DISABLED:
			// Ignore hook enabled / disabled events.

		default:
			// Ignore any other garbage.
			logger(LOG_LEVEL_WARN, "%s [%u]: Ignoring post event type %#X\n",
				__FUNCTION__, __LINE__, event->type);
			break;
	}

	// Release the previously held modifier keys used to fake the event mask.
	for (unsigned int i = 0; i < sizeof(keymask_lookup) / sizeof(KeySym); i++) {
		if (event->mask & 1 << i) {
			XTestFakeKeyEvent(disp, XKeysymToKeycode(disp, keymask_lookup[i]), False, 0);
		}
	}

	for (unsigned int i = 0; i < sizeof(btnmask_lookup) / sizeof(unsigned int); i++) {
		if (event->mask & btnmask_lookup[i]) {
			XTestFakeButtonEvent(disp, i + 1, False, 0);
		}
	}
	#else
	XEvent *x_event;
	
	#if defined(USE_XINERAMA) || defined(USE_XRANDR)
	uint8_t screen_count;
	screen_data *screens;
	#endif

	switch (event->type) {
		case EVENT_KEY_PRESSED:
		case EVENT_KEY_RELEASED:
			// Allocate memory for XKeyEvent and pre-populate.
			x_event = (XEvent *) create_key_event();
			
			((XKeyEvent *) x_event)->state = convert_to_native_mask(event->mask);
			((XKeyEvent *) x_event)->keycode = XKeysymToKeycode(disp, scancode_to_keycode(event->data.keyboard.keycode));

			if (event->type == EVENT_KEY_PRESSED) {
				((XKeyEvent *) x_event)->type = KeyPress;
				XSendEvent(disp, InputFocus, False, KeyPressMask, x_event);
			}
			else {
				((XKeyEvent *) x_event)->type = KeyRelease;
				XSendEvent(disp, InputFocus, False, KeyReleaseMask, x_event);
			}
			
			free(x_event);
			break;


		case EVENT_MOUSE_PRESSED:
		case EVENT_MOUSE_RELEASED:
		case EVENT_MOUSE_WHEEL:
			// Allocate memory for XButtonEvent and pre-populate.
			x_event = (XEvent *) create_button_event();
			
			((XButtonEvent *) x_event)->state = convert_to_native_mask(event->mask);
			
			((XButtonEvent *) x_event)->x = event->data.mouse.x;
			((XButtonEvent *) x_event)->y = event->data.mouse.y;

			#if defined(USE_XINERAMA) || defined(USE_XRANDR)
			screens = hook_get_screen_info(&screen_count);
			if (screen_count > 1) {
				((XButtonEvent *) x_event)->x += screens[0].x;
				((XButtonEvent *) x_event)->y += screens[0].y;
			}
			#endif

			// These are the same because Window == Root Window.
			((XButtonEvent *) x_event)->x_root = ((XButtonEvent *) x_event)->x;
			((XButtonEvent *) x_event)->y_root = ((XButtonEvent *) x_event)->y;

			if (event->type == EVENT_MOUSE_WHEEL) {
				((XButtonEvent *) x_event)->type = ButtonPress;
				
				// type, amount and rotation
				if (event->data.wheel.rotation < 0) {
					((XButtonEvent *) x_event)->button = WheelUp;
				}
				else {
					((XButtonEvent *) x_event)->button = WheelDown;
				}
				XSendEvent(disp, InputFocus, False, ButtonPressMask, x_event);
			}
			
			if (event->type == EVENT_KEY_PRESSED) {
				((XButtonEvent *) x_event)->type = ButtonPress;
				XSendEvent(disp, InputFocus, False, ButtonPressMask, x_event);
			}
			else {
				((XButtonEvent *) x_event)->type = ButtonRelease;
				XSendEvent(disp, InputFocus, False, ButtonReleaseMask, x_event);
			}
			
			free(x_event);
			break;

		case EVENT_MOUSE_MOVED:
		case EVENT_MOUSE_DRAGGED:
			x_event = (XEvent *) create_motion_event();
			
			((XMotionEvent *) x_event)->state = convert_to_native_mask(event->mask);
			
			((XButtonEvent *) x_event)->x = event->data.mouse.x;
			((XButtonEvent *) x_event)->y = event->data.mouse.y;

			#if defined(USE_XINERAMA) || defined(USE_XRANDR)
			screens = hook_get_screen_info(&screen_count);
			if (screen_count > 1) {
				((XButtonEvent *) x_event)->x += screens[0].x;
				((XButtonEvent *) x_event)->y += screens[0].y;
			}
			#endif

			// These are the same because Window == Root Window.
			((XButtonEvent *) x_event)->x_root = ((XButtonEvent *) x_event)->x;
			((XButtonEvent *) x_event)->y_root = ((XButtonEvent *) x_event)->y;
			
			long int x_mask = NoEventMask;
			if (event->type == EVENT_MOUSE_DRAGGED) {
				#if Button1Mask == Button1MotionMask && \
					Button2Mask == Button2MotionMask && \
					Button3Mask == Button3MotionMask && \
					Button4Mask == Button4MotionMask && \
					Button5Mask == Button5MotionMask
				// This little trick only works if Button#MotionMasks align with
				// the Button#Masks.
				x_mask = ((XMotionEvent *) x_event)->state &
						(Button1MotionMask | Button2MotionMask |
						Button2MotionMask | Button3MotionMask | Button5MotionMask);
				#else
				// Fallback to some slightly larger...
				if (((XMotionEvent *) x_event)->state & Button1Mask) {
					x_mask |= Button1MotionMask;
				}

				if (((XMotionEvent *) x_event)->state & Button2Mask) {
					x_mask |= Button2MotionMask;
				}

				if (((XMotionEvent *) x_event)->state & Button3Mask) {
					x_mask |= Button3MotionMask;
				}

				if (((XMotionEvent *) x_event)->state & Button4Mask) {
					x_mask |= Button4MotionMask;
				}

				if (((XMotionEvent *) x_event)->state & Button5Mask) {
					x_mask |= Button5MotionMask;
				}
				#endif
			}
			
			// NOTE x_mask = NoEventMask.
			XSendEvent(disp, InputFocus, False, x_mask, x_event);
			free(x_event);
			break;


		case EVENT_MOUSE_CLICKED:
		case EVENT_KEY_TYPED:
			// Ignore clicked and typed events.
			
		case EVENT_HOOK_ENABLED:
		case EVENT_HOOK_DISABLED:
			// Ignore hook enabled / disabled events.

		default:
			// Ignore any other garbage.
			logger(LOG_LEVEL_WARN, "%s [%u]: Ignoring post event type %#X\n",
				__FUNCTION__, __LINE__, event->type);
			break;
	}


	#endif

	// Don't forget to flush!
	XFlush(disp);
}
Esempio n. 3
0
static inline void post_mouse_motion_event(uiohook_event * const event) {
    #ifdef USE_XTEST
	XTestFakeMotionEvent(properties_disp, -1, event->data.mouse.x, event->data.mouse.y, 0);
    #else
	XMotionEvent mov_event;

	mov_event.serial = MotionNotify;
	mov_event.send_event = False;
	mov_event.display = properties_disp;
	mov_event.time = CurrentTime;
	mov_event.same_screen = True;
	mov_event.is_hint = NotifyNormal,
	mov_event.root = DefaultRootWindow(properties_disp);
	mov_event.window = mov_event.root;
	mov_event.subwindow = None;

	mov_event.type = 0x00;
	mov_event.state = 0x00;
	mov_event.x_root = 0;
	mov_event.y_root = 0;
	mov_event.x = 0;
	mov_event.y = 0;

	mov_event.state = convert_to_native_mask(event->mask);

	mov_event.x = event->data.mouse.x;
	mov_event.y = event->data.mouse.y;

	#if defined(USE_XINERAMA) || defined(USE_XRANDR)
	uint8_t screen_count;
	screen_data *screens = hook_create_screen_info(&screen_count);
	if (screen_count > 1) {
		mov_event.x += screens[0].x;
		mov_event.y += screens[0].y;
	}

	if (screens != NULL) {
		free(screens);
	}
	#endif

	// These are the same because Window == Root Window.
	mov_event.x_root = mov_event.x;
	mov_event.y_root = mov_event.y;

	long int event_mask = NoEventMask;
	if (event->type == EVENT_MOUSE_DRAGGED) {
		#if Button1Mask == Button1MotionMask && \
			Button2Mask == Button2MotionMask && \
			Button3Mask == Button3MotionMask && \
			Button4Mask == Button4MotionMask && \
			Button5Mask == Button5MotionMask
		// This little trick only works if Button#MotionMasks align with
		// the Button#Masks.
		event_mask = mov_event.state &
				(Button1MotionMask | Button2MotionMask |
				Button2MotionMask | Button3MotionMask | Button5MotionMask);
		#else
		// Fallback to some slightly larger...
		if (event->state & Button1Mask) {
			event_mask |= Button1MotionMask;
		}

		if (event->state & Button2Mask) {
			event_mask |= Button2MotionMask;
		}

		if (event->state & Button3Mask) {
			event_mask |= Button3MotionMask;
		}

		if (event->state & Button4Mask) {
			event_mask |= Button4MotionMask;
		}

		if (event->state & Button5Mask) {
			event_mask |= Button5MotionMask;
		}
		#endif
	}

	// NOTE x_mask = NoEventMask.
	XSendEvent(properties_disp, InputFocus, False, event_mask, (XEvent *) &mov_event);
    #endif
}
Esempio n. 4
0
static inline void post_mouse_button_event(uiohook_event * const event) {
	#ifdef USE_XTEST
	Window ret_root;
	Window ret_child;
	int root_x;
	int root_y;
	int win_x;
	int win_y;
	unsigned int mask;

	Window win_root = XDefaultRootWindow(properties_disp);
	Bool query_status = XQueryPointer(properties_disp, win_root, &ret_root, &ret_child, &root_x, &root_y, &win_x, &win_y, &mask);
	if (query_status) {
		if (event->data.mouse.x != root_x || event->data.mouse.y != root_y) {
			// Move the pointer to the specified position.
			XTestFakeMotionEvent(properties_disp, -1, event->data.mouse.x, event->data.mouse.y, 0);
		}
		else {
			query_status = False;
		}
	}

	if (event->type == EVENT_MOUSE_WHEEL) {
		// Wheel events should be the same as click events on X11.
		// type, amount and rotation
		if (event->data.wheel.rotation < 0) {
			XTestFakeButtonEvent(properties_disp, WheelUp, True, 0);
			XTestFakeButtonEvent(properties_disp, WheelUp, False, 0);
		}
		else {
			XTestFakeButtonEvent(properties_disp, WheelDown, True, 0);
			XTestFakeButtonEvent(properties_disp, WheelDown, False, 0);
		}
	}
	else if (event->type == EVENT_MOUSE_PRESSED) {
		XTestFakeButtonEvent(properties_disp, event->data.mouse.button, True, 0);
	}
	else if (event->type == EVENT_MOUSE_RELEASED) {
		XTestFakeButtonEvent(properties_disp, event->data.mouse.button, False, 0);
	}
	else if (event->type == EVENT_MOUSE_CLICKED) {
		XTestFakeButtonEvent(properties_disp, event->data.mouse.button, True, 0);
		XTestFakeButtonEvent(properties_disp, event->data.mouse.button, False, 0);
	}

	if (query_status) {
		// Move the pointer back to the original position.
		XTestFakeMotionEvent(properties_disp, -1, root_x, root_y, 0);
	}
	#else
	XButtonEvent btn_event;

	btn_event.serial = 0x00;
	btn_event.send_event = False;
	btn_event.display = properties_disp;
	btn_event.time = CurrentTime;
	btn_event.same_screen = True;

	btn_event.root = DefaultRootWindow(properties_disp);
	btn_event.window = btn_event.root;
	btn_event.subwindow = None;

	btn_event.type = 0x00;
	btn_event.state = 0x00;
	btn_event.x_root = 0;
	btn_event.y_root = 0;
	btn_event.x = 0;
	btn_event.y = 0;
	btn_event.button = 0x00;

	btn_event.state = convert_to_native_mask(event->mask);

	btn_event.x = event->data.mouse.x;
	btn_event.y = event->data.mouse.y;

	#if defined(USE_XINERAMA) || defined(USE_XRANDR)
	uint8_t screen_count;
	screen_data *screens = hook_create_screen_info(&screen_count);
	if (screen_count > 1) {
		btn_event.x += screens[0].x;
		btn_event.y += screens[0].y;
	}

	if (screens != NULL) {
		free(screens);
	}
	#endif

	// These are the same because Window == Root Window.
	btn_event.x_root = btn_event.x;
	btn_event.y_root = btn_event.y;

	if (event->type == EVENT_MOUSE_WHEEL) {
		// type, amount and rotation
		if (event->data.wheel.rotation < 0) {
			btn_event.button = WheelUp;
		}
		else {
			btn_event.button = WheelDown;
		}
	}

	if (event->type != EVENT_MOUSE_RELEASED) {
		// FIXME Where do we set event->button?
		btn_event.type = ButtonPress;
		XSendEvent(properties_disp, InputFocus, False, ButtonPressMask, (XEvent *) &btn_event);
	}

	if (event->type != EVENT_MOUSE_PRESSED) {
		btn_event.type = ButtonRelease;
		XSendEvent(properties_disp, InputFocus, False, ButtonReleaseMask, (XEvent *) &btn_event);
	}
	#endif
}