summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-03-18 23:51:52 +0000
committerJens Arnold <amiconn@rockbox.org>2005-03-18 23:51:52 +0000
commit74b731edc6e0495d43a37412c60cd23a24789679 (patch)
treee4d4014047b65f4cf05e9c0ba3d48a05a1eb04f9
parent9101465ae83fd89ebcdf55fc3e831dfca74884ea (diff)
downloadrockbox-74b731edc6e0495d43a37412c60cd23a24789679.tar.gz
rockbox-74b731edc6e0495d43a37412c60cd23a24789679.zip
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
-rw-r--r--uisimulator/x11/SOURCES1
-rw-r--r--uisimulator/x11/button-x11.c211
-rw-r--r--uisimulator/x11/kernel.c108
-rw-r--r--uisimulator/x11/lcd-x11.c15
-rw-r--r--uisimulator/x11/screenhack.c69
-rw-r--r--uisimulator/x11/screenhack.h10
-rw-r--r--uisimulator/x11/thread.c53
-rw-r--r--uisimulator/x11/uibasic.c23
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 @@
1button-x11.c 1button-x11.c
2kernel.c
2lcd-x11.c 3lcd-x11.c
3#if 0 /* if sound is enabled */ 4#if 0 /* if sound is enabled */
4oss_sound.c 5oss_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 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include <stdlib.h>
19#include "config.h" 20#include "config.h"
20#include "button.h" 21#include "button.h"
21#include "kernel.h" 22#include "kernel.h"
@@ -24,41 +25,122 @@
24 25
25#include "X11/keysym.h" 26#include "X11/keysym.h"
26 27
27/* 28extern int screenhack_handle_events(bool *release);
28 *Initialize buttons 29
29 */ 30struct event_queue button_queue;
30void button_init() 31
32static int button_state = 0; /* keeps track of pressed keys */
33static long lastbtn; /* Last valid button status */
34
35/* how often we check to see if a button is pressed */
36#define POLL_FREQUENCY HZ/25
37
38/* how long until repeat kicks in */
39#define REPEAT_START 8
40
41/* the speed repeat starts at */
42#define REPEAT_INTERVAL_START 4
43
44/* speed repeat finishes at */
45#define REPEAT_INTERVAL_FINISH 2
46
47/* mostly copied from real button.c */
48void button_read (void);
49
50void button_tick(void)
31{ 51{
52 static int tick = 0;
53 static int count = 0;
54 static int repeat_speed = REPEAT_INTERVAL_START;
55 static int repeat_count = 0;
56 static bool repeat = false;
57 int diff;
58 int btn;
59
60 /* only poll every X ticks */
61 if ( ++tick >= POLL_FREQUENCY )
62 {
63 bool post = false;
64 button_read();
65 btn = button_state;
66
67 /* Find out if a key has been released */
68 diff = btn ^ lastbtn;
69 if(diff && (btn & diff) == 0)
70 {
71 queue_post(&button_queue, BUTTON_REL | diff, NULL);
72 }
73 else
74 {
75 if ( btn )
76 {
77 /* normal keypress */
78 if ( btn != lastbtn )
79 {
80 post = true;
81 repeat = false;
82 repeat_speed = REPEAT_INTERVAL_START;
83
84 }
85 else /* repeat? */
86 {
87 if ( repeat )
88 {
89 count--;
90 if (count == 0) {
91 post = true;
92 /* yes we have repeat */
93 repeat_speed--;
94 if (repeat_speed < REPEAT_INTERVAL_FINISH)
95 repeat_speed = REPEAT_INTERVAL_FINISH;
96 count = repeat_speed;
97
98 repeat_count++;
99
100 }
101 }
102 else
103 {
104 if (count++ > REPEAT_START)
105 {
106 post = true;
107 repeat = true;
108 repeat_count = 0;
109 /* initial repeat */
110 count = REPEAT_INTERVAL_START;
111 }
112 }
113 }
114 if ( post )
115 {
116 if (repeat)
117 queue_post(&button_queue, BUTTON_REPEAT | btn, NULL);
118 else
119 queue_post(&button_queue, btn, NULL);
120 }
121 }
122 else
123 {
124 repeat = false;
125 count = 0;
126 }
127 }
128 lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT);
129 tick = 0;
130 }
32} 131}
33 132
34/* 133/*
35 * Translate X keys to Recorder keys 134 * Read X keys and translate to rockbox buttons
36 *
37 * We simulate recorder keys on the numeric keypad:
38 *
39 * 4,6,8,2 = Left, Right, Up, Down
40 * 5 = Play/pause
41 * Div,Mul,Sub = The tree menu keys
42 * +,Enter = On, Off
43 *
44 * Alternative Keys For Laptop or VNC Users
45 * Recorder:
46 * Space=Play Q=On A=Off 1,2,3 = F1,F2,F3
47 * Player:
48 * Q=On Return=Menu
49 */ 135 */
50 136
51extern int screenhack_handle_events(bool *release, bool *repeat); 137void button_read (void)
52
53int button_state = 0;
54
55static int get_raw_button (void)
56{ 138{
57 int k; 139 int k;
58 bool release=false; /* is this a release event */ 140 bool release = false; /* is this a release event */
59 bool repeat=false; /* is the key a repeated one */ 141 int ev = screenhack_handle_events(&release);
60 int ev=screenhack_handle_events(&release, &repeat); 142
61 switch(ev) 143 switch (ev)
62 { 144 {
63 case XK_KP_Left: 145 case XK_KP_Left:
64 case XK_Left: 146 case XK_Left:
@@ -144,10 +226,7 @@ static int get_raw_button (void)
144#ifdef HAVE_LCD_BITMAP 226#ifdef HAVE_LCD_BITMAP
145 case XK_5: 227 case XK_5:
146 if(!release) 228 if(!release)
147 {
148 screen_dump(); 229 screen_dump();
149 return 0;
150 }
151 break; 230 break;
152#endif 231#endif
153 232
@@ -168,75 +247,45 @@ static int get_raw_button (void)
168 break; 247 break;
169 } 248 }
170 249
171 if(release) { 250 if (release)
172 /* return a release event */
173 button_state &= ~k; 251 button_state &= ~k;
174 k |= BUTTON_REL; 252 else
175 } 253 button_state |= k;
176 else {
177 if(k) {
178 button_state |= k;
179 k = button_state;
180 }
181 }
182
183 if(repeat)
184 k |= BUTTON_REPEAT;
185 return k;
186} 254}
187 255
188/* 256/* Again copied from real button.c... */
189 * Timeout after TICKS unless a key is pressed. 257
190 */ 258long button_get(bool block)
191long button_get_w_tmo(int ticks)
192{ 259{
193 int bits; 260 struct event ev;
194 int i=0;
195 261
196 for(i=0; i< ticks; i++) { 262 if ( block || !queue_empty(&button_queue) )
197 bits = get_raw_button(); 263 {
198 if(!bits) 264 queue_wait(&button_queue, &ev);
199 sim_sleep(1); 265 return ev.id;
200 else
201 break;
202 } 266 }
203 267 return BUTTON_NONE;
204 return bits;
205} 268}
206 269
207/* 270long button_get_w_tmo(int ticks)
208 * Get the currently pressed button.
209 * Returns one of BUTTON_xxx codes, with possibly a modifier bit set.
210 * No modifier bits are set when the button is first pressed.
211 * BUTTON_HELD bit is while the button is being held.
212 * BUTTON_REL bit is set when button has been released.
213 */
214long button_get(bool block)
215{ 271{
216 int bits; 272 struct event ev;
217 do { 273 queue_wait_w_tmo(&button_queue, &ev, ticks);
218 bits = get_raw_button(); 274 return (ev.id != SYS_TIMEOUT)? ev.id: BUTTON_NONE;
219 if(block && !bits) 275}
220 sim_sleep(HZ/10);
221 else
222 break;
223 } while(1);
224
225 if(!block)
226 /* delay a bit */
227 sim_sleep(1);
228 276
229 return bits; 277void button_init(void)
278{
230} 279}
231 280
232int button_status(void) 281int button_status(void)
233{ 282{
234 return get_raw_button(); 283 return lastbtn;
235} 284}
236 285
237void button_clear_queue(void) 286void button_clear_queue(void)
238{ 287{
239 while (get_raw_button()); 288 queue_clear(&button_queue);
240} 289}
241 290
242#if CONFIG_KEYPAD == IRIVER_H100_PAD 291#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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Jens Arnold
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "kernel.h"
21#include "thread.h"
22
23int set_irq_level (int level)
24{
25 static int _lv = 0;
26 return (_lv = level);
27}
28
29void queue_init(struct event_queue *q)
30{
31 q->read = 0;
32 q->write = 0;
33}
34
35void queue_wait(struct event_queue *q, struct event *ev)
36{
37 while(q->read == q->write)
38 {
39 switch_thread();
40 }
41
42 *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK];
43}
44
45void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks)
46{
47 unsigned int timeout = current_tick + ticks;
48
49 while(q->read == q->write && TIME_BEFORE( current_tick, timeout ))
50 {
51 sleep(1);
52 }
53
54 if(q->read != q->write)
55 {
56 *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK];
57 }
58 else
59 {
60 ev->id = SYS_TIMEOUT;
61 }
62}
63
64void queue_post(struct event_queue *q, long id, void *data)
65{
66 int wr;
67 int oldlevel;
68
69 oldlevel = set_irq_level(15<<4);
70 wr = (q->write++) & QUEUE_LENGTH_MASK;
71
72 q->events[wr].id = id;
73 q->events[wr].data = data;
74 set_irq_level(oldlevel);
75}
76
77bool queue_empty(const struct event_queue* q)
78{
79 return ( q->read == q->write );
80}
81
82void queue_clear(struct event_queue* q)
83{
84 /* fixme: This is potentially unsafe in case we do interrupt-like processing */
85 q->read = 0;
86 q->write = 0;
87}
88
89void switch_thread (void)
90{
91 yield ();
92}
93
94void mutex_init(struct mutex *m)
95{
96 (void)m;
97}
98
99void mutex_lock(struct mutex *m)
100{
101 (void)m;
102}
103
104void mutex_unlock(struct mutex *m)
105{
106 (void)m;
107}
108
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 @@
42 42
43extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; 43extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH];
44extern void screen_resized(int width, int height); 44extern void screen_resized(int width, int height);
45extern Display *dpy;
46 45
47#ifdef HAVE_LCD_BITMAP 46#ifdef HAVE_LCD_BITMAP
48unsigned char lcd_framebuffer_copy[LCD_HEIGHT/8][LCD_WIDTH]; 47unsigned char lcd_framebuffer_copy[LCD_HEIGHT/8][LCD_WIDTH];
@@ -91,9 +90,11 @@ void lcd_update (void)
91 90
92 drawdots(0, &clearpoints[0], cp); 91 drawdots(0, &clearpoints[0], cp);
93 drawdots(1, &points[0], p); 92 drawdots(1, &points[0], p);
94/* printf("lcd_update: Draws %d pixels, clears %d pixels (max %d/%d)\n", 93 /* printf("lcd_update: Draws %d pixels, clears %d pixels (max %d/%d)\n",
95 p, cp, p+cp, LCD_HEIGHT*LCD_WIDTH); */ 94 p, cp, p+cp, LCD_HEIGHT*LCD_WIDTH); */
95 XtAppLock(app);
96 XSync(dpy,False); 96 XSync(dpy,False);
97 XtAppUnlock(app);
97} 98}
98 99
99void lcd_update_rect(int x_start, int y_start, 100void lcd_update_rect(int x_start, int y_start,
@@ -117,7 +118,7 @@ void lcd_update_rect(int x_start, int y_start,
117 /* The Y coordinates have to work on even 8 pixel rows */ 118 /* The Y coordinates have to work on even 8 pixel rows */
118 ymax = (yline + height)/8; 119 ymax = (yline + height)/8;
119 yline /= 8; 120 yline /= 8;
120 121
121 xmax = x_start + width; 122 xmax = x_start + width;
122 123
123 if(xmax > LCD_WIDTH) 124 if(xmax > LCD_WIDTH)
@@ -156,8 +157,10 @@ void lcd_update_rect(int x_start, int y_start,
156 157
157 drawdots(0, &clearpoints[0], cp); 158 drawdots(0, &clearpoints[0], cp);
158 drawdots(1, &points[0], p); 159 drawdots(1, &points[0], p);
159 /* printf("lcd_update_rect: Draws %d pixels, clears %d pixels\n", p, cp);*/ 160 /* printf("lcd_update_rect: Draws %d pixels, clears %d pixels\n", p, cp);*/
161 XtAppLock(app);
160 XSync(dpy,False); 162 XSync(dpy,False);
163 XtAppUnlock(app);
161} 164}
162#endif 165#endif
163#ifdef HAVE_LCD_CHARCELLS 166#ifdef HAVE_LCD_CHARCELLS
@@ -186,7 +189,11 @@ void lcd_update (void)
186 } 189 }
187 } 190 }
188 if (changed) 191 if (changed)
192 {
193 XtAppLock(app);
189 XSync(dpy,False); 194 XSync(dpy,False);
195 XtAppUnlock(app);
196 }
190 lcd_display_redraw=false; 197 lcd_display_redraw=false;
191} 198}
192 199
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;
125char *progname; 125char *progname;
126XrmDatabase db; 126XrmDatabase db;
127XtAppContext app; 127XtAppContext app;
128Display* dpy;
129Window window;
128Bool mono_p; 130Bool mono_p;
129 131
130static XrmOptionDescRec default_options [] = { 132static XrmOptionDescRec default_options [] = {
@@ -155,8 +157,8 @@ static char *default_defaults[] = {
155 0 157 0
156}; 158};
157 159
158extern Display* dpy;
159extern int display_zoom; 160extern int display_zoom;
161extern long current_tick;
160 162
161static XrmOptionDescRec *merged_options; 163static XrmOptionDescRec *merged_options;
162static int merged_options_size; 164static int merged_options_size;
@@ -238,27 +240,23 @@ static Bool MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
238 240
239static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW; 241static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW;
240 242
241static Bool checkrepeat(time_t prev, 243
242 time_t now) 244void kb_disable_auto_repeat(bool on)
243{ 245{
244 if(now-prev < 50) { 246 XKeyboardControl kb;
245 return true; 247
246 } 248 kb.auto_repeat_mode = on ? AutoRepeatModeOff : AutoRepeatModeDefault;
247 return false; 249 XChangeKeyboardControl(dpy, KBAutoRepeatMode, &kb);
248} 250}
249 251
250/* Dead-trivial event handling. 252/* Dead-trivial event handling.
251 Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received. 253 Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
252 */ 254 */
253int screenhack_handle_event(Display *dpy, XEvent *event, 255int screenhack_handle_event(XEvent *event, bool *release)
254 bool *release, bool *repeat)
255{ 256{
256 int key=0; 257 int key=0;
257 static time_t lasttime;
258 static unsigned int lastkeycode;
259 258
260 *release = FALSE; 259 *release = FALSE;
261 *repeat = false;
262 260
263 switch (event->xany.type) { 261 switch (event->xany.type) {
264 case KeyPress: 262 case KeyPress:
@@ -268,14 +266,9 @@ int screenhack_handle_event(Display *dpy, XEvent *event,
268 XLookupString (&event->xkey, &c, 1, &keysym, 0); 266 XLookupString (&event->xkey, &c, 1, &keysym, 0);
269 key = keysym; 267 key = keysym;
270#if 0 268#if 0
271 DEBUGF("Got keypress: %02x %x, time %lx\n", c, 269 DEBUGF("Got keypress: %c (%02x) %x, tick %ld\n", c, c,
272 event->xkey.keycode, 270 event->xkey.keycode, current_tick);
273 event->xkey.time);
274#endif 271#endif
275 if(lastkeycode == event->xkey.keycode)
276 *repeat = checkrepeat(lasttime, event->xkey.time);
277 lasttime = event->xkey.time;
278 lastkeycode = event->xkey.keycode;
279 } 272 }
280 break; 273 break;
281 case KeyRelease: 274 case KeyRelease:
@@ -285,22 +278,21 @@ int screenhack_handle_event(Display *dpy, XEvent *event,
285 XLookupString (&event->xkey, &c, 1, &keysym, 0); 278 XLookupString (&event->xkey, &c, 1, &keysym, 0);
286 key = keysym; 279 key = keysym;
287#if 0 280#if 0
288 DEBUGF("Got keyrelease: %c (%02x) %x\n", c, c, 281 DEBUGF("Got keyrelease: %c (%02x) %x, tick %ld\n", c, c,
289 event->xkey.keycode); 282 event->xkey.keycode, current_tick);
290#endif 283#endif
291 if(lastkeycode == event->xkey.keycode)
292 *repeat = checkrepeat(lasttime, event->xkey.time);
293 lasttime = event->xkey.time;
294 lastkeycode = event->xkey.keycode;
295 if(*repeat)
296 return 0; /* on repeats, return nothing on release */
297
298 *release = TRUE; 284 *release = TRUE;
299 } 285 }
300 break; 286 break;
301 case Expose: 287 case Expose:
302 screen_redraw(); 288 screen_redraw();
303 break; 289 break;
290 case FocusIn:
291 kb_disable_auto_repeat(true);
292 break;
293 case FocusOut:
294 kb_disable_auto_repeat(false);
295 break;
304 case ClientMessage: 296 case ClientMessage:
305 if (event->xclient.message_type != XA_WM_PROTOCOLS) { 297 if (event->xclient.message_type != XA_WM_PROTOCOLS) {
306 char *s = XGetAtomName(dpy, event->xclient.message_type); 298 char *s = XGetAtomName(dpy, event->xclient.message_type);
@@ -320,6 +312,8 @@ int screenhack_handle_event(Display *dpy, XEvent *event,
320 progname, s1, s2); 312 progname, s1, s2);
321 } 313 }
322 else { 314 else {
315 kb_disable_auto_repeat(false);
316 XSync(dpy, false); /* force the X server to process that */
323 exit (0); 317 exit (0);
324 } 318 }
325 break; 319 break;
@@ -330,15 +324,17 @@ int screenhack_handle_event(Display *dpy, XEvent *event,
330} 324}
331 325
332 326
333int screenhack_handle_events(bool *release, bool *repeat) 327int screenhack_handle_events(bool *release)
334{ 328{
335 int key=0; 329 int key=0;
330 XtAppLock(app);
336 if(XPending(dpy)) 331 if(XPending(dpy))
337 { 332 {
338 XEvent event; 333 XEvent event;
339 XNextEvent(dpy, &event); 334 XNextEvent(dpy, &event);
340 key=screenhack_handle_event(dpy, &event, release, repeat); 335 key=screenhack_handle_event(&event, release);
341 } 336 }
337 XtAppUnlock(app);
342 return key; 338 return key;
343} 339}
344 340
@@ -347,7 +343,7 @@ static Visual *pick_visual (Screen *screen)
347{ 343{
348#ifdef USE_GL 344#ifdef USE_GL
349 /* If we're linking against GL (that is, this is the version of 345 /* If we're linking against GL (that is, this is the version of
350 screenhack.o that the GL hacks will use, which is different from the 346 screenhack.o that the GL hacks will use, which is different from the
351 one that the non-GL hacks will use) then try to pick the "best" visual 347 one that the non-GL hacks will use) then try to pick the "best" visual
352 by interrogating the GL library instead of by asking Xlib. GL knows 348 by interrogating the GL library instead of by asking Xlib. GL knows
353 better. 349 better.
@@ -379,8 +375,6 @@ static Visual *pick_visual (Screen *screen)
379int main (int argc, char **argv) 375int main (int argc, char **argv)
380{ 376{
381 Widget toplevel; 377 Widget toplevel;
382 Display *dpy;
383 Window window;
384 Screen *screen; 378 Screen *screen;
385 Visual *visual; 379 Visual *visual;
386 Colormap cmap; 380 Colormap cmap;
@@ -460,9 +454,11 @@ int main (int argc, char **argv)
460 does work when passed as an -xrm arg on the command line. So screw it, 454 does work when passed as an -xrm arg on the command line. So screw it,
461 turn them off from C instead. 455 turn them off from C instead.
462 */ 456 */
463 SgiUseSchemes ("none"); 457 SgiUseSchemes ("none");
464#endif /* __sgi */ 458#endif /* __sgi */
465 459
460 XtToolkitThreadInitialize();
461
466 toplevel = XtAppInitialize (&app, progclass, merged_options, 462 toplevel = XtAppInitialize (&app, progclass, merged_options,
467 merged_options_size, &argc, argv, 463 merged_options_size, &argc, argv,
468 merged_defaults, 0, 0); 464 merged_defaults, 0, 0);
@@ -556,7 +552,7 @@ int main (int argc, char **argv)
556 XGetWindowAttributes (dpy, window, &xgwa); 552 XGetWindowAttributes (dpy, window, &xgwa);
557 XSelectInput (dpy, window, 553 XSelectInput (dpy, window,
558 xgwa.your_event_mask | KeyPressMask | KeyRelease | 554 xgwa.your_event_mask | KeyPressMask | KeyRelease |
559 ButtonPressMask | ExposureMask); 555 ButtonPressMask | ExposureMask | FocusChangeMask );
560 XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32, 556 XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
561 PropModeReplace, 557 PropModeReplace,
562 (unsigned char *) &XA_WM_DELETE_WINDOW, 1); 558 (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
@@ -573,6 +569,7 @@ int main (int argc, char **argv)
573 569
574 XSync (dpy, False); 570 XSync (dpy, False);
575 571
576 screenhack (dpy, window); /* doesn't return */ 572 kb_disable_auto_repeat(true);
573 screenhack(); /* doesn't return */
577 return 0; 574 return 0;
578} 575}
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 @@
28#include <X11/Xlib.h> 28#include <X11/Xlib.h>
29#include <X11/Xresource.h> 29#include <X11/Xresource.h>
30#include <X11/Xos.h> 30#include <X11/Xos.h>
31#include <X11/Intrinsic.h>
31 32
32#include "resources.h" 33#include "resources.h"
33#include "visual.h" 34#include "visual.h"
@@ -38,10 +39,13 @@ extern char *progclass;
38extern XrmDatabase db; 39extern XrmDatabase db;
39extern XrmOptionDescRec options []; 40extern XrmOptionDescRec options [];
40extern char *defaults []; 41extern char *defaults [];
42extern XtAppContext app;
43extern Display* dpy;
44extern Window window;
41 45
42extern void screenhack (Display*,Window); 46extern void screenhack();
43extern int screenhack_handle_event(Display*, XEvent*, bool *, bool *); 47extern int screenhack_handle_event(XEvent*, bool *);
44extern int screenhack_handle_events(bool *, bool *); 48extern int screenhack_handle_events(bool *);
45extern void screen_redraw(); 49extern void screen_redraw();
46extern void screen_resized(); 50extern void screen_resized();
47 51
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 @@
24#include <sys/time.h> 24#include <sys/time.h>
25 25
26long current_tick = 0; 26long current_tick = 0;
27extern void button_tick(void);
28
29static void msleep(int msec)
30{
31 struct timeval delay;
32
33 delay.tv_sec = msec / 1000;
34 delay.tv_usec = (msec - 1000 * delay.tv_sec) * 1000;
35 select(0, NULL, NULL, NULL, &delay); /* portable sub-second sleep */
36}
27 37
28/* 38/*
29 * This is not a target thread, so it does not fall under the 1 thread at a 39 * 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;
31 */ 41 */
32static void update_tick_thread() 42static void update_tick_thread()
33{ 43{
34 struct timeval start, now, delay; 44 struct timeval start, now;
45 long new_tick;
35 46
36 gettimeofday(&start, NULL); 47 gettimeofday(&start, NULL);
37 while (1) 48 while (1)
38 { 49 {
39 delay.tv_sec = 0; 50 msleep(5); /* check twice per simulated target tick */
40 delay.tv_usec = (1000000/HZ/4); /* check 4 times per target tick */
41 select(0, NULL, NULL, NULL, &delay); /* portable sub-second sleep */
42 gettimeofday(&now, NULL); 51 gettimeofday(&now, NULL);
43 current_tick = (now.tv_sec - start.tv_sec) * HZ 52 new_tick = (now.tv_sec - start.tv_sec) * HZ
44 + (now.tv_usec - start.tv_usec) * HZ / 1000000; 53 + (now.tv_usec - start.tv_usec) / (1000000/HZ);
54 if (new_tick > current_tick)
55 {
56 current_tick = new_tick;
57 button_tick(); /* Dirty call to button.c. This should probably
58 * be implemented as a tick task the same way
59 * as on the target. */
60 }
45 } 61 }
46} 62}
47 63
@@ -73,7 +89,8 @@ void init_threads(void)
73void yield(void) 89void yield(void)
74{ 90{
75 pthread_mutex_unlock(&mp); /* return */ 91 pthread_mutex_unlock(&mp); /* return */
76 pthread_mutex_lock(&mp); /* get it again */ 92 msleep(1); /* prevent busy loop */
93 pthread_mutex_lock(&mp); /* get it again */
77} 94}
78 95
79void newfunc(void (*func)(void)) 96void newfunc(void (*func)(void))
@@ -109,26 +126,8 @@ int create_thread(void* fp, void* sp, int stk_size)
109 126
110void sim_sleep(int ticks) 127void sim_sleep(int ticks)
111{ 128{
112 struct timeval delay;
113
114 pthread_mutex_unlock(&mp); /* return */ 129 pthread_mutex_unlock(&mp); /* return */
115 delay.tv_sec = ticks / HZ; 130 msleep((1000/HZ) * ticks);
116 delay.tv_usec = (ticks - HZ * delay.tv_sec) * (1000000/HZ); 131 pthread_mutex_lock(&mp); /* get it again */
117 select(0, NULL, NULL, NULL, &delay); /* portable subsecond sleep */
118 pthread_mutex_lock(&mp); /* get it again */
119}
120
121void mutex_init(struct mutex *m)
122{
123 (void)m;
124} 132}
125 133
126void mutex_lock(struct mutex *m)
127{
128 (void)m;
129}
130
131void mutex_unlock(struct mutex *m)
132{
133 (void)m;
134}
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;
48static Colormap cmap; 48static Colormap cmap;
49 49
50int display_zoom=1; 50int display_zoom=1;
51
52Display *dpy;
53Window window;
54bool lcd_display_redraw=true; 51bool lcd_display_redraw=true;
55 52
56XrmOptionDescRec options [] = { 53XrmOptionDescRec options [] = {
@@ -96,16 +93,19 @@ void screen_resized(int width, int height)
96 maxx = width; 93 maxx = width;
97 maxy = height; 94 maxy = height;
98 95
96 XtAppLock(app);
99 XSetForeground(dpy, draw_gc, 97 XSetForeground(dpy, draw_gc,
100 get_pixel_resource("background", "Background", dpy, cmap)); 98 get_pixel_resource("background", "Background", dpy, cmap));
101 XFillRectangle(dpy, window, draw_gc, 0, 0, width*display_zoom, 99 XFillRectangle(dpy, window, draw_gc, 0, 0, width*display_zoom,
102 height*display_zoom); 100 height*display_zoom);
101 XtAppUnlock(app);
103 lcd_display_redraw=true; 102 lcd_display_redraw=true;
104 screen_redraw(); 103 screen_redraw();
105} 104}
106 105
107void drawrect(int color, int x1, int y1, int x2, int y2) 106void drawrect(int color, int x1, int y1, int x2, int y2)
108{ 107{
108 XtAppLock(app);
109 if (color==0) 109 if (color==0)
110 XSetForeground(dpy, draw_gc, 110 XSetForeground(dpy, draw_gc,
111 get_pixel_resource("background", "Background", dpy, cmap)); 111 get_pixel_resource("background", "Background", dpy, cmap));
@@ -115,6 +115,7 @@ void drawrect(int color, int x1, int y1, int x2, int y2)
115 115
116 XFillRectangle(dpy, window, draw_gc, x1*display_zoom, y1*display_zoom, 116 XFillRectangle(dpy, window, draw_gc, x1*display_zoom, y1*display_zoom,
117 x2*display_zoom, y2*display_zoom); 117 x2*display_zoom, y2*display_zoom);
118 XtAppUnlock(app);
118} 119}
119 120
120static void help(void) 121static void help(void)
@@ -125,6 +126,7 @@ static void help(void)
125 126
126void drawline(int color, int x1, int y1, int x2, int y2) 127void drawline(int color, int x1, int y1, int x2, int y2)
127{ 128{
129 XtAppLock(app);
128 if (color==0) 130 if (color==0)
129 XSetForeground(dpy, draw_gc, 131 XSetForeground(dpy, draw_gc,
130 get_pixel_resource("background", "Background", dpy, cmap)); 132 get_pixel_resource("background", "Background", dpy, cmap));
@@ -137,10 +139,12 @@ void drawline(int color, int x1, int y1, int x2, int y2)
137 (int)(y1*display_zoom), 139 (int)(y1*display_zoom),
138 (int)(x2*display_zoom), 140 (int)(x2*display_zoom),
139 (int)(y2*display_zoom)); 141 (int)(y2*display_zoom));
142 XtAppUnlock(app);
140} 143}
141 144
142void drawdot(int color, int x, int y) 145void drawdot(int color, int x, int y)
143{ 146{
147 XtAppLock(app);
144 if (color==0) 148 if (color==0)
145 XSetForeground(dpy, draw_gc, 149 XSetForeground(dpy, draw_gc,
146 get_pixel_resource("background", "Background", dpy, cmap)); 150 get_pixel_resource("background", "Background", dpy, cmap));
@@ -150,10 +154,12 @@ void drawdot(int color, int x, int y)
150 154
151 XFillRectangle(dpy, window, draw_gc, x*display_zoom, y*display_zoom, 155 XFillRectangle(dpy, window, draw_gc, x*display_zoom, y*display_zoom,
152 display_zoom, display_zoom); 156 display_zoom, display_zoom);
157 XtAppUnlock(app);
153} 158}
154 159
155void drawdots(int color, struct coordinate *points, int count) 160void drawdots(int color, struct coordinate *points, int count)
156{ 161{
162 XtAppLock(app);
157 if (color==0) 163 if (color==0)
158 XSetForeground(dpy, draw_gc, 164 XSetForeground(dpy, draw_gc,
159 get_pixel_resource("background", "Background", dpy, cmap)); 165 get_pixel_resource("background", "Background", dpy, cmap));
@@ -168,10 +174,12 @@ void drawdots(int color, struct coordinate *points, int count)
168 display_zoom, 174 display_zoom,
169 display_zoom); 175 display_zoom);
170 } 176 }
177 XtAppUnlock(app);
171} 178}
172 179
173void drawrectangles(int color, struct rectangle *points, int count) 180void drawrectangles(int color, struct rectangle *points, int count)
174{ 181{
182 XtAppLock(app);
175 if (color==0) 183 if (color==0)
176 XSetForeground(dpy, draw_gc, 184 XSetForeground(dpy, draw_gc,
177 get_pixel_resource("background", "Background", dpy, cmap)); 185 get_pixel_resource("background", "Background", dpy, cmap));
@@ -186,10 +194,12 @@ void drawrectangles(int color, struct rectangle *points, int count)
186 points[count].width*display_zoom, 194 points[count].width*display_zoom,
187 points[count].height*display_zoom); 195 points[count].height*display_zoom);
188 } 196 }
197 XtAppUnlock(app);
189} 198}
190 199
191void drawtext(int color, int x, int y, char *text) 200void drawtext(int color, int x, int y, char *text)
192{ 201{
202 XtAppLock(app);
193 if (color==0) 203 if (color==0)
194 XSetForeground(dpy, draw_gc, 204 XSetForeground(dpy, draw_gc,
195 get_pixel_resource("background", "Background", dpy, cmap)); 205 get_pixel_resource("background", "Background", dpy, cmap));
@@ -199,13 +209,13 @@ void drawtext(int color, int x, int y, char *text)
199 209
200 XDrawString(dpy, window, draw_gc, x*display_zoom, y*display_zoom, text, 210 XDrawString(dpy, window, draw_gc, x*display_zoom, y*display_zoom, text,
201 strlen(text)); 211 strlen(text));
212 XtAppUnlock(app);
202} 213}
203 214
204/* this is where the applicaton starts */ 215/* this is where the applicaton starts */
205extern void app_main(void); 216extern void app_main(void);
206 217
207void 218void screenhack()
208screenhack (Display *the_dpy, Window the_window)
209{ 219{
210 Bool helpme; 220 Bool helpme;
211 221
@@ -216,9 +226,6 @@ screenhack (Display *the_dpy, Window the_window)
216 226
217 printf(PROGNAME " " ROCKBOXUI_VERSION " (" __DATE__ ")\n"); 227 printf(PROGNAME " " ROCKBOXUI_VERSION " (" __DATE__ ")\n");
218 228
219 dpy=the_dpy;
220 window=the_window;
221
222 init_window(); 229 init_window();
223 230
224 screen_redraw(); 231 screen_redraw();