Touchscreen: Improved scroll threshold

Remove the hardcoded (and way too small) scroll threshold (the distance moved in pixels before we think the users wants to scroll) and replace it with something based on the actual DPI of the screen.
On Android we call the API for that, on other touchscreens we reimplemented Android's formula (as of 2.2) and calculate it.

Flyspray: 11727

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28548 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thomas Martitz 2010-11-10 15:25:15 +00:00
parent e134021e1b
commit 33af0dec28
13 changed files with 115 additions and 3 deletions

View file

@ -28,16 +28,20 @@ import org.rockbox.Helper.MediaButtonReceiver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
public class RockboxFramebuffer extends View
{
private Bitmap btm;
private ByteBuffer native_buf;
private MediaButtonReceiver media_monitor;
private final DisplayMetrics metrics;
private final ViewConfiguration view_config;
public RockboxFramebuffer(Context c, int lcd_width,
int lcd_height, ByteBuffer native_fb)
@ -53,6 +57,9 @@ public class RockboxFramebuffer extends View
media_monitor.register();
/* the service needs to know the about us */
((RockboxService)c).set_fb(this);
metrics = c.getResources().getDisplayMetrics();
view_config = ViewConfiguration.get(c);
}
public void onDraw(Canvas c)
@ -133,6 +140,18 @@ public class RockboxFramebuffer extends View
}
}
@SuppressWarnings("unused")
private int getDpi()
{
return metrics.densityDpi;
}
@SuppressWarnings("unused")
private int getScrollThreshold()
{
return view_config.getScaledTouchSlop();
}
private native void set_lcd_active(int active);
private native void touchHandler(boolean down, int x, int y);
private native boolean buttonHandler(int keycode, boolean state);

View file

