From 74b731edc6e0495d43a37412c60cd23a24789679 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Fri, 18 Mar 2005 23:51:52 +0000 Subject: Major rework of the x11 simulator button handling. (1) Button repeat should always work correctly now, not sending a release before the repeat(s). Fixes e.g. calling the Ondio menu. (2) Button handling is done in the timer thread, not sleep()ing the main thread for extended times. Fixes slow performance of high-workload plugins (codec tests). (3) The x11 simulator now also contains the queue handling code. (4) The new code requires X11R6 because the multi-threading extension is used. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6215 a1c6a512-1295-4272-9138-f99709370657 --- uisimulator/x11/SOURCES | 1 + uisimulator/x11/button-x11.c | 211 ++++++++++++++++++++++++++----------------- uisimulator/x11/kernel.c | 108 ++++++++++++++++++++++ uisimulator/x11/lcd-x11.c | 15 ++- uisimulator/x11/screenhack.c | 69 +++++++------- uisimulator/x11/screenhack.h | 10 +- uisimulator/x11/thread.c | 53 ++++++----- uisimulator/x11/uibasic.c | 23 +++-- 8 files changed, 331 insertions(+), 159 deletions(-) create mode 100644 uisimulator/x11/kernel.c diff --git a/uisimulator/x11/SOURCES b/uisimulator/x11/SOURCES index ea60b4e68a..c4813706c3 100644 --- a/uisimulator/x11/SOURCES +++ b/uisimulator/x11/SOURCES @@ -1,4 +1,5 @@ button-x11.c +kernel.c lcd-x11.c #if 0 /* if sound is enabled */ oss_sound.c diff --git a/uisimulator/x11/button-x11.c b/uisimulator/x11/button-x11.c index 28ede95df6..593d926b3f 100644 --- a/uisimulator/x11/button-x11.c +++ b/uisimulator/x11/button-x11.c @@ -16,6 +16,7 @@ * KIND, either express or implied. * ****************************************************************************/ +#include #include "config.h" #include "button.h" #include "kernel.h" @@ -24,41 +25,122 @@ #include "X11/keysym.h" -/* - *Initialize buttons - */ -void button_init() +extern int screenhack_handle_events(bool *release); + +struct event_queue button_queue; + +static int button_state = 0; /* keeps track of pressed keys */ +static long lastbtn; /* Last valid button status */ + +/* how often we check to see if a button is pressed */ +#define POLL_FREQUENCY HZ/25 + +/* how long until repeat kicks in */ +#define REPEAT_START 8 + +/* the speed repeat starts at */ +#define REPEAT_INTERVAL_START 4 + +/* speed repeat finishes at */ +#define REPEAT_INTERVAL_FINISH 2 + +/* mostly copied from real button.c */ +void button_read (void); + +void button_tick(void) { + static int tick = 0; + static int count = 0; + static int repeat_speed = REPEAT_INTERVAL_START; + static int repeat_count = 0; + static bool repeat = false; + int diff; + int btn; + + /* only poll every X ticks */ + if ( ++tick >= POLL_FREQUENCY ) + { + bool post = false; + button_read(); + btn = button_state; + + /* Find out if a key has been released */ + diff = btn ^ lastbtn; + if(diff && (btn & diff) == 0) + { + queue_post(&button_queue, BUTTON_REL | diff, NULL); + } + else + { + if ( btn ) + { + /* normal keypress */ + if ( btn != lastbtn ) + { + post = true; + repeat = false; + repeat_speed = REPEAT_INTERVAL_START; + + } + else /* repeat? */ + { + if ( repeat ) + { + count--; + if (count == 0) { + post = true; + /* yes we have repeat */ + repeat_speed--; + if (repeat_speed < REPEAT_INTERVAL_FINISH) + repeat_speed = REPEAT_INTERVAL_FINISH; + count = repeat_speed; + + repeat_count++; + + } + } + else + { + if (count++ > REPEAT_START) + { + post = true; + repeat = true; + repeat_count = 0; + /* initial repeat */ + count = REPEAT_INTERVAL_START; + } + } + } + if ( post ) + { + if (repeat) + queue_post(&button_queue, BUTTON_REPEAT | btn, NULL); + else + queue_post(&button_queue, btn, NULL); + } + } + else + { + repeat = false; + count = 0; + } + } + lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT); + tick = 0; + } } /* - * Translate X keys to Recorder keys - * - * We simulate recorder keys on the numeric keypad: - * - * 4,6,8,2 = Left, Right, Up, Down - * 5 = Play/pause - * Div,Mul,Sub = The tree menu keys - * +,Enter = On, Off - * - * Alternative Keys For Laptop or VNC Users - * Recorder: - * Space=Play Q=On A=Off 1,2,3 = F1,F2,F3 - * Player: - * Q=On Return=Menu + * Read X keys and translate to rockbox buttons */ -extern int screenhack_handle_events(bool *release, bool *repeat); - -int button_state = 0; - -static int get_raw_button (void) +void button_read (void) { int k; - bool release=false; /* is this a release event */ - bool repeat=false; /* is the key a repeated one */ - int ev=screenhack_handle_events(&release, &repeat); - switch(ev) + bool release = false; /* is this a release event */ + int ev = screenhack_handle_events(&release); + + switch (ev) { case XK_KP_Left: case XK_Left: @@ -144,10 +226,7 @@ static int get_raw_button (void) #ifdef HAVE_LCD_BITMAP case XK_5: if(!release) - { screen_dump(); - return 0; - } break; #endif @@ -168,75 +247,45 @@ static int get_raw_button (void) break; } - if(release) { - /* return a release event */ + if (release) button_state &= ~k; - k |= BUTTON_REL; - } - else { - if(k) { - button_state |= k; - k = button_state; - } - } - - if(repeat) - k |= BUTTON_REPEAT; - return k; + else + button_state |= k; } -/* - * Timeout after TICKS unless a key is pressed. - */ -long button_get_w_tmo(int ticks) +/* Again copied from real button.c... */ + +long button_get(bool block) { - int bits; - int i=0; + struct event ev; - for(i=0; i< ticks; i++) { - bits = get_raw_button(); - if(!bits) - sim_sleep(1); - else - break; + if ( block || !queue_empty(&button_queue) ) + { + queue_wait(&button_queue, &ev); + return ev.id; } - - return bits; + return BUTTON_NONE; } -/* - * Get the currently pressed button. - * Returns one of BUTTON_xxx codes, with possibly a modifier bit set. - * No modifier bits are set when the button is first pressed. - * BUTTON_HELD bit is while the button is being held. - * BUTTON_REL bit is set when button has been released. - */ -long button_get(bool block) +long button_get_w_tmo(int ticks) { - int bits; - do { - bits = get_raw_button(); - if(block && !bits) - sim_sleep(HZ/10); - else - break; - } while(1); - - if(!block) - /* delay a bit */ - sim_sleep(1); + struct event ev; + queue_wait_w_tmo(&button_queue, &ev, ticks); + return (ev.id != SYS_TIMEOUT)? ev.id: BUTTON_NONE; +} - return bits; +void button_init(void) +{ } int button_status(void) { - return get_raw_button(); + return lastbtn; } void button_clear_queue(void) { - while (get_raw_button()); + queue_clear(&button_queue); } #if CONFIG_KEYPAD == IRIVER_H100_PAD diff --git a/uisimulator/x11/kernel.c b/uisimulator/x11/kernel.c new file mode 100644 index 0000000000..7405fec52f --- /dev/null +++ b/uisimulator/x11/kernel.c @@ -0,0 +1,108 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Jens Arnold + * + * 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 "kernel.h" +#include "thread.h" + +int set_irq_level (int level) +{ + static int _lv = 0; + return (_lv = level); +} + +void queue_init(struct event_queue *q) +{ + q->read = 0; + q->write = 0; +} + +void queue_wait(struct event_queue *q, struct event *ev) +{ + while(q->read == q->write) + { + switch_thread(); + } + + *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; +} + +void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks) +{ + unsigned int timeout = current_tick + ticks; + + while(q->read == q->write && TIME_BEFORE( current_tick, timeout )) + { + sleep(1); + } + + if(q->read != q->write) + { + *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK]; + } + else + { + ev->id = SYS_TIMEOUT; + } +} + +void queue_post(struct event_queue *q, long id, void *data) +{ + int wr; + int oldlevel; + + oldlevel = set_irq_level(15<<4); + wr = (q->write++) & QUEUE_LENGTH_MASK; + + q->events[wr].id = id; + q->events[wr].data = data; + set_irq_level(oldlevel); +} + +bool queue_empty(const struct event_queue* q) +{ + return ( q->read == q->write ); +} + +void queue_clear(struct event_queue* q) +{ + /* fixme: This is potentially unsafe in case we do interrupt-like processing */ + q->read = 0; + q->write = 0; +} + +void switch_thread (void) +{ + yield (); +} + +void mutex_init(struct mutex *m) +{ + (void)m; +} + +void mutex_lock(struct mutex *m) +{ + (void)m; +} + +void mutex_unlock(struct mutex *m) +{ + (void)m; +} + diff --git a/uisimulator/x11/lcd-x11.c b/uisimulator/x11/lcd-x11.c index be687d1181..dada13d42d 100644 --- a/uisimulator/x11/lcd-x11.c +++ b/uisimulator/x11/lcd-x11.c @@ -42,7 +42,6 @@ extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; extern void screen_resized(int width, int height); -extern Display *dpy; #ifdef HAVE_LCD_BITMAP unsigned char lcd_framebuffer_copy[LCD_HEIGHT/8][LCD_WIDTH]; @@ -91,9 +90,11 @@ void lcd_update (void) drawdots(0, &clearpoints[0], cp); drawdots(1, &points[0], p); -/* printf("lcd_update: Draws %d pixels, clears %d pixels (max %d/%d)\n", + /* printf("lcd_update: Draws %d pixels, clears %d pixels (max %d/%d)\n", p, cp, p+cp, LCD_HEIGHT*LCD_WIDTH); */ + XtAppLock(app); XSync(dpy,False); + XtAppUnlock(app); } void lcd_update_rect(int x_start, int y_start, @@ -117,7 +118,7 @@ void lcd_update_rect(int x_start, int y_start, /* The Y coordinates have to work on even 8 pixel rows */ ymax = (yline + height)/8; yline /= 8; - + xmax = x_start + width; if(xmax > LCD_WIDTH) @@ -156,8 +157,10 @@ void lcd_update_rect(int x_start, int y_start, drawdots(0, &clearpoints[0], cp); drawdots(1, &points[0], p); - /* printf("lcd_update_rect: Draws %d pixels, clears %d pixels\n", p, cp);*/ + /* printf("lcd_update_rect: Draws %d pixels, clears %d pixels\n", p, cp);*/ + XtAppLock(app); XSync(dpy,False); + XtAppUnlock(app); } #endif #ifdef HAVE_LCD_CHARCELLS @@ -186,7 +189,11 @@ void lcd_update (void) } } if (changed) + { + XtAppLock(app); XSync(dpy,False); + XtAppUnlock(app); + } lcd_display_redraw=false; } diff --git a/uisimulator/x11/screenhack.c b/uisimulator/x11/screenhack.c index d7f21a60ce..d8731e4125 100644 --- a/uisimulator/x11/screenhack.c +++ b/uisimulator/x11/screenhack.c @@ -125,6 +125,8 @@ char having_new_lcd=True; char *progname; XrmDatabase db; XtAppContext app; +Display* dpy; +Window window; Bool mono_p; static XrmOptionDescRec default_options [] = { @@ -155,8 +157,8 @@ static char *default_defaults[] = { 0 }; -extern Display* dpy; extern int display_zoom; +extern long current_tick; static XrmOptionDescRec *merged_options; static int merged_options_size; @@ -238,27 +240,23 @@ static Bool MapNotify_event_p (Display *dpy, XEvent *event, XPointer window) static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW; -static Bool checkrepeat(time_t prev, - time_t now) + +void kb_disable_auto_repeat(bool on) { - if(now-prev < 50) { - return true; - } - return false; + XKeyboardControl kb; + + kb.auto_repeat_mode = on ? AutoRepeatModeOff : AutoRepeatModeDefault; + XChangeKeyboardControl(dpy, KBAutoRepeatMode, &kb); } /* Dead-trivial event handling. Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received. */ -int screenhack_handle_event(Display *dpy, XEvent *event, - bool *release, bool *repeat) +int screenhack_handle_event(XEvent *event, bool *release) { int key=0; - static time_t lasttime; - static unsigned int lastkeycode; *release = FALSE; - *repeat = false; switch (event->xany.type) { case KeyPress: @@ -268,14 +266,9 @@ int screenhack_handle_event(Display *dpy, XEvent *event, XLookupString (&event->xkey, &c, 1, &keysym, 0); key = keysym; #if 0 - DEBUGF("Got keypress: %02x %x, time %lx\n", c, - event->xkey.keycode, - event->xkey.time); + DEBUGF("Got keypress: %c (%02x) %x, tick %ld\n", c, c, + event->xkey.keycode, current_tick); #endif - if(lastkeycode == event->xkey.keycode) - *repeat = checkrepeat(lasttime, event->xkey.time); - lasttime = event->xkey.time; - lastkeycode = event->xkey.keycode; } break; case KeyRelease: @@ -285,22 +278,21 @@ int screenhack_handle_event(Display *dpy, XEvent *event, XLookupString (&event->xkey, &c, 1, &keysym, 0); key = keysym; #if 0 - DEBUGF("Got keyrelease: %c (%02x) %x\n", c, c, - event->xkey.keycode); + DEBUGF("Got keyrelease: %c (%02x) %x, tick %ld\n", c, c, + event->xkey.keycode, current_tick); #endif - if(lastkeycode == event->xkey.keycode) - *repeat = checkrepeat(lasttime, event->xkey.time); - lasttime = event->xkey.time; - lastkeycode = event->xkey.keycode; - if(*repeat) - return 0; /* on repeats, return nothing on release */ - *release = TRUE; } break; case Expose: screen_redraw(); break; + case FocusIn: + kb_disable_auto_repeat(true); + break; + case FocusOut: + kb_disable_auto_repeat(false); + break; case ClientMessage: if (event->xclient.message_type != XA_WM_PROTOCOLS) { char *s = XGetAtomName(dpy, event->xclient.message_type); @@ -320,6 +312,8 @@ int screenhack_handle_event(Display *dpy, XEvent *event, progname, s1, s2); } else { + kb_disable_auto_repeat(false); + XSync(dpy, false); /* force the X server to process that */ exit (0); } break; @@ -330,15 +324,17 @@ int screenhack_handle_event(Display *dpy, XEvent *event, } -int screenhack_handle_events(bool *release, bool *repeat) +int screenhack_handle_events(bool *release) { int key=0; + XtAppLock(app); if(XPending(dpy)) { XEvent event; XNextEvent(dpy, &event); - key=screenhack_handle_event(dpy, &event, release, repeat); + key=screenhack_handle_event(&event, release); } + XtAppUnlock(app); return key; } @@ -347,7 +343,7 @@ static Visual *pick_visual (Screen *screen) { #ifdef USE_GL /* If we're linking against GL (that is, this is the version of - screenhack.o that the GL hacks will use, which is different from the + screenhack.o that the GL hacks will use, which is different from the one that the non-GL hacks will use) then try to pick the "best" visual by interrogating the GL library instead of by asking Xlib. GL knows better. @@ -379,8 +375,6 @@ static Visual *pick_visual (Screen *screen) int main (int argc, char **argv) { Widget toplevel; - Display *dpy; - Window window; Screen *screen; Visual *visual; Colormap cmap; @@ -460,9 +454,11 @@ int main (int argc, char **argv) does work when passed as an -xrm arg on the command line. So screw it, turn them off from C instead. */ - SgiUseSchemes ("none"); + SgiUseSchemes ("none"); #endif /* __sgi */ + XtToolkitThreadInitialize(); + toplevel = XtAppInitialize (&app, progclass, merged_options, merged_options_size, &argc, argv, merged_defaults, 0, 0); @@ -556,7 +552,7 @@ int main (int argc, char **argv) XGetWindowAttributes (dpy, window, &xgwa); XSelectInput (dpy, window, xgwa.your_event_mask | KeyPressMask | KeyRelease | - ButtonPressMask | ExposureMask); + ButtonPressMask | ExposureMask | FocusChangeMask ); XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32, PropModeReplace, (unsigned char *) &XA_WM_DELETE_WINDOW, 1); @@ -573,6 +569,7 @@ int main (int argc, char **argv) XSync (dpy, False); - screenhack (dpy, window); /* doesn't return */ + kb_disable_auto_repeat(true); + screenhack(); /* doesn't return */ return 0; } diff --git a/uisimulator/x11/screenhack.h b/uisimulator/x11/screenhack.h index 084f8769bd..5c2e5321ac 100644 --- a/uisimulator/x11/screenhack.h +++ b/uisimulator/x11/screenhack.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "resources.h" #include "visual.h" @@ -38,10 +39,13 @@ extern char *progclass; extern XrmDatabase db; extern XrmOptionDescRec options []; extern char *defaults []; +extern XtAppContext app; +extern Display* dpy; +extern Window window; -extern void screenhack (Display*,Window); -extern int screenhack_handle_event(Display*, XEvent*, bool *, bool *); -extern int screenhack_handle_events(bool *, bool *); +extern void screenhack(); +extern int screenhack_handle_event(XEvent*, bool *); +extern int screenhack_handle_events(bool *); extern void screen_redraw(); extern void screen_resized(); diff --git a/uisimulator/x11/thread.c b/uisimulator/x11/thread.c index 6f109a3425..12a3b3e0c7 100644 --- a/uisimulator/x11/thread.c +++ b/uisimulator/x11/thread.c @@ -24,6 +24,16 @@ #include long current_tick = 0; +extern void button_tick(void); + +static void msleep(int msec) +{ + struct timeval delay; + + delay.tv_sec = msec / 1000; + delay.tv_usec = (msec - 1000 * delay.tv_sec) * 1000; + select(0, NULL, NULL, NULL, &delay); /* portable sub-second sleep */ +} /* * This is not a target thread, so it does not fall under the 1 thread at a @@ -31,17 +41,23 @@ long current_tick = 0; */ static void update_tick_thread() { - struct timeval start, now, delay; + struct timeval start, now; + long new_tick; gettimeofday(&start, NULL); while (1) { - delay.tv_sec = 0; - delay.tv_usec = (1000000/HZ/4); /* check 4 times per target tick */ - select(0, NULL, NULL, NULL, &delay); /* portable sub-second sleep */ + msleep(5); /* check twice per simulated target tick */ gettimeofday(&now, NULL); - current_tick = (now.tv_sec - start.tv_sec) * HZ - + (now.tv_usec - start.tv_usec) * HZ / 1000000; + new_tick = (now.tv_sec - start.tv_sec) * HZ + + (now.tv_usec - start.tv_usec) / (1000000/HZ); + if (new_tick > current_tick) + { + current_tick = new_tick; + button_tick(); /* Dirty call to button.c. This should probably + * be implemented as a tick task the same way + * as on the target. */ + } } } @@ -73,7 +89,8 @@ void init_threads(void) void yield(void) { pthread_mutex_unlock(&mp); /* return */ - pthread_mutex_lock(&mp); /* get it again */ + msleep(1); /* prevent busy loop */ + pthread_mutex_lock(&mp); /* get it again */ } void newfunc(void (*func)(void)) @@ -109,26 +126,8 @@ int create_thread(void* fp, void* sp, int stk_size) void sim_sleep(int ticks) { - struct timeval delay; - pthread_mutex_unlock(&mp); /* return */ - delay.tv_sec = ticks / HZ; - delay.tv_usec = (ticks - HZ * delay.tv_sec) * (1000000/HZ); - select(0, NULL, NULL, NULL, &delay); /* portable subsecond sleep */ - pthread_mutex_lock(&mp); /* get it again */ -} - -void mutex_init(struct mutex *m) -{ - (void)m; + msleep((1000/HZ) * ticks); + pthread_mutex_lock(&mp); /* get it again */ } -void mutex_lock(struct mutex *m) -{ - (void)m; -} - -void mutex_unlock(struct mutex *m) -{ - (void)m; -} diff --git a/uisimulator/x11/uibasic.c b/uisimulator/x11/uibasic.c index ca3c2c5568..0c3e9bb9d0 100644 --- a/uisimulator/x11/uibasic.c +++ b/uisimulator/x11/uibasic.c @@ -48,9 +48,6 @@ GC draw_gc; static Colormap cmap; int display_zoom=1; - -Display *dpy; -Window window; bool lcd_display_redraw=true; XrmOptionDescRec options [] = { @@ -96,16 +93,19 @@ void screen_resized(int width, int height) maxx = width; maxy = height; + XtAppLock(app); XSetForeground(dpy, draw_gc, get_pixel_resource("background", "Background", dpy, cmap)); XFillRectangle(dpy, window, draw_gc, 0, 0, width*display_zoom, height*display_zoom); + XtAppUnlock(app); lcd_display_redraw=true; screen_redraw(); } void drawrect(int color, int x1, int y1, int x2, int y2) { + XtAppLock(app); if (color==0) XSetForeground(dpy, draw_gc, get_pixel_resource("background", "Background", dpy, cmap)); @@ -115,6 +115,7 @@ void drawrect(int color, int x1, int y1, int x2, int y2) XFillRectangle(dpy, window, draw_gc, x1*display_zoom, y1*display_zoom, x2*display_zoom, y2*display_zoom); + XtAppUnlock(app); } static void help(void) @@ -125,6 +126,7 @@ static void help(void) void drawline(int color, int x1, int y1, int x2, int y2) { + XtAppLock(app); if (color==0) XSetForeground(dpy, draw_gc, get_pixel_resource("background", "Background", dpy, cmap)); @@ -137,10 +139,12 @@ void drawline(int color, int x1, int y1, int x2, int y2) (int)(y1*display_zoom), (int)(x2*display_zoom), (int)(y2*display_zoom)); + XtAppUnlock(app); } void drawdot(int color, int x, int y) { + XtAppLock(app); if (color==0) XSetForeground(dpy, draw_gc, get_pixel_resource("background", "Background", dpy, cmap)); @@ -150,10 +154,12 @@ void drawdot(int color, int x, int y) XFillRectangle(dpy, window, draw_gc, x*display_zoom, y*display_zoom, display_zoom, display_zoom); + XtAppUnlock(app); } void drawdots(int color, struct coordinate *points, int count) { + XtAppLock(app); if (color==0) XSetForeground(dpy, draw_gc, get_pixel_resource("background", "Background", dpy, cmap)); @@ -168,10 +174,12 @@ void drawdots(int color, struct coordinate *points, int count) display_zoom, display_zoom); } + XtAppUnlock(app); } void drawrectangles(int color, struct rectangle *points, int count) { + XtAppLock(app); if (color==0) XSetForeground(dpy, draw_gc, get_pixel_resource("background", "Background", dpy, cmap)); @@ -186,10 +194,12 @@ void drawrectangles(int color, struct rectangle *points, int count) points[count].width*display_zoom, points[count].height*display_zoom); } + XtAppUnlock(app); } void drawtext(int color, int x, int y, char *text) { + XtAppLock(app); if (color==0) XSetForeground(dpy, draw_gc, get_pixel_resource("background", "Background", dpy, cmap)); @@ -199,13 +209,13 @@ void drawtext(int color, int x, int y, char *text) XDrawString(dpy, window, draw_gc, x*display_zoom, y*display_zoom, text, strlen(text)); + XtAppUnlock(app); } /* this is where the applicaton starts */ extern void app_main(void); -void -screenhack (Display *the_dpy, Window the_window) +void screenhack() { Bool helpme; @@ -216,9 +226,6 @@ screenhack (Display *the_dpy, Window the_window) printf(PROGNAME " " ROCKBOXUI_VERSION " (" __DATE__ ")\n"); - dpy=the_dpy; - window=the_window; - init_window(); screen_redraw(); -- cgit v1.2.3