2009-08-02 07:05:30 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 by Maurus Cuelenaere
|
|
|
|
* Copyright (C) 2009 by Karl Kurbjun
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "plugin.h"
|
|
|
|
|
|
|
|
#include "pluginlib_touchscreen.h"
|
2012-01-26 23:12:03 +00:00
|
|
|
#include "pluginlib_exit.h"
|
2009-08-02 07:05:30 +00:00
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Touchbutton functions: These functions allow the plugin to specify a button
|
|
|
|
* location that, in turn gets mapped to a button press return value.
|
|
|
|
******************************************************************************/
|
|
|
|
|
2012-01-26 23:12:03 +00:00
|
|
|
/* touchbutton_check_button:
|
2009-08-02 07:05:30 +00:00
|
|
|
* This function checks the touchbutton structure passed to it for hits. When
|
2012-01-26 23:12:03 +00:00
|
|
|
* one is found it returns action. It doesn't block because it doesn't actually
|
|
|
|
* call button_get. You need to call it before and pass its result.
|
2009-08-02 07:05:30 +00:00
|
|
|
* inputs:
|
|
|
|
* struct touchbutton *data: This is intended to be an array of
|
|
|
|
* touchbuttons of size num_buttons. Each element in the array defines
|
|
|
|
* one button.
|
|
|
|
* int button: This is the button return value from a button_get() call.
|
2012-01-26 23:12:03 +00:00
|
|
|
* It is used to determine REPEAT/RELEASE events. This way
|
|
|
|
* this function can be mixed with other buttons
|
2009-08-02 07:05:30 +00:00
|
|
|
* int num_buttons: This tells touchbutton_get how many elements are in
|
|
|
|
* data.
|
|
|
|
* return:
|
|
|
|
* If a touch occured over one of the defined buttons, return action, else
|
|
|
|
* return 0.
|
|
|
|
*/
|
2012-01-26 23:12:03 +00:00
|
|
|
int touchbutton_check_button(int button, struct touchbutton *data, int num_buttons) {
|
2009-08-02 07:05:30 +00:00
|
|
|
short x,y;
|
|
|
|
|
|
|
|
/* Get the x/y location of the button press, this is set by button_get when
|
|
|
|
* a button is pulled from the queue.
|
|
|
|
*/
|
|
|
|
x = rb->button_get_data() >> 16;
|
|
|
|
y = (short) rb->button_get_data();
|
|
|
|
struct viewport *v;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Loop over the data array to check if any of the buttons were pressed */
|
|
|
|
for (i=0; i<num_buttons; i++) {
|
|
|
|
v=&data[i].vp;
|
|
|
|
/* See if the point is inside the button viewport */
|
|
|
|
if( x >= v->x && x < (v->x + v->width) &&
|
|
|
|
y >= v->y && y < (v->y + v->height) ) {
|
|
|
|
if( ((button & BUTTON_REPEAT) && data[i].repeat) ||
|
|
|
|
((button & BUTTON_REL) && !data[i].repeat) ) {
|
|
|
|
return data[i].action;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-26 23:12:03 +00:00
|
|
|
/* touchbutton_get_w_tmo:
|
|
|
|
* This function checks the touchbutton structure passed to it for hits. When
|
|
|
|
* one is found it returns the corresponding action.
|
|
|
|
* inputs:
|
|
|
|
* struct touchbutton *data: This is intended to be an array of
|
|
|
|
* touchbuttons of size num_buttons. Each element in the array defines
|
|
|
|
* one button.
|
|
|
|
* int tmo: Timeout when waiting for input.
|
|
|
|
* int num_buttons: This tells touchbutton_get how many elements are in
|
|
|
|
* data.
|
|
|
|
* return:
|
|
|
|
* If a touch occured over one of the defined buttons, return action, else
|
|
|
|
* return 0.
|
|
|
|
*/
|
|
|
|
int touchbutton_get_w_tmo(int tmo, struct touchbutton *data, int num_buttons)
|
|
|
|
{
|
|
|
|
int btn = rb->button_get_w_tmo(tmo);
|
|
|
|
int result = touchbutton_check_button(btn, data, num_buttons);
|
|
|
|
exit_on_usb(result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* touchbutton_get:
|
|
|
|
* This function checks the touchbutton structure passed to it for hits. When
|
|
|
|
* one is found it returns the corresponding action.
|
|
|
|
* inputs:
|
|
|
|
* struct touchbutton *data: This is intended to be an array of
|
|
|
|
* touchbuttons of size num_buttons. Each element in the array defines
|
|
|
|
* one button.
|
|
|
|
* int num_buttons: This tells touchbutton_get how many elements are in
|
|
|
|
* data.
|
|
|
|
* return:
|
|
|
|
* If a touch occured over one of the defined buttons, return action, else
|
|
|
|
* return 0.
|
|
|
|
*/
|
|
|
|
int touchbutton_get(struct touchbutton *data, int num_buttons)
|
|
|
|
{
|
|
|
|
return touchbutton_get_w_tmo(TIMEOUT_BLOCK, data, num_buttons);
|
|
|
|
}
|
|
|
|
|
2009-08-02 07:05:30 +00:00
|
|
|
/* touchbutton_draw:
|
|
|
|
* This function draws the button with the associated text as long as the
|
|
|
|
* invisible flag is not set. Support for pixmaps needs to be added.
|
|
|
|
* inputs:
|
|
|
|
* struct touchbutton *data: This is intended to be an array of
|
|
|
|
* touchbuttons of size num_buttons. Each element in the array defines
|
|
|
|
* one button.
|
|
|
|
* int num_buttons: This tells touchbutton_get how many elements are in
|
|
|
|
* data.
|
|
|
|
* return:
|
|
|
|
* If a touch occured over one of the defined buttons, return action, else
|
|
|
|
* return 0.
|
|
|
|
*/
|
|
|
|
void touchbutton_draw(struct touchbutton *data, int num_buttons) {
|
|
|
|
int i;
|
2010-10-10 23:15:05 +00:00
|
|
|
struct screen *lcd = rb->screens[SCREEN_MAIN];
|
|
|
|
|
2009-08-02 07:05:30 +00:00
|
|
|
/* Loop over all the elements in data */
|
|
|
|
for(i=0; i<num_buttons; i++) {
|
|
|
|
/* Is this a visible button? */
|
|
|
|
if(!data[i].invisible) {
|
|
|
|
/* Set the current viewport to the button so that all drawing
|
|
|
|
* operations are within the button location.
|
|
|
|
*/
|
2010-10-10 23:15:05 +00:00
|
|
|
lcd->set_viewport(&data[i].vp);
|
2011-10-17 18:28:35 +00:00
|
|
|
|
2013-04-16 14:06:13 +00:00
|
|
|
/* TODO: Center text vert*/
|
2012-01-23 00:08:11 +00:00
|
|
|
data[i].vp.flags |= VP_FLAG_ALIGN_CENTER;
|
2009-08-02 07:05:30 +00:00
|
|
|
|
|
|
|
/* If the width offset was 0, use a scrolling puts, else center and
|
|
|
|
* print the title.
|
|
|
|
*/
|
2013-04-14 16:04:46 +00:00
|
|
|
lcd->puts_scroll(0, 0, data[i].title);
|
2009-08-02 07:05:30 +00:00
|
|
|
/* Draw bounding box around the button location. */
|
2010-10-11 01:19:55 +00:00
|
|
|
lcd->draw_border_viewport();
|
2009-08-02 07:05:30 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-10 23:15:05 +00:00
|
|
|
lcd->set_viewport(NULL); /* Go back to the default viewport */
|
2009-08-02 07:05:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Touchmap functions: Not sure how exactly these functions are used, comments
|
|
|
|
* needed!!!
|
|
|
|
******************************************************************************/
|
|
|
|
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;
|
|
|
|
}
|