@ -486,16 +486,26 @@ void _gui_synclist_stop_kinetic_scrolling(void)
* otherwise it returns true even if it didn't actually scroll,
* but scrolling mode shouldn't be changed
**/
static int scroll_begin_threshold;
static int threshold_accumulation;
static bool swipe_scroll(struct gui_synclist * gui_list, int line_height, int difference)
{
/* fixme */
const enum screen_type screen = screens[SCREEN_MAIN].screen_type;
const int nb_lines = viewport_get_nb_lines(&list_text[screen]);
if (UNLIKELY(scroll_begin_threshold == 0))
scroll_begin_threshold = touchscreen_get_scroll_threshold();
/* make selecting items easier */
if (abs(difference) < SCROLL_BEGIN_THRESHOLD && scroll_mode == SCROLL_NONE)
threshold_accumulation += abs(difference);
if (threshold_accumulation < scroll_begin_threshold && scroll_mode == SCROLL_NONE)
return false;
threshold_accumulation = 0;
/* does the list even scroll? if no, return but still show
* the caller that we would scroll */
if (nb_lines >= gui_list->nb_items)

View file

@ -25,6 +25,7 @@
#include "touchscreen.h"
#include "string.h"
#include "logf.h"
#include "lcd.h"
/* Size of the 'dead zone' around each 3x3 button */
#define BUTTON_MARGIN_X (int)(LCD_WIDTH * 0.03)
@ -167,3 +168,33 @@ enum touchscreen_mode touchscreen_get_mode(void)
{
return current_mode;
}
#if ((CONFIG_PLATFORM & PLATFORM_ANDROID) == 0)
/* android has an API for this */
#define TOUCH_SLOP 16u
#define REFERENCE_DPI 160
int touchscreen_get_scroll_threshold(void)
{
#ifdef LCD_DPI
const int dpi = LCD_DPI;
#else
const int dpi = lcd_get_dpi();
#endif
/* Inspired by Android calculation
*
* float density = real dpi / reference dpi (=160)
* int threshold = (int) (density * TOUCH_SLOP + 0.5f);(original calculation)
*
* + 0.5f is for rounding, we use fixed point math to achieve that
*/
int result = dpi * (TOUCH_SLOP<<1) / REFERENCE_DPI;
result += result & 1; /* round up if needed */
return result>>1;
}
#endif

View file

@ -75,6 +75,7 @@
/* LCD dimensions */
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
#define LCD_DPI 160
#define LCD_DEPTH 16
#define LCD_PIXELFORMAT 565

View file

@ -87,9 +87,11 @@
#if _RESOLUTION == _LCD_RES_VGA
#define LCD_NATIVE_WIDTH 480
#define LCD_NATIVE_HEIGHT 640
#define LCD_DPI 216
#else
#define LCD_NATIVE_WIDTH 240
#define LCD_NATIVE_HEIGHT 320
#define LCD_DPI 108
#endif
/* choose the lcd orientation. CONFIG_ORIENTATION defined in config.h */

View file

@ -79,6 +79,7 @@
#define LCD_WIDTH 240
#define LCD_HEIGHT 400
#endif
#define LCD_DPI 155
#define LCD_DEPTH 16 /* 16bit colours */
#define LCD_PIXELFORMAT RGB565 /* rgb565 */

View file

@ -65,8 +65,11 @@
/* LCD dimensions */
#define CONFIG_LCD LCD_ONDAVX767
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
/* this are not actually the correct dimensions (480x272 is correct)
* should be fixed once there's a working LCD driver */
#define LCD_WIDTH 480
#define LCD_HEIGHT 272
#define LCD_DPI 128
#define LCD_DEPTH 16 /* 16bit colours */
#define LCD_PIXELFORMAT RGB565 /* rgb565 */

View file

@ -73,6 +73,7 @@
#define LCD_WIDTH 240
#define LCD_HEIGHT 400
#endif
#define LCD_DPI 155
#define LCD_DEPTH 16 /* 16bit colours */
#define LCD_PIXELFORMAT RGB565 /* rgb565 */

View file

@ -19,6 +19,7 @@
#undef HAVE_ATA_POWER_OFF
#undef CONFIG_LCD
#undef LCD_DPI /* likely to be too different on a PC */
#undef CONFIG_LED

View file

@ -549,4 +549,14 @@ extern void lcd_bitmap_transparent(const fb_data *src, int x, int y,
#endif /* HAVE_LCD_BITMAP */
#ifdef HAVE_TOUCHSCREEN
/* only needed for touchscreen for now, feel free to implement it for others
* once needed
*/
/* returns the pixel density of the display */
extern int lcd_get_dpi(void);
#endif
#endif /* __LCD_H__ */

View file

@ -50,5 +50,6 @@ void touchscreen_set_mode(enum touchscreen_mode mode);
enum touchscreen_mode touchscreen_get_mode(void);
void touchscreen_disable_mapping(void);
void touchscreen_reset_mapping(void);
int touchscreen_get_scroll_threshold(void);
#endif /* __TOUCHSCREEN_INCLUDE_H_ */

View file

@ -35,6 +35,8 @@ static jmethodID java_lcd_update;
static jmethodID java_lcd_update_rect;
static bool display_on;
static int dpi;
static int scroll_threshold;
void lcd_init_device(void)
{
@ -77,6 +79,20 @@ void lcd_init_device(void)
RockboxFramebuffer_class,
"java_lcd_update_rect",
"(IIII)V");
jmethodID get_dpi = e->GetMethodID(env_ptr,
RockboxFramebuffer_class,
"getDpi", "()I");
jmethodID get_scroll_threshold
= e->GetMethodID(env_ptr,
RockboxFramebuffer_class,
"getScrollThreshold", "()I");
dpi = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance,
get_dpi);
scroll_threshold = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance,
get_scroll_threshold);
display_on = true;
}
@ -101,6 +117,16 @@ bool lcd_active(void)
return display_on;
}
int lcd_get_dpi(void)
{
return dpi;
}
int touchscreen_get_scroll_threshold(void)
{
return scroll_threshold;
}
/*
* (un)block lcd updates.
*

View file

@ -111,3 +111,9 @@ void sdl_set_gradient(SDL_Surface *surface, SDL_Color *start, SDL_Color *end,
SDL_SetPalette(surface, SDL_LOGPAL|SDL_PHYSPAL, palette, first, steps);
}
int lcd_get_dpi(void)
{
/* TODO: find a way to query it from the OS, SDL doesn't support it
* directly; for now assume the more or less standard 96 */
return 96;
}