#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
+#include <time.h>
+#include <unistd.h>
#include "SDL.h"
#include "SDL_audio.h"
#include "SDL_image.h"
#include "SDL_ttf.h"
#include "SDL_gfxPrimitives.h"
#include "SDL_rotozoom.h"
+#include "SDL_thread.h"
#include "pnd_conf.h"
#include "pnd_logger.h"
#include "pnd_container.h"
#include "pnd_discovery.h"
#include "pnd_apps.h"
+#include "pnd_device.h"
#include "mmenu.h"
#include "mmcat.h"
*/
SDL_Surface *sdl_realscreen = NULL;
unsigned int sdl_ticks = 0;
+SDL_Thread *g_preview_thread = NULL;
+
+enum { sdl_user_ticker = 0,
+ sdl_user_finishedpreview = 1,
+ sdl_user_finishedicon = 2,
+};
/* app state
*/
static SDL_Surface *ui_scale_image ( SDL_Surface *s, unsigned int maxwidth, int maxheight ); // height -1 means ignore
static int ui_selected_index ( void );
-static unsigned int ui_timer ( unsigned int interval ) {
- sdl_ticks++;
- return ( interval );
-}
-
unsigned char ui_setup ( void ) {
/* set up SDL
SDL_Init ( SDL_INIT_EVERYTHING | SDL_INIT_NOPARACHUTE );
- SDL_SetTimer ( 30, ui_timer ); // 30fps
-
SDL_JoystickOpen ( 0 ); // turn on joy-0
SDL_WM_SetCaption ( "mmenu", "mmenu" );
char fullpath [ PATH_MAX ];
// big font
- sprintf ( fullpath, "%s/%s", pnd_conf_get_as_char ( g_conf, MMENU_ARTPATH ), pnd_conf_get_as_char ( g_conf, "minimenu.font" ) );
+ sprintf ( fullpath, "%s/%s", g_skinpath, pnd_conf_get_as_char ( g_conf, "minimenu.font" ) );
g_big_font = TTF_OpenFont ( fullpath, pnd_conf_get_as_int_d ( g_conf, "minimenu.font_ptsize", 24 ) );
if ( ! g_big_font ) {
pnd_log ( pndn_error, "ERROR: Couldn't load font '%s' for size %u\n",
}
// grid font
- sprintf ( fullpath, "%s/%s", pnd_conf_get_as_char ( g_conf, MMENU_ARTPATH ), pnd_conf_get_as_char ( g_conf, MMENU_GRID_FONT ) );
+ sprintf ( fullpath, "%s/%s", g_skinpath, pnd_conf_get_as_char ( g_conf, MMENU_GRID_FONT ) );
g_grid_font = TTF_OpenFont ( fullpath, pnd_conf_get_as_int_d ( g_conf, MMENU_GRID_FONTSIZE, 10 ) );
if ( ! g_grid_font ) {
pnd_log ( pndn_error, "ERROR: Couldn't load font '%s' for size %u\n",
}
// detailtext font
- sprintf ( fullpath, "%s/%s", pnd_conf_get_as_char ( g_conf, MMENU_ARTPATH ), pnd_conf_get_as_char ( g_conf, "detailtext.font" ) );
+ sprintf ( fullpath, "%s/%s", g_skinpath, pnd_conf_get_as_char ( g_conf, "detailtext.font" ) );
g_detailtext_font = TTF_OpenFont ( fullpath, pnd_conf_get_as_int_d ( g_conf, "detailtext.font_ptsize", 10 ) );
if ( ! g_detailtext_font ) {
pnd_log ( pndn_error, "ERROR: Couldn't load font '%s' for size %u\n",
}
// tab font
- sprintf ( fullpath, "%s/%s", pnd_conf_get_as_char ( g_conf, MMENU_ARTPATH ), pnd_conf_get_as_char ( g_conf, "tabs.font" ) );
+ sprintf ( fullpath, "%s/%s", g_skinpath, pnd_conf_get_as_char ( g_conf, "tabs.font" ) );
g_tab_font = TTF_OpenFont ( fullpath, pnd_conf_get_as_int_d ( g_conf, "tabs.font_ptsize", 10 ) );
if ( ! g_tab_font ) {
pnd_log ( pndn_error, "ERROR: Couldn't load font '%s' for size %u\n",
{ IMG_SELECTED_ALPHAMASK, "graphics.IMG_SELECTED_ALPHAMASK" },
{ IMG_TAB_SEL, "graphics.IMG_TAB_SEL" },
{ IMG_TAB_UNSEL, "graphics.IMG_TAB_UNSEL" },
+ { IMG_TAB_LINE, "graphics.IMG_TAB_LINE" },
+ { IMG_TAB_LINEL, "graphics.IMG_TAB_LINEL" },
+ { IMG_TAB_LINER, "graphics.IMG_TAB_LINER" },
{ IMG_ICON_MISSING, "graphics.IMG_ICON_MISSING" },
{ IMG_SELECTED_HILITE, "graphics.IMG_SELECTED_HILITE" },
{ IMG_PREVIEW_MISSING, "graphics.IMG_PREVIEW_MISSING" },
unsigned int icon_offset_x = pnd_conf_get_as_int ( g_conf, "grid.icon_offset_x" );
unsigned int icon_offset_y = pnd_conf_get_as_int ( g_conf, "grid.icon_offset_y" );
+ unsigned int icon_max_width = pnd_conf_get_as_int ( g_conf, "grid.icon_max_width" );
+ unsigned int icon_max_height = pnd_conf_get_as_int ( g_conf, "grid.icon_max_height" );
unsigned int text_width = pnd_conf_get_as_int ( g_conf, "grid.text_width" );
unsigned int text_clip_x = pnd_conf_get_as_int ( g_conf, "grid.text_clip_x" );
}
#endif
+ // reset touchscreen regions
+ ui_register_reset();
+
// ensure selection is visible
if ( ui_selected ) {
dest -> w = sdl_realscreen -> w;
dest -> h = sdl_realscreen -> h;
SDL_BlitSurface ( g_imagecache [ IMG_BACKGROUND_800480 ].i, NULL /* whole image */, sdl_realscreen, dest /* 0,0 */ );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
}
dest -> w = sdl_realscreen -> w;
dest -> h = sdl_realscreen -> h;
SDL_BlitSurface ( g_imagecache [ IMG_BACKGROUND_TABMASK ].i, NULL /* whole image */, sdl_realscreen, dest /* 0,0 */ );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
}
if ( g_imagecache [ IMG_TAB_SEL ].i && g_imagecache [ IMG_TAB_UNSEL ].i ) {
unsigned int tab_width = pnd_conf_get_as_int ( g_conf, "tabs.tab_width" );
unsigned int tab_height = pnd_conf_get_as_int ( g_conf, "tabs.tab_height" );
+ unsigned int tab_selheight = pnd_conf_get_as_int ( g_conf, "tabs.tab_selheight" );
unsigned int tab_offset_x = pnd_conf_get_as_int ( g_conf, "tabs.tab_offset_x" );
unsigned int tab_offset_y = pnd_conf_get_as_int ( g_conf, "tabs.tab_offset_y" );
unsigned int text_offset_x = pnd_conf_get_as_int ( g_conf, "tabs.text_offset_x" );
unsigned int text_offset_y = pnd_conf_get_as_int ( g_conf, "tabs.text_offset_y" );
unsigned int text_width = pnd_conf_get_as_int ( g_conf, "tabs.text_width" );
+ unsigned int maxtab = ( screen_width / tab_width ) < g_categorycount ? ( screen_width / tab_width ) + ui_catshift : g_categorycount + ui_catshift;
+ // draw tabs with categories
for ( col = ui_catshift;
- col < (
- ( screen_width / tab_width ) < g_categorycount ? ( screen_width / tab_width ) + ui_catshift : g_categorycount + ui_catshift
- );
+ col < maxtab;
col++ )
{
src.x = 0;
src.y = 0;
src.w = tab_width;
- src.h = tab_height;
- dest -> x = tab_offset_x + ( col * tab_width );
+ if ( col == ui_category ) {
+ src.h = tab_selheight;
+ } else {
+ src.h = tab_height;
+ }
+ dest -> x = tab_offset_x + ( (col-ui_catshift) * tab_width );
dest -> y = tab_offset_y;
//pnd_log ( pndn_debug, "tab %u at %ux%u\n", col, dest.x, dest.y );
SDL_BlitSurface ( s, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+
+ // store touch info
+ ui_register_tab ( col, dest -> x, dest -> y, tab_width, tab_height );
+
dest++;
+ // draw tab line
+ if ( col == ui_category ) {
+ // no line for selected tab
+ } else {
+ if ( col - ui_catshift == 0 ) {
+ s = g_imagecache [ IMG_TAB_LINEL ].i;
+ } else if ( col - ui_catshift == maxtab - 1 ) {
+ s = g_imagecache [ IMG_TAB_LINER ].i;
+ } else {
+ s = g_imagecache [ IMG_TAB_LINE ].i;
+ }
+ dest -> x = tab_offset_x + ( (col-ui_catshift) * tab_width );
+ dest -> y = tab_offset_y + tab_height;
+ SDL_BlitSurface ( s, NULL /* whole image */, sdl_realscreen, dest );
+ dest++;
+ }
+
// draw text
SDL_Surface *rtext;
SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
src.y = 0;
src.w = rtext -> w < text_width ? rtext -> w : text_width;
src.h = rtext -> h;
- dest -> x = tab_offset_x + ( col * tab_width ) + text_offset_x;
+ dest -> x = tab_offset_x + ( (col-ui_catshift) * tab_width ) + text_offset_x;
dest -> y = tab_offset_y + text_offset_y;
SDL_BlitSurface ( rtext, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+
+ } // for
+
+ // draw tab lines under where tabs would be if we had categories
+ maxtab = ( screen_width / tab_width );
+ for ( /* foo */; col < maxtab; col++ ) {
+ SDL_Surface *s;
+
+ if ( col - ui_catshift == 0 ) {
+ s = g_imagecache [ IMG_TAB_LINEL ].i;
+ } else if ( col - ui_catshift == maxtab - 1 ) {
+ s = g_imagecache [ IMG_TAB_LINER ].i;
+ } else {
+ s = g_imagecache [ IMG_TAB_LINE ].i;
+ }
+ dest -> x = tab_offset_x + ( (col-ui_catshift) * tab_width );
+ dest -> y = tab_offset_y + tab_height;
+ SDL_BlitSurface ( s, NULL /* whole image */, sdl_realscreen, dest );
dest++;
} // for
dest -> x = pnd_conf_get_as_int_d ( g_conf, "grid.arrow_up_x", 450 );
dest -> y = pnd_conf_get_as_int_d ( g_conf, "grid.arrow_up_y", 80 );
SDL_BlitSurface ( g_imagecache [ IMG_ARROW_UP ].i, NULL /* whole image */, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
show_bar = 1;
dest -> x = pnd_conf_get_as_int_d ( g_conf, "grid.arrow_down_x", 450 );
dest -> y = pnd_conf_get_as_int_d ( g_conf, "grid.arrow_down_y", 80 );
SDL_BlitSurface ( g_imagecache [ IMG_ARROW_DOWN ].i, NULL /* whole image */, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
show_bar = 1;
dest -> x = pnd_conf_get_as_int_d ( g_conf, "grid.arrow_bar_x", 450 );
dest -> y = pnd_conf_get_as_int_d ( g_conf, "grid.arrow_bar_y", 100 );
SDL_BlitSurface ( g_imagecache [ IMG_ARROW_SCROLLBAR ].i, &src /* whole image */, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
} // bar
dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 );
dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 );
SDL_BlitSurface ( g_imagecache [ IMG_DETAIL_BG ].i, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
}
dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 );
dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 );
SDL_BlitSurface ( g_imagecache [ IMG_DETAIL_PANEL ].i, NULL /* whole image */, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
}
dest -> x = grid_offset_x + ( col * cell_width ) + icon_offset_x;
dest -> y = grid_offset_y + ( displayrow * cell_height ) + icon_offset_y;
SDL_BlitSurface ( g_imagecache [ IMG_SELECTED_ALPHAMASK ].i, NULL /* all */, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
// text
dest -> x = grid_offset_x + ( col * cell_width ) + text_clip_x;
dest -> y = grid_offset_y + ( displayrow * cell_height ) + pnd_conf_get_as_int ( g_conf, "grid.text_hilite_offset_y" );
SDL_BlitSurface ( g_imagecache [ IMG_SELECTED_HILITE ].i, NULL /* all */, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
} // selected?
src.y = 0;
src.w = 60;
src.h = 60;
- dest -> x = grid_offset_x + ( col * cell_width ) + icon_offset_x;
- dest -> y = grid_offset_y + ( displayrow * cell_height ) + icon_offset_y;
+ dest -> x = grid_offset_x + ( col * cell_width ) + icon_offset_x + (( icon_max_width - iconsurface -> w ) / 2);
+ dest -> y = grid_offset_y + ( displayrow * cell_height ) + icon_offset_y + (( icon_max_height - iconsurface -> h ) / 2);
SDL_BlitSurface ( iconsurface, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+
+ // store touch info
+ ui_register_app ( appiter, dest -> x, dest -> y, src.w, src.h );
+
dest++;
}
}
dest -> y = grid_offset_y + ( displayrow * cell_height ) + text_offset_y;
SDL_BlitSurface ( rtext, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ SDL_FreeSurface ( rtext );
dest++;
}
dest -> x = cell_offset_x;
dest -> y = desty;
SDL_BlitSurface ( rtext, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ SDL_FreeSurface ( rtext );
dest++;
desty += src.h;
}
dest -> x = cell_offset_x;
dest -> y = desty;
SDL_BlitSurface ( rtext, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ SDL_FreeSurface ( rtext );
dest++;
desty += src.h;
}
dest -> x = cell_offset_x;
dest -> y = desty;
SDL_BlitSurface ( rtext, &src, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+ desty += src.h;
+ }
+
+ // show sub-app# on right side of cpu clock?
+ //if ( ui_selected -> ref -> subapp_number )
+ {
+ sprintf ( buffer, "(app#%u)", ui_selected -> ref -> subapp_number );
+
+ SDL_Surface *rtext;
+ SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
+ rtext = TTF_RenderText_Blended ( g_grid_font, buffer, tmpfontcolor );
+ dest -> x = cell_offset_x + cell_width - rtext -> w;
+ dest -> y = desty - src.h;
+ SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+ }
+
+ // info hint
+ if ( ui_selected -> ref -> clockspeed && ui_selected -> ref -> info_filename ) {
+
+ sprintf ( buffer, "Documentation - hit Y" );
+
+ SDL_Surface *rtext;
+ SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
+ rtext = TTF_RenderText_Blended ( g_detailtext_font, buffer, tmpfontcolor );
+ src.x = 0;
+ src.y = 0;
+ src.w = rtext -> w < cell_width ? rtext -> w : cell_width;
+ src.h = rtext -> h;
+ dest -> x = cell_offset_x;
+ dest -> y = desty;
+ SDL_BlitSurface ( rtext, &src, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
dest++;
desty += src.h;
}
( ( pnd_conf_get_as_int_d ( g_conf, "previewpic.cell_width", 50 ) - previewpic -> w ) / 2 );
dest -> y = pnd_conf_get_as_int_d ( g_conf, "previewpic.cell_offset_y", 50 );
SDL_BlitSurface ( previewpic, NULL /* whole image */, sdl_realscreen, dest );
- //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
dest++;
}
} // selected?
+ // extras
+ //
+
+ // battery
+ if ( 1 ) {
+ static int last_battlevel = 0;
+ static unsigned char batterylevel = 0;
+ char buffer [ 100 ];
+
+ if ( time ( NULL ) - last_battlevel > 60 ) {
+ batterylevel = pnd_device_get_battery_gauge_perc();
+ last_battlevel = time ( NULL );
+ }
+
+ sprintf ( buffer, "Battery: %u%%", batterylevel );
+
+ SDL_Surface *rtext;
+ SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
+ rtext = TTF_RenderText_Blended ( g_grid_font, buffer, tmpfontcolor );
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "display.battery_x", 20 );
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "display.battery_y", 450 );
+ SDL_BlitSurface ( rtext, NULL /* all */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+ }
+
+ // hints
+ if ( pnd_conf_get_as_char ( g_conf, "display.hintline" ) ) {
+ char *buffer = pnd_conf_get_as_char ( g_conf, "display.hintline" );
+ SDL_Surface *rtext;
+ SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
+ rtext = TTF_RenderText_Blended ( g_grid_font, buffer, tmpfontcolor );
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "display.hint_x", 40 );
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "display.hint_y", 450 );
+ SDL_BlitSurface ( rtext, NULL /* all */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+ }
+
+ // hints
+ if ( pnd_conf_get_as_int_d ( g_conf, "display.clock_x", -1 ) != -1 ) {
+ char buffer [ 50 ];
+
+ time_t t = time ( NULL );
+ struct tm *tm = localtime ( &t );
+ strftime ( buffer, 50, "%a %H:%M %F", tm );
+
+ SDL_Surface *rtext;
+ SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
+ rtext = TTF_RenderText_Blended ( g_grid_font, buffer, tmpfontcolor );
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "display.clock_x", 700 );
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "display.clock_y", 450 );
+ SDL_BlitSurface ( rtext, NULL /* all */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+ }
+
// update all the rects and send it all to sdl
SDL_UpdateRects ( sdl_realscreen, dest - rects, rects );
SDL_Event event;
unsigned char ui_event = 0; // if we get a ui event, flip to 1 and break
- static ui_sdl_button_e ui_mask = uisb_none; // current buttons down
+ //static ui_sdl_button_e ui_mask = uisb_none; // current buttons down
while ( ! ui_event &&
block_p ? SDL_WaitEvent ( &event ) : SDL_PollEvent ( &event ) )
switch ( event.type ) {
+ case SDL_USEREVENT:
+ // update something
+
+ if ( event.user.code == sdl_user_ticker ) {
+
+ // timer went off, time to load something
+ if ( pnd_conf_get_as_int_d ( g_conf, "minimenu.load_previews_later", 0 ) ) {
+
+ pnd_log ( pndn_debug, "Deferred preview pic load ----------\n" );
+
+ // load the preview pics now!
+ pnd_disco_t *iter = ui_selected -> ref;
+
+ if ( iter -> preview_pic1 ) {
+
+ if ( pnd_conf_get_as_int_d ( g_conf, "minimenu.threaded_preview", 0 ) ) {
+
+ g_preview_thread = SDL_CreateThread ( (void*)ui_threaded_defered_preview, iter );
+
+ if ( ! g_preview_thread ) {
+ pnd_log ( pndn_error, "ERROR: Couldn't create preview thread\n" );
+ }
+
+ } else {
+
+ if ( ! cache_preview ( iter, pnd_conf_get_as_int_d ( g_conf, "previewpic.cell_width", 200 ),
+ pnd_conf_get_as_int_d ( g_conf, "previewpic.cell_height", 180 ) )
+ )
+ {
+ pnd_log ( pndn_debug, " Couldn't load preview pic: '%s' -> '%s'\n",
+ IFNULL(iter->title_en,"No Name"), iter -> preview_pic1 );
+ }
+
+ } // threaded?
+
+ } // got a preview at all?
+
+ pnd_log ( pndn_debug, "Deferred preview pic load finish ---\n" );
+
+ ui_event++;
+ }
+
+ } else if ( event.user.code == sdl_user_finishedpreview ) {
+
+ // if we just finished the one we happen to be looking at, better redraw now; otherwise, if
+ // we finished another, no big woop
+ if ( ui_selected && event.user.data1 == ui_selected -> ref ) {
+ ui_event++;
+ }
+
+ } else if ( event.user.code == sdl_user_finishedicon ) {
+ // redraw, so we can show the newly loaded icon
+ ui_event++;
+
+ }
+
+ break;
+
#if 0 // joystick motion
case SDL_JOYAXISMOTION:
if ( event.jaxis.axis == 0 ) {
// horiz
if ( event.jaxis.value < 0 ) {
- ui_push_left();
+ ui_push_left ( 0 );
pnd_log ( PND_LOG_DEFAULT, "joystick axis - LEFT\n" );
} else if ( event.jaxis.value > 0 ) {
- ui_push_right();
+ ui_push_right ( 0 );
pnd_log ( PND_LOG_DEFAULT, "joystick axis - RIGHT\n" );
}
} else if ( event.jaxis.axis == 1 ) {
//pnd_log ( pndn_debug, "key up %u\n", event.key.keysym.sym );
+ // SDLK_LALT -> Start
+
// directional
if ( event.key.keysym.sym == SDLK_RIGHT ) {
- ui_push_right();
+ ui_push_right ( 0 );
ui_event++;
} else if ( event.key.keysym.sym == SDLK_LEFT ) {
- ui_push_left();
+ ui_push_left ( 0 );
ui_event++;
} else if ( event.key.keysym.sym == SDLK_UP ) {
ui_push_up();
ui_event++;
} else if ( event.key.keysym.sym == SDLK_x || event.key.keysym.sym == SDLK_RCTRL ) {
ui_push_rtrigger();
+ ui_event++;
+ } else if ( event.key.keysym.sym == SDLK_y || event.key.keysym.sym == SDLK_PAGEUP ) {
+ // info
+ if ( ui_selected ) {
+ ui_show_info ( pnd_run_script, ui_selected -> ref );
+ ui_event++;
+ }
+
+ } else if ( event.key.keysym.sym == SDLK_LALT ) { // start button
+ ui_push_exec();
+ ui_event++;
+
+ } else if ( event.key.keysym.sym == SDLK_LCTRL /*LALT*/ ) { // select button
+ char *opts [ 20 ] = {
+ "Return to Minimenu",
+ "Shutdown Pandora",
+ "Rescan for Applications",
+ "Run xfce4 from Minimenu",
+ "Run a terminal/console",
+ "Exit and run xfce4",
+ "Exit and run pmenu",
+ "Quit (<- beware)",
+ "About Minimenu"
+ };
+ int sel = ui_modal_single_menu ( opts, 9, "Minimenu", "Enter to select; other to return." );
+
+ char buffer [ 100 ];
+ if ( sel == 0 ) {
+ // do nothing
+ } else if ( sel == 1 ) {
+ // shutdown
+ sprintf ( buffer, "sudo poweroff" );
+ system ( buffer );
+ } else if ( sel == 2 ) {
+ // rescan apps
+ pnd_log ( pndn_debug, "Freeing up applications\n" );
+ applications_free();
+ pnd_log ( pndn_debug, "Rescanning applications\n" );
+ applications_scan();
+ // reset view
+ ui_selected = NULL;
+ ui_rows_scrolled_down = 0;
+ } else if ( sel == 3 ) {
+ // run xfce
+ char buffer [ PATH_MAX ];
+ sprintf ( buffer, "%s %s\n", MM_RUN, "/usr/bin/startxfce4" );
+ emit_and_quit ( buffer );
+ } else if ( sel == 4 ) {
+ // run terminal
+ char *argv[5];
+ argv [ 0 ] = pnd_conf_get_as_char ( g_conf, "utility.terminal" );
+ argv [ 1 ] = NULL;
+
+ if ( argv [ 0 ] ) {
+ ui_forkexec ( argv );
+ }
+
+ } else if ( sel == 5 ) {
+ // set env to xfce
+ sprintf ( buffer, "echo startxfce4 > /tmp/gui.load" );
+ system ( buffer );
+ //sprintf ( buffer, "sudo poweroff" );
+ //system ( buffer );
+ exit ( 0 );
+ } else if ( sel == 6 ) {
+ // set env to pmenu
+ sprintf ( buffer, "echo pmenu > /tmp/gui.load" );
+ system ( buffer );
+ //sprintf ( buffer, "sudo poweroff" );
+ //system ( buffer );
+ exit ( 0 );
+ } else if ( sel == 7 ) {
+ emit_and_quit ( MM_QUIT );
+ } else if ( sel == 8 ) {
+ // about
+ }
+
ui_event++;
}
break;
#endif
-#if 0 // mouse / touchscreen
+#if 1 // mouse / touchscreen
+#if 0
case SDL_MOUSEBUTTONDOWN:
if ( event.button.button == SDL_BUTTON_LEFT ) {
cb_pointer_press ( gc, event.button.x / g_scale, event.button.y / g_scale );
ui_event++;
}
break;
+#endif
case SDL_MOUSEBUTTONUP:
if ( event.button.button == SDL_BUTTON_LEFT ) {
- cb_pointer_release ( gc, event.button.x / g_scale, event.button.y / g_scale );
- retval |= STAT_pen;
+ ui_touch_act ( event.button.x, event.button.y );
ui_event++;
}
break;
return;
}
-void ui_push_left ( void ) {
+void ui_push_left ( unsigned char forcecoil ) {
if ( ! ui_selected ) {
- ui_push_right();
+ ui_push_right ( 0 );
return;
}
+ // what column we in?
+ unsigned int col = ui_determine_screen_col ( ui_selected );
+
// are we alreadt at first item?
- if ( g_categories [ ui_category ].refs == ui_selected ) {
+ if ( forcecoil == 0 &&
+ pnd_conf_get_as_int_d ( g_conf, "grid.wrap_horiz_samerow", 0 ) &&
+ col == 0 )
+ {
+ unsigned int i = pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1;
+ while ( i ) {
+ ui_push_right ( 0 );
+ i--;
+ }
+
+ } else if ( g_categories [ ui_category ].refs == ui_selected ) {
// can't go any more left, we're at the head
+
} else {
// figure out the previous item; yay for singly linked list :/
mm_appref_t *i = g_categories [ ui_category ].refs;
}
}
+ ui_set_selected ( ui_selected );
+
return;
}
-void ui_push_right ( void ) {
+void ui_push_right ( unsigned char forcecoil ) {
if ( ui_selected ) {
- if ( ui_selected -> next ) {
- ui_selected = ui_selected -> next;
+ // what column we in?
+ unsigned int col = ui_determine_screen_col ( ui_selected );
+
+ // wrap same or no?
+ if ( forcecoil == 0 &&
+ pnd_conf_get_as_int_d ( g_conf, "grid.wrap_horiz_samerow", 0 ) &&
+ col == pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1 )
+ {
+ // same wrap
+ unsigned int i = pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1;
+ while ( i ) {
+ ui_push_left ( 0 );
+ i--;
+ }
+
+ } else {
+ // just go to the next
+
+ if ( ui_selected -> next ) {
+ ui_selected = ui_selected -> next;
+ }
+
}
} else {
ui_selected = g_categories [ ui_category ].refs;
}
+ ui_set_selected ( ui_selected );
+
return;
}
void ui_push_up ( void ) {
unsigned char col_max = pnd_conf_get_as_int ( g_conf, MMENU_DISP_COLMAX );
- while ( col_max ) {
- ui_push_left();
- col_max--;
+ if ( ! ui_selected ) {
+ return;
+ }
+
+ // what row we in?
+ unsigned int row = ui_determine_row ( ui_selected );
+
+ if ( row == 0 &&
+ pnd_conf_get_as_int_d ( g_conf, "grid.wrap_vert_stop", 1 ) == 0 )
+ {
+ // wrap around instead
+
+ unsigned int col = ui_determine_screen_col ( ui_selected );
+
+ // go to end
+ ui_selected = g_categories [ ui_category ].refs;
+ while ( ui_selected -> next ) {
+ ui_selected = ui_selected -> next;
+ }
+
+ // try to move to same column
+ unsigned int newcol = ui_determine_screen_col ( ui_selected );
+ if ( newcol > col ) {
+ col = newcol - col;
+ while ( col ) {
+ ui_push_left ( 0 );
+ col--;
+ }
+ }
+
+ // scroll down to show it
+ int r = ui_determine_row ( ui_selected ) - 1;
+ if ( r - pnd_conf_get_as_int ( g_conf, MMENU_DISP_ROWMAX ) > 0 ) {
+ ui_rows_scrolled_down = (unsigned int) r;
+ }
+
+ } else {
+ // stop at top/bottom
+
+ while ( col_max ) {
+ ui_push_left ( 1 );
+ col_max--;
+ }
+
}
return;
unsigned char col_max = pnd_conf_get_as_int ( g_conf, MMENU_DISP_COLMAX );
if ( ui_selected ) {
- while ( col_max ) {
- ui_push_right();
- col_max--;
+
+ // what row we in?
+ unsigned int row = ui_determine_row ( ui_selected );
+
+ // max rows?
+ unsigned int icon_rows = g_categories [ ui_category ].refcount / col_max;
+ if ( g_categories [ ui_category ].refcount % col_max > 0 ) {
+ icon_rows++;
+ }
+
+ // we at the end?
+ if ( row == ( icon_rows - 1 ) &&
+ pnd_conf_get_as_int_d ( g_conf, "grid.wrap_vert_stop", 1 ) == 0 )
+ {
+
+ unsigned char col = ui_determine_screen_col ( ui_selected );
+
+ ui_selected = g_categories [ ui_category ].refs;
+
+ while ( col ) {
+ ui_selected = ui_selected -> next;
+ col--;
+ }
+
+ ui_rows_scrolled_down = 0;
+
+ } else {
+
+ while ( col_max ) {
+ ui_push_right ( 1 );
+ col_max--;
+ }
+
}
+
} else {
- ui_push_right();
+ ui_push_right ( 0 );
}
return;
if ( oldcat != ui_category ) {
ui_selected = NULL;
+ ui_set_selected ( ui_selected );
}
+ // make tab visible?
+ if ( ui_catshift > 0 && ui_category == ui_catshift - 1 ) {
+ ui_catshift--;
+ }
+
+ // unscroll
+ ui_rows_scrolled_down = 0;
+
return;
}
void ui_push_rtrigger ( void ) {
unsigned char oldcat = ui_category;
+ unsigned int screen_width = pnd_conf_get_as_int_d ( g_conf, "display.screen_width", 800 );
+ unsigned int tab_width = pnd_conf_get_as_int ( g_conf, "tabs.tab_width" );
+
if ( ui_category < ( g_categorycount - 1 ) ) {
ui_category++;
} else {
if ( oldcat != ui_category ) {
ui_selected = NULL;
+ ui_set_selected ( ui_selected );
+ }
+
+ // make tab visible?
+ if ( ui_category > ui_catshift + ( screen_width / tab_width ) - 1 ) {
+ ui_catshift++;
}
+ // unscroll
+ ui_rows_scrolled_down = 0;
+
return;
}
}
- pnd_log ( pndn_debug, " Upscaling; scale factor %f\n", scale );
scaled = rotozoomSurface ( s, 0 /* angle*/, scale /* scale */, 1 /* smooth==1*/ );
SDL_FreeSurface ( s );
s = scaled;
dest.y = 20;
SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, &dest );
SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ SDL_FreeSurface ( rtext );
return;
}
}
SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, &dest );
SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ SDL_FreeSurface ( rtext );
// render icon
if ( g_imagecache [ IMG_ICON_MISSING ].i ) {
SDL_Rect rects [ 4 ];
SDL_Rect *dest = rects;
+ SDL_Rect src;
bzero ( dest, sizeof(SDL_Rect)* 4 );
unsigned int font_rgba_r = pnd_conf_get_as_int_d ( g_conf, "display.font_rgba_r", 200 );
dest++;
}
- }
+ } else {
+
+ // render background
+ if ( g_imagecache [ IMG_BACKGROUND_800480 ].i ) {
+ src.x = 0;
+ src.y = 0;
+ src.w = sdl_realscreen -> w;
+ src.h = 100;
+ dest -> x = 0;
+ dest -> y = 0;
+ dest -> w = sdl_realscreen -> w;
+ dest -> h = sdl_realscreen -> h;
+ SDL_BlitSurface ( g_imagecache [ IMG_BACKGROUND_800480 ].i, &src, sdl_realscreen, dest );
+ dest++;
+ }
+
+ } // clear it
// render text
SDL_Surface *rtext;
SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
rtext = TTF_RenderText_Blended ( g_big_font, "Caching applications artwork...", tmpfontcolor );
- if ( clearscreen ) {
- dest -> x = 20;
- dest -> y = 20;
- } else {
- dest -> x = 20;
- dest -> y = 40;
- }
+ dest -> x = 20;
+ dest -> y = 20;
SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
dest++;
// render icon
dest -> x = 20;
dest -> y = 50;
SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
dest++;
}
return ( -1 );
}
+
+static mm_appref_t *timer_ref = NULL;
+void ui_set_selected ( mm_appref_t *r ) {
+
+ if ( ! pnd_conf_get_as_int_d ( g_conf, "minimenu.load_previews_later", 0 ) ) {
+ return; // no desire to defer anything
+ }
+
+ if ( ! r ) {
+ // cancel timer
+ SDL_SetTimer ( 0, NULL );
+ timer_ref = NULL;
+ return;
+ }
+
+ SDL_SetTimer ( pnd_conf_get_as_int_d ( g_conf, "previewpic.defer_timer_ms", 1000 ), ui_callback_f );
+ timer_ref = r;
+
+ return;
+}
+
+unsigned int ui_callback_f ( unsigned int t ) {
+
+ if ( ui_selected != timer_ref ) {
+ return ( 0 ); // user has moved it, who cares
+ }
+
+ SDL_Event e;
+ bzero ( &e, sizeof(SDL_Event) );
+ e.type = SDL_USEREVENT;
+ e.user.code = sdl_user_ticker;
+ SDL_PushEvent ( &e );
+
+ return ( 0 );
+}
+
+int ui_modal_single_menu ( char *argv[], unsigned int argc, char *title, char *footer ) {
+ SDL_Rect rects [ 40 ];
+ SDL_Rect *dest = rects;
+ SDL_Rect src;
+ SDL_Surface *rtext;
+
+ bzero ( rects, sizeof(SDL_Rect) * 40 );
+
+ unsigned int sel = 0;
+
+ unsigned int font_rgba_r = pnd_conf_get_as_int_d ( g_conf, "display.font_rgba_r", 200 );
+ unsigned int font_rgba_g = pnd_conf_get_as_int_d ( g_conf, "display.font_rgba_g", 200 );
+ unsigned int font_rgba_b = pnd_conf_get_as_int_d ( g_conf, "display.font_rgba_b", 200 );
+ unsigned int font_rgba_a = pnd_conf_get_as_int_d ( g_conf, "display.font_rgba_a", 100 );
+
+ SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
+
+ SDL_Color selfontcolor = { 0/*font_rgba_r*/, font_rgba_g, font_rgba_b, font_rgba_a };
+
+ unsigned int i;
+ SDL_Event event;
+
+ while ( 1 ) {
+
+ // clear
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 );
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 );
+ dest -> w = ((SDL_Surface*) g_imagecache [ IMG_DETAIL_PANEL ].i) -> w;
+ dest -> h = ((SDL_Surface*) g_imagecache [ IMG_DETAIL_PANEL ].i) -> h;
+ SDL_FillRect( sdl_realscreen, dest, 0 );
+
+ // show dialog background
+ if ( g_imagecache [ IMG_DETAIL_BG ].i ) {
+ src.x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 );
+ src.y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 );
+ src.w = ((SDL_Surface*)(g_imagecache [ IMG_DETAIL_PANEL ].i)) -> w;
+ src.h = ((SDL_Surface*)(g_imagecache [ IMG_DETAIL_PANEL ].i)) -> h;
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 );
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 );
+ SDL_BlitSurface ( g_imagecache [ IMG_DETAIL_BG ].i, &src, sdl_realscreen, dest );
+ // repeat for darken?
+ SDL_BlitSurface ( g_imagecache [ IMG_DETAIL_BG ].i, &src, sdl_realscreen, dest );
+ SDL_BlitSurface ( g_imagecache [ IMG_DETAIL_BG ].i, &src, sdl_realscreen, dest );
+ //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ dest++;
+ }
+
+ // show dialog frame
+ if ( g_imagecache [ IMG_DETAIL_PANEL ].i ) {
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 );
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 );
+ SDL_BlitSurface ( g_imagecache [ IMG_DETAIL_PANEL ].i, NULL /* whole image */, sdl_realscreen, dest );
+ //SDL_UpdateRects ( sdl_realscreen, 1, &dest );
+ dest++;
+ }
+
+ // show header
+ if ( title ) {
+ rtext = TTF_RenderText_Blended ( g_tab_font, title, tmpfontcolor );
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 ) + 20;
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 ) + 20;
+ SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+ }
+
+ // show footer
+ if ( footer ) {
+ rtext = TTF_RenderText_Blended ( g_tab_font, footer, tmpfontcolor );
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 ) + 20;
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 ) +
+ ((SDL_Surface*) g_imagecache [ IMG_DETAIL_PANEL ].i) -> h
+ - 60;
+ SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+ }
+
+ // show options
+ for ( i = 0; i < argc; i++ ) {
+
+ // show options
+ if ( sel == i ) {
+ rtext = TTF_RenderText_Blended ( g_tab_font, argv [ i ], selfontcolor );
+ } else {
+ rtext = TTF_RenderText_Blended ( g_tab_font, argv [ i ], tmpfontcolor );
+ }
+ dest -> x = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_x", 460 ) + 20;
+ dest -> y = pnd_conf_get_as_int_d ( g_conf, "detailpane.pane_offset_y", 60 ) + 40 + ( 20 * ( i + 1 ) );
+ SDL_BlitSurface ( rtext, NULL /* full src */, sdl_realscreen, dest );
+ SDL_FreeSurface ( rtext );
+ dest++;
+
+ } // for
+
+ // update all the rects and send it all to sdl
+ SDL_UpdateRects ( sdl_realscreen, dest - rects, rects );
+ dest = rects;
+
+ // check for input
+ while ( SDL_WaitEvent ( &event ) ) {
+
+ switch ( event.type ) {
+
+ case SDL_KEYUP:
+
+ if ( event.key.keysym.sym == SDLK_UP ) {
+ if ( sel ) {
+ sel--;
+ }
+ } else if ( event.key.keysym.sym == SDLK_DOWN ) {
+ if ( sel < argc - 1 ) {
+ sel++;
+ }
+
+ } else if ( event.key.keysym.sym == SDLK_RETURN ) {
+ return ( sel );
+
+ } else if ( event.key.keysym.sym == SDLK_q ) {
+ exit ( 0 );
+
+ } else {
+ return ( -1 ); // nada
+ }
+
+ break;
+
+ } // switch
+
+ break;
+ } // while
+
+ } // while
+
+ return ( -1 );
+}
+
+unsigned char ui_determine_row ( mm_appref_t *a ) {
+ unsigned int row = 0;
+
+ mm_appref_t *i = g_categories [ ui_category ].refs;
+ while ( i != a ) {
+ i = i -> next;
+ row++;
+ } // while
+ row /= pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 );
+
+ return ( row );
+}
+
+unsigned char ui_determine_screen_row ( mm_appref_t *a ) {
+ return ( ui_determine_row ( a ) % pnd_conf_get_as_int_d ( g_conf, "grid.row_max", 5 ) );
+}
+
+unsigned char ui_determine_screen_col ( mm_appref_t *a ) {
+ unsigned int col = 0;
+
+ mm_appref_t *i = g_categories [ ui_category ].refs;
+ while ( i != a ) {
+ i = i -> next;
+ col++;
+ } // while
+ col %= pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 );
+
+ return ( col );
+}
+
+unsigned char ui_show_info ( char *pndrun, pnd_disco_t *p ) {
+ char *viewer, *searchpath;
+ pnd_conf_handle desktoph;
+
+ // viewer
+ searchpath = pnd_conf_query_searchpath();
+
+ desktoph = pnd_conf_fetch_by_id ( pnd_conf_desktop, searchpath );
+
+ if ( ! desktoph ) {
+ return ( 0 );
+ }
+
+ viewer = pnd_conf_get_as_char ( desktoph, "info.viewer" );
+
+ if ( ! viewer ) {
+ return ( 0 ); // no way to view the file
+ }
+
+ // etc
+ if ( ! p -> unique_id ) {
+ return ( 0 );
+ }
+
+ if ( ! p -> info_filename ) {
+ return ( 0 );
+ }
+
+ if ( ! p -> info_name ) {
+ return ( 0 );
+ }
+
+ if ( ! pndrun ) {
+ return ( 0 );
+ }
+
+ // exec line
+ char args [ 1001 ];
+ char *pargs = args;
+ if ( pnd_conf_get_as_char ( desktoph, "info.viewer_args" ) ) {
+ snprintf ( pargs, 1001, "%s %s",
+ pnd_conf_get_as_char ( desktoph, "info.viewer_args" ), p -> info_filename );
+ } else {
+ pargs = NULL;
+ }
+
+ char pndfile [ 1024 ];
+ if ( p -> object_type == pnd_object_type_directory ) {
+ // for PXML-app-dir, pnd_run.sh doesn't want the PXML.xml.. it just wants the dir-name
+ strncpy ( pndfile, p -> object_path, 1000 );
+ } else if ( p -> object_type == pnd_object_type_pnd ) {
+ // pnd_run.sh wants the full path and filename for the .pnd file
+ snprintf ( pndfile, 1020, "%s/%s", p -> object_path, p -> object_filename );
+ }
+
+ if ( ! pnd_apps_exec ( pndrun, pndfile, p -> unique_id, viewer, p -> startdir, pargs,
+ p -> clockspeed ? atoi ( p -> clockspeed ) : 0, PND_EXEC_OPTION_NORUN ) )
+ {
+ return ( 0 );
+ }
+
+ pnd_log ( pndn_debug, "Info Exec=%s\n", pnd_apps_exec_runline() );
+
+ // try running it
+ int x;
+ if ( ( x = fork() ) < 0 ) {
+ pnd_log ( pndn_error, "ERROR: Couldn't fork()\n" );
+ return ( 0 );
+ }
+
+ if ( x == 0 ) {
+ execl ( "/bin/sh", "/bin/sh", "-c", pnd_apps_exec_runline(), (char*)NULL );
+ pnd_log ( pndn_error, "ERROR: Couldn't exec(%s)\n", pnd_apps_exec_runline() );
+ return ( 0 );
+ }
+
+ return ( 1 );
+}
+
+typedef struct {
+ SDL_Rect r;
+ int catnum;
+ mm_appref_t *ref;
+} ui_touch_t;
+#define MAXTOUCH 100
+ui_touch_t ui_touchrects [ MAXTOUCH ];
+unsigned char ui_touchrect_count = 0;
+
+void ui_register_reset ( void ) {
+ bzero ( ui_touchrects, sizeof(ui_touch_t)*MAXTOUCH );
+ ui_touchrect_count = 0;
+ return;
+}
+
+void ui_register_tab ( unsigned char catnum, unsigned int x, unsigned int y, unsigned int w, unsigned int h ) {
+
+ if ( ui_touchrect_count == MAXTOUCH ) {
+ return;
+ }
+
+ ui_touchrects [ ui_touchrect_count ].r.x = x;
+ ui_touchrects [ ui_touchrect_count ].r.y = y;
+ ui_touchrects [ ui_touchrect_count ].r.w = w;
+ ui_touchrects [ ui_touchrect_count ].r.h = h;
+ ui_touchrects [ ui_touchrect_count ].catnum = catnum;
+ ui_touchrect_count++;
+
+ return;
+}
+
+void ui_register_app ( mm_appref_t *app, unsigned int x, unsigned int y, unsigned int w, unsigned int h ) {
+
+ if ( ui_touchrect_count == MAXTOUCH ) {
+ return;
+ }
+
+ ui_touchrects [ ui_touchrect_count ].r.x = x;
+ ui_touchrects [ ui_touchrect_count ].r.y = y;
+ ui_touchrects [ ui_touchrect_count ].r.w = w;
+ ui_touchrects [ ui_touchrect_count ].r.h = h;
+ ui_touchrects [ ui_touchrect_count ].ref = app;
+ ui_touchrect_count++;
+
+ return;
+}
+
+void ui_touch_act ( unsigned int x, unsigned int y ) {
+
+ unsigned char i;
+ ui_touch_t *t;
+
+ for ( i = 0; i < ui_touchrect_count; i++ ) {
+ t = &(ui_touchrects [ i ]);
+
+ if ( x >= t -> r.x &&
+ x <= t -> r.x + t -> r.w &&
+ y >= t -> r.y &&
+ y <= t -> r.y + t -> r.h
+ )
+ {
+
+ if ( t -> ref ) {
+ ui_selected = t -> ref;
+ ui_push_exec();
+ } else {
+ ui_category = t -> catnum;
+ }
+
+ break;
+ }
+
+ } // for
+
+ return;
+}
+
+unsigned char ui_forkexec ( char *argv[] ) {
+ char *fooby = argv[0];
+ int x;
+
+ if ( ( x = fork() ) < 0 ) {
+ pnd_log ( pndn_error, "ERROR: Couldn't fork() for '%s'\n", fooby );
+ return ( 0 );
+ }
+
+ if ( x == 0 ) { // child
+ execv ( fooby, argv );
+ pnd_log ( pndn_error, "ERROR: Couldn't exec(%s)\n", fooby );
+ return ( 0 );
+ }
+
+ // parent, success
+ return ( 1 );
+}
+
+unsigned char ui_threaded_defered_preview ( pnd_disco_t *p ) {
+
+ if ( ! cache_preview ( p, pnd_conf_get_as_int_d ( g_conf, "previewpic.cell_width", 200 ),
+ pnd_conf_get_as_int_d ( g_conf, "previewpic.cell_height", 180 ) )
+ )
+ {
+ pnd_log ( pndn_debug, "THREAD: Couldn't load preview pic: '%s' -> '%s'\n",
+ IFNULL(p->title_en,"No Name"), p -> preview_pic1 );
+ }
+
+ // trigger that we completed
+ SDL_Event e;
+ bzero ( &e, sizeof(SDL_Event) );
+ e.type = SDL_USEREVENT;
+ e.user.code = sdl_user_finishedpreview;
+ e.user.data1 = p;
+ SDL_PushEvent ( &e );
+
+ return ( 0 );
+}
+
+SDL_Thread *g_icon_thread = NULL;
+void ui_post_scan ( void ) {
+
+ // if deferred icon load, kick off the thread now
+ if ( pnd_conf_get_as_int_d ( g_conf, "minimenu.load_icons_later", 0 ) == 1 ) {
+
+ g_icon_thread = SDL_CreateThread ( (void*)ui_threaded_defered_icon, NULL );
+
+ if ( ! g_icon_thread ) {
+ pnd_log ( pndn_error, "ERROR: Couldn't create icon thread\n" );
+ }
+
+ } // deferred icon load
+
+ return;
+}
+
+unsigned char ui_threaded_defered_icon ( void *p ) {
+ extern pnd_box_handle g_active_apps;
+ pnd_box_handle h = g_active_apps;
+
+ unsigned char maxwidth, maxheight;
+ maxwidth = pnd_conf_get_as_int_d ( g_conf, MMENU_DISP_ICON_MAX_WIDTH, 50 );
+ maxheight = pnd_conf_get_as_int_d ( g_conf, MMENU_DISP_ICON_MAX_HEIGHT, 50 );
+
+ pnd_disco_t *iter = pnd_box_get_head ( h );
+
+ while ( iter ) {
+
+ // cache it
+ if ( iter -> pnd_icon_pos &&
+ ! cache_icon ( iter, maxwidth, maxheight ) )
+ {
+ pnd_log ( pndn_warning, " Couldn't load icon: '%s'\n", IFNULL(iter->title_en,"No Name") );
+ } else {
+
+ // trigger that we completed
+ SDL_Event e;
+ bzero ( &e, sizeof(SDL_Event) );
+ e.type = SDL_USEREVENT;
+ e.user.code = sdl_user_finishedicon;
+ SDL_PushEvent ( &e );
+
+ //pnd_log ( pndn_warning, " Finished deferred load icon: '%s'\n", IFNULL(iter->title_en,"No Name") );
+ usleep ( pnd_conf_get_as_int_d ( g_conf, "minimenu.defer_icon_us", 50000 ) );
+
+ }
+
+ // next
+ iter = pnd_box_get_next ( iter );
+ } // while
+
+ return ( 0 );
+}