From e1753de41af9149b09fbacc6ac16515747d0b1f3 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 6 Jun 2008 18:29:46 +0000 Subject: 1) Implement generic touchscreen detection library for the plugins 2) Adapt minesweeper, pegbox & calculator to it 3) Simplify gui/bitmap/list.c git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17695 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/bitmap/list.c | 14 +---- apps/plugins/calculator.c | 34 +++++++++++ apps/plugins/lib/SOURCES | 3 + apps/plugins/lib/touchscreen.c | 133 +++++++++++++++++++++++++++++++++++++++++ apps/plugins/lib/touchscreen.h | 90 ++++++++++++++++++++++++++++ apps/plugins/minesweeper.c | 40 ++++++++++++- apps/plugins/pegbox.c | 80 +++++++++++++++++++++++++ 7 files changed, 382 insertions(+), 12 deletions(-) create mode 100644 apps/plugins/lib/touchscreen.c create mode 100644 apps/plugins/lib/touchscreen.h diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index bf0d22df32..abae87e3b5 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c @@ -344,20 +344,12 @@ unsigned gui_synclist_do_touchpad(struct gui_synclist * gui_list, struct viewpor if (y > list_text[SCREEN_MAIN].y) { int i, line_height, actual_y; + actual_y = y - list_text[SCREEN_MAIN].y; line_height = font_get(parent->font)->height; - line = -1; - for(i=0; inb_items; i++) - { - if(actual_y > line_height*i && actual_y < line_height*(i+1)) - { - line = i; - break; - } - } + line = actual_y / line_height; - /* Something went wrong during line detection... */ - if(line == -1) + if(actual_y%line_height == 0) /* Pressed a border */ return ACTION_NONE; if (line != gui_list->selected_item - gui_list->start_item[SCREEN_MAIN] && button ^ BUTTON_REL) diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c index 47facaadf4..8628d816d4 100644 --- a/apps/plugins/calculator.c +++ b/apps/plugins/calculator.c @@ -288,6 +288,9 @@ PLUGIN_HEADER #ifndef CALCULATOR_CLEAR #define CALCULATOR_CLEAR BUTTON_TOPRIGHT #endif + +#include "lib/touchscreen.h" +static struct ts_raster calc_raster = { X_0_POS, Y_1_POS, BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT }; #endif static const struct plugin_api* rb; @@ -1547,6 +1550,37 @@ enum plugin_status plugin_start(const struct plugin_api* api, const void* parame while (calStatus != cal_exit ) { btn = rb->button_get_w_tmo(HZ/2); +#ifdef HAVE_TOUCHPAD + if(btn & BUTTON_TOUCHPAD) + { + struct ts_raster_result res; + if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, &res) == 1) + { + btn_row = res.y; + btn_col = res.x; + drawButtons(buttonGroup); + drawLines(); + + rb->lcd_update(); + + prev_btn_row = btn_row; + prev_btn_col = btn_col; + if(btn & BUTTON_REL) + { + btn = CALCULATOR_INPUT; + switch(buttonGroup){ + case basicButtons: + basicButtonsProcess(); + break; + case sciButtons: + sciButtonsProcess(); + break; + } + btn = BUTTON_TOUCHPAD; + } + } + } +#endif switch (btn) { case CALCULATOR_INPUT: case CALCULATOR_CALC: diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index 58074f500c..c5c3a25e26 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES @@ -39,3 +39,6 @@ bmp_smooth_scale.c #endif pluginlib_actions.c helper.c +#ifdef HAVE_TOUCHPAD +touchscreen.c +#endif diff --git a/apps/plugins/lib/touchscreen.c b/apps/plugins/lib/touchscreen.c new file mode 100644 index 0000000000..9acee9cbe8 --- /dev/null +++ b/apps/plugins/lib/touchscreen.c @@ -0,0 +1,133 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Copyright (C) 2008 by Maurus Cuelenaere +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "plugin.h" + +#ifdef HAVE_TOUCHPAD + +#include "touchscreen.h" + +unsigned int touchscreen_map(struct ts_mappings *map, int x, int y) +{ + int i; + for(i=0; i < map->amount; i++) + { + #define _MAP(x) (map->mappings[x]) + if(x > _MAP(i).tl_x && x < (_MAP(i).tl_x+_MAP(i).width) + && y > _MAP(i).tl_y && y < (_MAP(i).tl_y+_MAP(i).height)) + return i; + } + + return -1; +} + +unsigned int touchscreen_map_raster(struct ts_raster *map, int x, int y, struct ts_raster_result *result) +{ + int res1_x, res2_x, res1_y, res2_y; + + if((x - map->tl_x) < 0 || + (x - map->tl_x) > map->width) + return -1; + res1_x = (x - map->tl_x)/(map->raster_width); + res2_x = (x - map->tl_x)%(map->raster_width); + + if((y - map->tl_y) < 0 || + (y - map->tl_y) > map->height) + return -1; + res1_y = (y - map->tl_y)/(map->raster_height); + res2_y = (y - map->tl_y)%(map->raster_height); + + if(res2_x == 0 || res2_y == 0) /* pen hit a raster boundary */ + return -2; + else + { + (*result).x = res1_x; + (*result).y = res1_y; + return 1; + } +} + +struct ts_raster_button_result touchscreen_raster_map_button(struct ts_raster_button_mapping *map, int x, int y, int button) +{ + struct ts_raster_button_result ret = {0, {0, 0}, {0, 0}}; + struct ts_raster_result tmp; + + ret.action = TS_ACTION_NONE; + if(touchscreen_map_raster(map->raster, x, y, &tmp) != 1) + return ret; + + #define NOT_HANDLED (ret.action == TS_ACTION_NONE) + if((button == BUTTON_REPEAT) && (map->_prev_btn_state != BUTTON_REPEAT) && map->drag_drop_enable) + { + map->_prev_x = tmp.x; + map->_prev_y = tmp.y; + } + if((button == BUTTON_REL) && (map->_prev_btn_state == BUTTON_REPEAT) && map->drag_drop_enable) + { + ret.action = TS_ACTION_DRAG_DROP; + ret.from.x = map->_prev_x; + ret.from.y = map->_prev_y; + ret.to.x = tmp.x; + ret.to.y = tmp.y; + } + if((button == BUTTON_REL) && map->double_click_enable && NOT_HANDLED) + { + if(map->_prev_x == tmp.x && map->_prev_y == tmp.y) + { + ret.action = TS_ACTION_DOUBLE_CLICK; + ret.from.x = ret.to.x = tmp.x; + ret.from.y = ret.to.y = tmp.y; + } + else + { + map->_prev_x = tmp.x; + map->_prev_y = tmp.y; + } + } + if((button & BUTTON_REL || button & BUTTON_REPEAT) && map->two_d_movement_enable && NOT_HANDLED) + { + if((map->two_d_from.x == tmp.x) ^ (map->two_d_from.y == tmp.y)) + { + ret.action = TS_ACTION_TWO_D_MOVEMENT; + ret.from.x = map->two_d_from.x; + ret.from.y = map->two_d_from.y; + ret.to.x = map->two_d_from.x + (map->two_d_from.x == tmp.x ? 0 : (tmp.x > map->two_d_from.x ? 1 : -1)); + ret.to.y = map->two_d_from.y + (map->two_d_from.y == tmp.y ? 0 : (tmp.y > map->two_d_from.y ? 1 : -1)); + } + else + ret.action = TS_ACTION_NONE; + } + if(map->click_enable && (button & BUTTON_REL) && NOT_HANDLED) + { + ret.action = TS_ACTION_CLICK; + ret.from.x = ret.to.x = tmp.x; + ret.from.y = ret.to.y = tmp.y; + } + if(map->move_progress_enable && NOT_HANDLED) + { + ret.action = TS_ACTION_MOVE; + ret.from.x = ret.to.x = tmp.x; + ret.from.y = ret.to.y = tmp.y; + } + + map->_prev_btn_state = button; + return ret; +} + +#endif /* HAVE_TOUCHPAD */ diff --git a/apps/plugins/lib/touchscreen.h b/apps/plugins/lib/touchscreen.h new file mode 100644 index 0000000000..e7bc0004cc --- /dev/null +++ b/apps/plugins/lib/touchscreen.h @@ -0,0 +1,90 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Copyright (C) 2008 by Maurus Cuelenaere +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#ifndef _PLUGIN_LIB_TOUCHSCREEN_H_ +#define _PLUGIN_LIB_TOUCHSCREEN_H_ + +#ifdef HAVE_TOUCHPAD + +struct ts_mapping +{ + int tl_x; /* top left */ + int tl_y; + int width; + int height; +}; + +struct ts_mappings +{ + struct ts_mapping *mappings; + int amount; +}; + +unsigned int touchscreen_map(struct ts_mappings *map, int x, int y); + +struct ts_raster +{ + int tl_x; /* top left */ + int tl_y; + int width; + int height; + int raster_width; + int raster_height; +}; + +struct ts_raster_result +{ + int x; + int y; +}; + +unsigned int touchscreen_map_raster(struct ts_raster *map, int x, int y, struct ts_raster_result *result); + +struct ts_raster_button_mapping +{ + struct ts_raster *raster; + bool drag_drop_enable; /* ... */ + bool double_click_enable; /* ... */ + bool click_enable; /* ... */ + bool move_progress_enable; /* ... */ + bool two_d_movement_enable; /* ... */ + struct ts_raster_result two_d_from; /* ... */ + int _prev_x; /* Internal: DO NOT MODIFY! */ + int _prev_y; /* Internal: DO NOT MODIFY! */ + int _prev_btn_state; /* Internal: DO NOT MODIFY! */ +}; + +struct ts_raster_button_result +{ + enum{ + TS_ACTION_NONE, + TS_ACTION_MOVE, + TS_ACTION_CLICK, + TS_ACTION_DOUBLE_CLICK, + TS_ACTION_DRAG_DROP, + TS_ACTION_TWO_D_MOVEMENT + } action; + struct ts_raster_result from; + struct ts_raster_result to; +}; + +struct ts_raster_button_result touchscreen_raster_map_button(struct ts_raster_button_mapping *map, int x, int y, int button); + +#endif /* HAVE_TOUCHPAD */ +#endif /* _PLUGIN_LIB_TOUCHSCREEN_H_ */ diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c index 7b1587ce6f..75a9330f47 100644 --- a/apps/plugins/minesweeper.c +++ b/apps/plugins/minesweeper.c @@ -303,6 +303,12 @@ int stack_pos = 0; /* a usefull string for snprintf */ char str[30]; +#ifdef HAVE_TOUCHPAD + +#include "lib/touchscreen.h" +static struct ts_raster mine_raster = { 0, 0, MAX_WIDTH, MAX_HEIGHT, TileSize, TileSize }; +#endif + void push( int *stack, int y, int x ) { @@ -477,6 +483,9 @@ void mine_show( void ) button = rb->button_get(true); while( ( button == BUTTON_NONE ) || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); +#ifdef HAVE_TOUCHPAD + button = BUTTON_NONE; +#endif } int count_tiles_left( void ) @@ -570,6 +579,13 @@ enum minesweeper_status minesweeper( void ) */ top = (LCD_HEIGHT-height*TileSize)/2; left = (LCD_WIDTH-width*TileSize)/2; + +#ifdef HAVE_TOUCHPAD + mine_raster.tl_x = left; + mine_raster.tl_y = top; + mine_raster.width = width*TileSize; + mine_raster.height = height*TileSize; +#endif rb->srand( *rb->current_tick ); minesweeper_init(); @@ -614,7 +630,29 @@ enum minesweeper_status minesweeper( void ) /* update the screen */ rb->lcd_update(); - switch( button = rb->button_get( true ) ) + button = rb->button_get(true); +#ifdef HAVE_TOUCHPAD + if(button & BUTTON_TOUCHPAD) + { + struct ts_raster_result res; + if(touchscreen_map_raster(&mine_raster, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, &res) == 1) + { + button &= ~BUTTON_TOUCHPAD; + lastbutton &= ~BUTTON_TOUCHPAD; + + if(button & BUTTON_REPEAT && lastbutton != MINESWP_TOGGLE && lastbutton ^ BUTTON_REPEAT) + button = MINESWP_TOGGLE; + else if(button == BUTTON_REL && lastbutton ^ BUTTON_REPEAT) + button = MINESWP_DISCOVER; + else + button |= BUTTON_TOUCHPAD; + + x = res.x; + y = res.y; + } + } +#endif + switch(button) { /* quit minesweeper (you really shouldn't use this button ...) */ #ifdef MINESWP_RC_QUIT diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c index ed58ac605d..f3a4f0e67c 100644 --- a/apps/plugins/pegbox.c +++ b/apps/plugins/pegbox.c @@ -368,6 +368,32 @@ PLUGIN_HEADER #define BOARD_Y 0 #endif +#ifdef HAVE_TOUCHPAD +#include "lib/touchscreen.h" + +static struct ts_mapping main_menu_items[5] = +{ +{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, +{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9), BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, +{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9)*2, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, +{(LCD_WIDTH-BMPWIDTH_pegbox_menu_items)/2, BMPHEIGHT_pegbox_menu_top+(BMPHEIGHT_pegbox_menu_items/9)*3, BMPWIDTH_pegbox_menu_items, (BMPHEIGHT_pegbox_menu_items/9)}, +{ +#if (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) +0, BMPHEIGHT_pegbox_menu_top+4*(BMPHEIGHT_pegbox_menu_items/9)+8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT +#elif LCD_WIDTH > 112 +0, LCD_HEIGHT - 8, SYSFONT_WIDTH*28, SYSFONT_HEIGHT +#else +#error "Touchpad isn't supported on non-bitmap screens!" +#endif +} + +}; +static struct ts_mappings main_menu = {main_menu_items, 5}; + +static struct ts_raster pegbox_raster = { BOARD_X, BOARD_Y, COLS*BMPWIDTH_pegbox_pieces, ROWS*BMPWIDTH_pegbox_pieces, BMPWIDTH_pegbox_pieces, BMPWIDTH_pegbox_pieces }; +static struct ts_raster_button_mapping pegbox_raster_btn = { &pegbox_raster, false, false, true, false, true, {0, 0}, 0, 0, 0 }; +#endif + struct game_context { unsigned int level; unsigned int highlevel; @@ -612,6 +638,9 @@ static void display_text(char *str, bool waitkey) key = rb->button_get(true); switch (key) { +#ifdef HAVE_TOUCHPAD + case BUTTON_TOUCHPAD: +#endif case PEGBOX_QUIT: case PEGBOX_LEFT: case PEGBOX_DOWN: @@ -738,6 +767,28 @@ static void new_piece(struct game_context* pb, unsigned int x_loc, while (!exit) { draw_board(pb); button = rb->button_get(true); +#ifdef HAVE_TOUCHPAD + if(button & BUTTON_TOUCHPAD) + { + pegbox_raster_btn.two_d_from.y = x_loc; + pegbox_raster_btn.two_d_from.x = y_loc; + + struct ts_raster_button_result ret = touchscreen_raster_map_button(&pegbox_raster_btn, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, button); + if(ret.action == TS_ACTION_TWO_D_MOVEMENT) + { + if(ret.to.x > ret.from.x) + button = PEGBOX_UP; + else if(ret.to.x < ret.from.x) + button = PEGBOX_DOWN; + else if(ret.to.y > ret.from.y) + button = PEGBOX_LEFT; + else if(ret.to.y < ret.from.y) + button = PEGBOX_RIGHT; + } + else if(ret.action == TS_ACTION_CLICK && (unsigned)ret.to.x == y_loc && (unsigned)ret.to.y == x_loc) + button = PEGBOX_SAVE; + } +#endif switch(button){ case PEGBOX_LEFT: case (PEGBOX_LEFT|BUTTON_REPEAT): @@ -1053,6 +1104,24 @@ static unsigned int pegbox_menu(struct game_context* pb) { /* handle menu button presses */ button = rb->button_get(true); + +#ifdef HAVE_TOUCHPAD + if(button & BUTTON_TOUCHPAD) + { + unsigned int result = touchscreen_map(&main_menu, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff); + if(result != (unsigned)-1 && button & BUTTON_REL) + { + if(result == 4) + button = PEGBOX_LVL_UP; + else + { + if(loc == result) + button = PEGBOX_RIGHT; + loc = result; + } + } + } +#endif switch(button) { case PEGBOX_SAVE: /* start playing */ @@ -1169,6 +1238,17 @@ static int pegbox(struct game_context* pb) { while (true) { temp_var = rb->button_get(true); +#ifdef HAVE_TOUCHPAD + if(temp_var & BUTTON_TOUCHPAD) + { + pegbox_raster_btn.two_d_from.y = pb->player_row; + pegbox_raster_btn.two_d_from.x = pb->player_col; + + struct ts_raster_button_result ret = touchscreen_raster_map_button(&pegbox_raster_btn, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, temp_var); + if(ret.action == TS_ACTION_TWO_D_MOVEMENT) + move_player(pb, ret.to.x - ret.from.x, ret.to.y - ret.from.y); + } +#endif switch(temp_var){ case PEGBOX_LEFT: /* move cursor left */ case (PEGBOX_LEFT|BUTTON_REPEAT): -- cgit v1.2.3