Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fa5153a authored by that's avatar that Committed by Dees Troy
Browse files

gui: move input handling into a class

Change-Id: I97e08a23369af0112875af84b3fb529cf42e929e
parent e13fa63d
Loading
Loading
Loading
Loading
+243 −219
Original line number Diff line number Diff line
@@ -56,6 +56,12 @@ extern "C"
// Enable to print render time of each frame to the log file
//#define PRINT_RENDER_TIME 1

#ifdef _EVENT_LOGGING
#define LOGEVENT(...) LOGERR(__VA_ARGS)
#else
#define LOGEVENT(...) do {} while (0)
#endif

const static int CURTAIN_FADE = 32;

using namespace rapidxml;
@@ -67,7 +73,6 @@ static TWAtomicInt gGuiConsoleRunning;
static TWAtomicInt gGuiConsoleTerminate;
static TWAtomicInt gForceRender;
const int gNoAnimation = 1;
static int gGuiInputInit = 0;
blanktimer blankTimer;
int ors_read_fd = -1;

@@ -172,8 +177,21 @@ void curtainClose()
#endif
}

void input_init(void)
class InputHandler
{
public:
	void init()
	{
		// these might be read from DataManager in the future
		touch_hold_ms = 500;
		touch_repeat_ms = 100;
		key_hold_ms = 500;
		key_repeat_ms = 100;
		touch_status = TS_NONE;
		key_status = KS_NONE;
		state = AS_NO_ACTION;
		x = y = 0;

#ifndef TW_NO_SCREEN_TIMEOUT
		{
			string seconds;
@@ -184,9 +202,18 @@ void input_init(void)
#else
		LOGINFO("Skipping screen timeout: TW_NO_SCREEN_TIMEOUT is set\n");
#endif
	gGuiInputInit = 1;
	}

	void processInput();
	void handleDrag();

private:
	// timeouts for touch/key hold and repeat
	int touch_hold_ms;
	int touch_repeat_ms;
	int key_hold_ms;
	int key_repeat_ms;

	enum touch_status_enum {
		TS_NONE = 0,
		TS_TOUCH_AND_HOLD = 1,
@@ -200,99 +227,115 @@ enum key_status_enum {
	};

	enum action_state_enum {
	AS_IN_ACTION_AREA = 0,
	AS_NO_ACTION = 1,
		AS_IN_ACTION_AREA = 0, // we've touched a spot with an action
		AS_NO_ACTION = 1,    // we've touched in an empty area (no action) and ignore remaining events until touch release
	};
	touch_status_enum touch_status;
	key_status_enum key_status;
	action_state_enum state;
	int x, y; // x and y coordinates of last touch
	struct timeval touchStart; // used to track time for long press / key repeat

	void processHoldAndRepeat();
	void process_EV_REL(input_event& ev);
	void process_EV_ABS(input_event& ev);
	void process_EV_KEY(input_event& ev);

	void doTouchStart();
};

void get_input(int send_drag)
{
	static touch_status_enum touch_status = TS_NONE;
	static key_status_enum key_status = KS_NONE;
	static int x = 0, y = 0; // x and y coordinates
	static struct timeval touchStart; // used to track time for long press / key repeat
	static HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();
	static MouseCursor *cursor = PageManager::GetMouseCursor();
	struct input_event ev;
	static action_state_enum state = AS_NO_ACTION; // 1 means that we've touched in an empty area (no action) while 0 means we've touched a spot with an action
	int ret = 0; // return value from ev_get
InputHandler input_handler;

	if (send_drag) {
		// This allows us to only send one NotifyTouch event per render
		// cycle to reduce overhead and perceived input latency.
		static int prevx = 0, prevy = 0; // these track where the last drag notice was so that we don't send duplicate drag notices
		if (touch_status && (x != prevx || y != prevy)) {
			prevx = x;
			prevy = y;
			if (PageManager::NotifyTouch(TOUCH_DRAG, x, y) > 0)
				state = AS_NO_ACTION;
			else
				state = AS_IN_ACTION_AREA;
		}
		return;
	}

	ret = ev_get(&ev);
void InputHandler::processInput()
{
	input_event ev;
	int ret = ev_get(&ev);

	if (ret < 0)
	{
		// This path means that we did not get any new touch data, but
		// we do not get new touch data if you press and hold on either
		// the screen or on a keyboard key or mouse button
		if (touch_status || key_status) {
		if (touch_status || key_status)
			processHoldAndRepeat();
		return;
	}

	switch (ev.type)
	{
	case EV_ABS:
		process_EV_ABS(ev);
		break;

	case EV_REL:
		process_EV_REL(ev);
		break;

	case EV_KEY:
		process_EV_KEY(ev);
		break;
	}
}

void InputHandler::processHoldAndRepeat()
{
	HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();

	// touch and key repeat section
	struct timeval curTime;
			long mtime, seconds, useconds;
	gettimeofday(&curTime, NULL);
			seconds = curTime.tv_sec - touchStart.tv_sec;
			useconds = curTime.tv_usec - touchStart.tv_usec;
			mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5;
	long seconds = curTime.tv_sec - touchStart.tv_sec;
	long useconds = curTime.tv_usec - touchStart.tv_usec;
	long mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5;

			if (touch_status == TS_TOUCH_AND_HOLD && mtime > 500)
	if (touch_status == TS_TOUCH_AND_HOLD && mtime > touch_hold_ms)
	{
		touch_status = TS_TOUCH_REPEAT;
		gettimeofday(&touchStart, NULL);
#ifdef _EVENT_LOGGING
				LOGERR("TOUCH_HOLD: %d,%d\n", x, y);
#endif
		LOGEVENT("TOUCH_HOLD: %d,%d\n", x, y);
		PageManager::NotifyTouch(TOUCH_HOLD, x, y);
		blankTimer.resetTimerAndUnblank();
	}
			else if (touch_status == TS_TOUCH_REPEAT && mtime > 100)
	else if (touch_status == TS_TOUCH_REPEAT && mtime > touch_repeat_ms)
	{
#ifdef _EVENT_LOGGING
				LOGERR("TOUCH_REPEAT: %d,%d\n", x, y);
#endif
		LOGEVENT("TOUCH_REPEAT: %d,%d\n", x, y);
		gettimeofday(&touchStart, NULL);
		PageManager::NotifyTouch(TOUCH_REPEAT, x, y);
		blankTimer.resetTimerAndUnblank();
	}
			else if (key_status == KS_KEY_PRESSED && mtime > 500)
	else if (key_status == KS_KEY_PRESSED && mtime > key_hold_ms)
	{
#ifdef _EVENT_LOGGING
				LOGERR("KEY_HOLD: %d,%d\n", x, y);
#endif
		LOGEVENT("KEY_HOLD: %d,%d\n", x, y);
		gettimeofday(&touchStart, NULL);
		key_status = KS_KEY_REPEAT;
		kb->KeyRepeat();
		blankTimer.resetTimerAndUnblank();

	}
			else if (key_status == KS_KEY_REPEAT && mtime > 100)
	else if (key_status == KS_KEY_REPEAT && mtime > key_repeat_ms)
	{
#ifdef _EVENT_LOGGING
				LOGERR("KEY_REPEAT: %d,%d\n", x, y);
#endif
		LOGEVENT("KEY_REPEAT: %d,%d\n", x, y);
		gettimeofday(&touchStart, NULL);
		kb->KeyRepeat();
		blankTimer.resetTimerAndUnblank();
	}
		} else {
			return; // nothing is pressed so do nothing and exit
		}
}
	else if (ev.type == EV_ABS)

void InputHandler::doTouchStart()
{
	LOGEVENT("TOUCH_START: %d,%d\n", x, y);
	if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
		state = AS_NO_ACTION;
	else
		state = AS_IN_ACTION_AREA;
	touch_status = TS_TOUCH_AND_HOLD;
	gettimeofday(&touchStart, NULL);
	blankTimer.resetTimerAndUnblank();
}

void InputHandler::process_EV_ABS(input_event& ev)
{
	x = ev.value >> 16;
	y = ev.value & 0xFFFF;

@@ -300,9 +343,7 @@ void get_input(int send_drag)
	{
		if (state == AS_IN_ACTION_AREA)
		{
#ifdef _EVENT_LOGGING
				LOGERR("TOUCH_RELEASE: %d,%d\n", x, y);
#endif
			LOGEVENT("TOUCH_RELEASE: %d,%d\n", x, y);
			PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
			blankTimer.resetTimerAndUnblank();
		}
@@ -312,53 +353,33 @@ void get_input(int send_drag)
	{
		if (!touch_status)
		{
				if (x != 0 && y != 0) {
#ifdef _EVENT_LOGGING
					LOGERR("TOUCH_START: %d,%d\n", x, y);
#endif
					if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
						state = AS_NO_ACTION;
					else
						state = AS_IN_ACTION_AREA;
					touch_status = TS_TOUCH_AND_HOLD;
					gettimeofday(&touchStart, NULL);
				}
				blankTimer.resetTimerAndUnblank();
			doTouchStart();
		}
		else
		{
			if (state == AS_IN_ACTION_AREA)
			{
#ifdef _EVENT_LOGGING
					LOGERR("TOUCH_DRAG: %d,%d\n", x, y);
#endif
				LOGEVENT("TOUCH_DRAG: %d,%d\n", x, y);
				blankTimer.resetTimerAndUnblank();
			}
		}
	}
}
	else if (ev.type == EV_KEY)

void InputHandler::process_EV_KEY(input_event& ev)
{
	HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();

	// Handle key-press here
#ifdef _EVENT_LOGGING
		LOGERR("TOUCH_KEY: %d\n", ev.code);
#endif
		// Left mouse button
	LOGEVENT("TOUCH_KEY: %d\n", ev.code);
	// Left mouse button is treated as a touch
	if(ev.code == BTN_LEFT)
	{
			// Left mouse button is treated as a touch
		MouseCursor *cursor = PageManager::GetMouseCursor();
		if(ev.value == 1)
		{
			cursor->GetPos(x, y);
#ifdef _EVENT_LOGGING
				LOGERR("Mouse TOUCH_START: %d,%d\n", x, y);
#endif
				if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
					state = AS_NO_ACTION;
				else
					state = AS_IN_ACTION_AREA;
				touch_status = TS_TOUCH_AND_HOLD;
				gettimeofday(&touchStart, NULL);
			doTouchStart();
		}
		else if(touch_status)
		{
@@ -368,11 +389,8 @@ void get_input(int send_drag)
			{
				cursor->GetPos(x, y);

#ifdef _EVENT_LOGGING
					LOGERR("Mouse TOUCH_RELEASE: %d,%d\n", x, y);
#endif
				LOGEVENT("Mouse TOUCH_RELEASE: %d,%d\n", x, y);
				PageManager::NotifyTouch(TOUCH_RELEASE, x, y);

			}
			touch_status = TS_NONE;
		}
@@ -405,12 +423,12 @@ void get_input(int send_drag)
		blankTimer.resetTimerAndUnblank();
	}
}
	else if(ev.type == EV_REL)

void InputHandler::process_EV_REL(input_event& ev)
{
	// Mouse movement
#ifdef _EVENT_LOGGING
		LOGERR("EV_REL %d %d\n", ev.code, ev.value);
#endif
	MouseCursor *cursor = PageManager::GetMouseCursor();
	LOGEVENT("EV_REL %d %d\n", ev.code, ev.value);
	if(ev.code == REL_X)
		cursor->Move(ev.value, 0);
	else if(ev.code == REL_Y)
@@ -418,13 +436,24 @@ void get_input(int send_drag)

	if(touch_status) {
		cursor->GetPos(x, y);
#ifdef _EVENT_LOGGING
			LOGERR("Mouse TOUCH_DRAG: %d, %d\n", x, y);
#endif
		LOGEVENT("Mouse TOUCH_DRAG: %d, %d\n", x, y);
		key_status = KS_NONE;
	}
}
	return;

void InputHandler::handleDrag()
{
	// This allows us to only send one NotifyTouch event per render
	// cycle to reduce overhead and perceived input latency.
	static int prevx = 0, prevy = 0; // these track where the last drag notice was so that we don't send duplicate drag notices
	if (touch_status && (x != prevx || y != prevy)) {
		prevx = x;
		prevy = y;
		if (PageManager::NotifyTouch(TOUCH_DRAG, x, y) > 0)
			state = AS_NO_ACTION;
		else
			state = AS_IN_ACTION_AREA;
	}
}

static void setup_ors_command()
@@ -537,7 +566,7 @@ static void loopTimer(void)

	do
	{
		get_input(0); // get inputs but don't send drag notices
		input_handler.processInput(); // get inputs but don't send drag notices
		timespec curTime;
		clock_gettime(CLOCK_MONOTONIC, &curTime);

@@ -547,7 +576,7 @@ static void loopTimer(void)
		if (diff.tv_sec || diff.tv_nsec > 33333333)
		{
			lastCall = curTime;
			get_input(1); // send only drag notices if needed
			input_handler.handleDrag(); // send only drag notices if needed
			return;
		}

@@ -577,10 +606,6 @@ static int runPages(const char *page_name, const int stop_on_page_done)

	DataManager::SetValue("tw_loaded", 1);

#ifdef PRINT_RENDER_TIME
	timespec start, end;
	int32_t render_t, flip_t;
#endif
#ifndef TW_OEM_BUILD
	struct timeval timeout;
	fd_set fdset;
@@ -622,6 +647,8 @@ static int runPages(const char *page_name, const int stop_on_page_done)
#else
			if (ret > 1)
			{
				timespec start, end;
				int32_t render_t, flip_t;
				clock_gettime(CLOCK_MONOTONIC, &start);
				PageManager::Render();
				clock_gettime(CLOCK_MONOTONIC, &end);
@@ -856,10 +883,7 @@ extern "C" int gui_startPage(const char *page_name, const int allow_commands, in
	// Set the default package
	PageManager::SelectPackage("TWRP");

	if (!gGuiInputInit)
	{
		input_init();
	}
	input_handler.init();
#ifndef TW_OEM_BUILD
	if (allow_commands)
	{

gui/hardwarekeyboard.cpp

100755 → 100644
+1 −2
Original line number Diff line number Diff line
// hardwarekeyboard.cpp - HardwareKeyboard object
// Custom hardware keyboard support for Asus Transformer devices

#include <stdarg.h>
#include <stdio.h>