From 69a4c42d6871ef2a88a96590dba78760a4d61ff4 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Mon, 9 Dec 2019 11:18:24 -0700 Subject: [PATCH] added the rectangle functions and a "wait for input" mechanism to the system input thread --- src/Makefile | 2 +- src/gfxtype.h | 31 +++++++++++++++++ src/msg_queue.c | 9 +++++ src/msg_queue.h | 1 + src/rect.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ src/sysinput.c | 79 +++++++++++++++++++++++++++++------------- src/sysinput.h | 1 + 7 files changed, 189 insertions(+), 25 deletions(-) create mode 100755 src/gfxtype.h create mode 100755 src/rect.c diff --git a/src/Makefile b/src/Makefile index 16b5f0c..bcc135c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ BUILDUTILS=../buildutils RESOURCES=../resources SPLASHSCREEN=splash-vmwcblk.png -OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_upiwin_tmp.o ep_util.o fbinit.o fontengine.o fbprimitive.o \ +OBJS=main.o sysinput.o ep_init.o ep_upiwin.o ep_backlight.o ep_upiwin_tmp.o ep_util.o fbinit.o rect.o fontengine.o fbprimitive.o \ log.o gpio.o msg_queue.o time_func.o config.o splash.o LIBS=-lpython3.7m -lcrypt -lfreetype -lbcm2835 -lpthread -ldl -lutil -lm CFLAGS=-I/usr/include/python3.7m -I/usr/include/freetype2 -I/usr/include/libpng16 \ diff --git a/src/gfxtype.h b/src/gfxtype.h new file mode 100755 index 0000000..e992d9e --- /dev/null +++ b/src/gfxtype.h @@ -0,0 +1,31 @@ +#ifndef __GFXTYPE_H_INCLUDED +#define __GFXTYPE_H_INCLUDED + +#include "wintype.h" + +typedef struct tagPOINT { + INT32 x; + INT32 y; +} POINT, *PPOINT; + +typedef struct tagRECT { + INT32 left; + INT32 top; + INT32 right; + INT32 bottom; +} RECT, *PRECT; + +typedef const POINT *PCPOINT; +typedef const RECT *PCRECT; + +extern BOOL G_set_rect(PRECT rect, int left, int top, int right, int bottom); +extern BOOL G_set_rect_empty(PRECT rect); +extern BOOL G_inflate_rect(PRECT rect, int dx, int dy); +extern BOOL G_offset_rect(PRECT rect, int dx, int dy); +extern BOOL G_is_rect_empty(PCRECT rect); +extern BOOL G_point_in_rect(PCRECT rect, PCPOINT pt); +extern BOOL G_rect_equal(PCRECT rect1, PCRECT rect2); +extern BOOL G_rect_intersect(PRECT dest, PCRECT src1, PCRECT src2); +extern BOOL G_rect_union(PRECT dest, PCRECT src1, PCRECT src2); + +#endif /* __GFXTYPE_H_INCLUDED */ diff --git a/src/msg_queue.c b/src/msg_queue.c index 61252ad..566dc0e 100644 --- a/src/msg_queue.c +++ b/src/msg_queue.c @@ -93,3 +93,12 @@ BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags) pthread_mutex_unlock(&(queue->mutex)); return rc; } + +BOOL Mq_is_empty(PMSG_QUEUE queue) +{ + BOOL rc; + pthread_mutex_lock(&(queue->mutex)); + rc = (queue->head == queue->tail); + pthread_mutex_unlock(&(queue->mutex)); + return rc; +} diff --git a/src/msg_queue.h b/src/msg_queue.h index 10c49ae..6ca5f75 100644 --- a/src/msg_queue.h +++ b/src/msg_queue.h @@ -26,6 +26,7 @@ extern void Mq_destroy(PMSG_QUEUE queue); extern void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *attrs, int nattrs); extern void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2); extern BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags); +extern BOOL Mq_is_empty(PMSG_QUEUE queue); #define Mq_post0(q, tgt, msg) Mq_post2(q, tgt, msg, 0, 0) #define Mq_post1(q, tgt, msg, attr) Mq_post2(q, tgt, msg, attr, 0) diff --git a/src/rect.c b/src/rect.c new file mode 100755 index 0000000..b4cc505 --- /dev/null +++ b/src/rect.c @@ -0,0 +1,91 @@ +#include +#include "log.h" +#include "gfxtype.h" + +BOOL G_set_rect(PRECT rect, int left, int top, int right, int bottom) +{ + rect->left = left; + rect->top = top; + rect->right = right; + rect->bottom = bottom; + return TRUE; +} + +BOOL G_set_rect_empty(PRECT rect) +{ + memset(rect, 0, sizeof(RECT)); + return TRUE; +} + +BOOL G_inflate_rect(PRECT rect, int dx, int dy) +{ + rect->left += dx; + rect->top += dy; + rect->right -= dx; + rect->bottom -= dy; + return TRUE; +} + +BOOL G_offset_rect(PRECT rect, int dx, int dy) +{ + rect->left += dx; + rect->top += dy; + rect->right += dx; + rect->bottom += dy; + return TRUE; +} + +BOOL G_is_rect_empty(PCRECT rect) +{ + return (rect->right <= rect.left) || (rect->bottom <= rect.top); +} + +BOOL G_point_in_rect(PCRECT rect, PCPOINT pt) +{ + return (rect->left <= pt->x) && (pt->x < rect->right) && (rect->top <= pt->y) && (pt->y < rect->bottom); +} + +BOOL G_rect_equal(PCRECT rect1, PCRECT rect2) +{ + return (memcmp(rect1, rect2, sizeof(RECT)) == 0); +} + +BOOL G_rect_intersect(PRECT dest, PCRECT src1, PCRECT src2) +{ + if (G_is_rect_empty(src1) || G_is_rect_empty(src2)) + { + memset(dest, 0, sizeof(RECT)); + return FALSE; + } + if ((src1->left >= src2->right) || (src2->left >= src1->right) || (src1->top >= src2->bottom) || (src2->top >= src1->bottom)) + { + memset(dest, 0, sizeof(RECT)); + return FALSE; + } + dest->left = MAX(src1->left, src2->left); + dest->top = MAX(src1->top, src2->top); + dest->right = MIN(src1->right, src2->right); + dest->bottom = MIN(src1->bottom, src2->bottom); + ASSERT(dest->left <= dest->right); + ASSERT(dest->top <= dest->bottom); + return TRUE; +} + +BOOL G_rect_union(PRECT dest, PCRECT src1, PCRECT src2) +{ + if (G_is_rect_empty(src1)) + { + memcpy(dest, src2, sizeof(RECT)); + return !G_is_rect_empty(src2); + } + else if (G_is_rect_empty(src2)) + { + memcpy(dest, src1, sizeof(RECT)); + return TRUE; + } + dest->left = MIN(src1->left, src2->left); + dest->top = MIN(src1->top, src2->top); + dest->right = MAX(src1->right, src2->right); + dest->bottom = MAX(src1->bottom, src2->bottom); + return TRUE; +} diff --git a/src/sysinput.c b/src/sysinput.c index 530489c..28e7864 100644 --- a/src/sysinput.c +++ b/src/sysinput.c @@ -21,6 +21,9 @@ static int ts_fd = 0; /* file descriptor for touchscreen */ static pthread_t ithread; /* input thread handle */ static volatile sig_atomic_t running = 1; /* "running" flag for input thread */ +static pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER; /* mutex for waiting on input */ +static pthread_cond_t wait_cond = PTHREAD_COND_INITIALIZER; /* condition for waiting on input */ + /* Local data for poll_buttons() */ static UINT32 last_bstate = 0; /* previous button state */ static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT]; /* timestamps to debounce events */ @@ -30,8 +33,9 @@ static UINT_PTR touch_x = 0; /* X coordinate to send with next static UINT_PTR touch_y = 0; /* Y coordinate to send with next message */ static UINT32 touch_nextmsg = WM_TOUCHMOVE; /* identifier of next message to send */ -static void poll_buttons(void) +static BOOL poll_buttons(void) { + BOOL posted = FALSE; UINT32 st, down, up, mask; UINT_PTR attr; TIMESTAMP now; @@ -46,22 +50,28 @@ static void poll_buttons(void) for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1) { if (now < button_event_ok[attr - 1]) - continue; /* this is a "contact bounce" event, don't bother */ + continue; /* this is a "contact bounce" event, don't bother */ if (up & mask) { - /* reset contact bounce timer - only seems to happen after button releases */ - button_event_ok[attr - 1] = now + Gconfig.button_debounce; - Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr); + /* reset contact bounce timer - only seems to happen after button releases */ + button_event_ok[attr - 1] = now + Gconfig.button_debounce; + Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr); + posted = TRUE; } else if (down & mask) - Mq_post1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr); + { + Mq_post1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr); + posted = TRUE; + } } last_bstate = st; } + return posted; } -static void poll_touchscreen(void) +static BOOL poll_touchscreen(void) { + BOOL posted = FALSE; int nb, nev, xerrno, i; struct input_event buffer[INPUT_EVENT_BATCH]; @@ -89,33 +99,37 @@ static void poll_touchscreen(void) switch (buffer[i].type) { case EV_SYN: - if (buffer[i].code == SYN_REPORT) - { - Mq_post2(Sys_Queue, 0, touch_nextmsg, touch_x, touch_y); - touch_nextmsg = WM_TOUCHMOVE; - } - break; + if (buffer[i].code == SYN_REPORT) + { + Mq_post2(Sys_Queue, 0, touch_nextmsg, touch_x, touch_y); + touch_nextmsg = WM_TOUCHMOVE; + posted = TRUE; + } + break; case EV_ABS: - if (buffer[i].code == ABS_X) - touch_x = buffer[i].value; - else if (buffer[i].code == ABS_Y) - touch_y = buffer[i].value; - break; + if (buffer[i].code == ABS_X) + touch_x = buffer[i].value; + else if (buffer[i].code == ABS_Y) + touch_y = buffer[i].value; + break; case EV_KEY: - if (buffer[i].code == BTN_TOUCH) - touch_nextmsg = (buffer[i].value ? WM_TOUCHDOWN : WM_TOUCHUP); - break; + if (buffer[i].code == BTN_TOUCH) + touch_nextmsg = (buffer[i].value ? WM_TOUCHDOWN : WM_TOUCHUP); + break; default: - break; + break; } } + return posted; } static void *input_thread(void *arg) { + BOOL gotinput; + /* clear all state at startup */ last_bstate = 0; memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP)); @@ -124,8 +138,14 @@ static void *input_thread(void *arg) while (running) { - poll_buttons(); - poll_touchscreen(); + gotinput = poll_buttons(); + gotinput = poll_touchscreen() || gotinput; + if (gotinput) + { + pthread_mutex_lock(&wait_mutex); + pthread_cond_signal(&wait_cond); + pthread_mutex_unlock(&wait_mutex); + } } return NULL; } @@ -178,4 +198,15 @@ HRESULT Sys_enable_input(void) do_disable_input(); } return rc; + +error_0: + return rc; +} + +void Sys_wait_for_input(void) +{ + pthread_mutex_lock(&wait_mutex); + while (Mq_is_empty(Sys_Queue)) + pthread_cond_wait(&wait_cond); + pthread_mutex_unlock(&wait_mutex); } diff --git a/src/sysinput.h b/src/sysinput.h index 8f316d0..e39c6e1 100644 --- a/src/sysinput.h +++ b/src/sysinput.h @@ -7,5 +7,6 @@ extern PMSG_QUEUE Sys_Queue; extern HRESULT Sys_enable_input(void); +extern void Sys_wait_for_input(void); #endif /* __SYSINPUT_H_INCLUDED */