diff options
Diffstat (limited to 'uisimulator/x11')
-rw-r--r-- | uisimulator/x11/SOURCES | 1 | ||||
-rw-r--r-- | uisimulator/x11/button-x11.c | 211 | ||||
-rw-r--r-- | uisimulator/x11/kernel.c | 108 | ||||
-rw-r--r-- | uisimulator/x11/lcd-x11.c | 15 | ||||
-rw-r--r-- | uisimulator/x11/screenhack.c | 69 | ||||
-rw-r--r-- | uisimulator/x11/screenhack.h | 10 | ||||
-rw-r--r-- | uisimulator/x11/thread.c | 53 | ||||
-rw-r--r-- | uisimulator/x11/uibasic.c | 23 |
8 files changed, 331 insertions, 159 deletions
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 <stdlib.h> #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 <X11/Xlib.h> #include <X11/Xresource.h> #include <X11/Xos.h> +#include <X11/Intrinsic.h> #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 <sys/time.h> 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(); |