/[pearpc]/src/system/ui/x11/sysx11.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/system/ui/x11/sysx11.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 10098 byte(s)
import upstream CVS
1 /*
2 * PearPC
3 * sysx11.cc
4 *
5 * Copyright (C) 1999-2002 Stefan Weyergraf
6 * Copyright (C) 1999-2004 Sebastian Biallas (sb@biallas.net)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <X11/Xutil.h>
23 #include <X11/keysym.h>
24 #include <sys/time.h>
25
26 #include <csignal>
27 #include <cstdlib>
28 #include <cstdio>
29 #include <unistd.h>
30 #include <cstring>
31
32 #include "system/sysclk.h"
33 #include "system/display.h"
34 #include "system/keyboard.h"
35 #include "system/mouse.h"
36
37 #include "tools/snprintf.h"
38
39 #include "sysx11.h"
40
41 sys_mutex gX11Mutex;
42 Display * gX11Display = NULL;
43 Window gX11Window;
44
45 static uint8 x11_key_to_adb_key[256] = {
46 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
47 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x35,0x12,0x13,0x14,0x15,0x17,0x16,
48 0x1a,0x1c,0x19,0x1d,0x1b,0x18,0x33,0x30,0x0c,0x0d,0x0e,0x0f,0x11,0x10,0x20,0x22,
49 0x1f,0x23,0x21,0x1e,0x24,0x36,0x00,0x01,0x02,0x03,0x05,0x04,0x26,0x28,0x25,0x29,
50 0x27,0x32,0x38,0x2a,0x06,0x07,0x08,0x09,0x0b,0x2d,0x2e,0x2b,0x2f,0x2c,0x38,0x43,
51 0x37,0x31,0xff,0x7a,0x78,0x63,0x76,0x60,0x61,0x62,0x64,0x65,0x6d,0x47,0xff,0x59,
52 0x5b,0x5c,0x4e,0x56,0x57,0x58,0x45,0x53,0x54,0x55,0x52,0x41,0xff,0xff,0x0a,0x67,
53 0x6f,0x73,0x3e,0x74,0x3b,0xff,0x3c,0x77,0x3d,0x79,0x72,0x75,0x4c,0x36,0xff,0xff,
54 0x4b,0x3a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
55 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
56 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
57 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
58 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
59 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
60 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
61 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
62 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
63 };
64
65 static void handleX11Event(const XEvent &event)
66 {
67 static bool visible = true;
68 static bool mapped = true;
69 static bool mouseButton[3] = {false, false, false};
70 bool tmpMouseButton[3];
71
72 switch (event.type) {
73 case GraphicsExpose:
74 case Expose:
75 damageFrameBufferAll();
76 gDisplay->displayShow();
77 break;
78 case KeyRelease: {
79 char buffer[4];
80 SystemEvent ev;
81 XComposeStatus compose;
82 KeySym keysym;
83
84 ev.key.keycode = x11_key_to_adb_key[event.xkey.keycode];
85 if ((ev.key.keycode & 0xff) == 0xff) break;
86 ev.type = sysevKey;
87 ev.key.pressed = false;
88
89 sys_lock_mutex(gX11Mutex);
90 XLookupString((XKeyEvent*)&event, buffer, sizeof buffer, &keysym, &compose);
91 sys_unlock_mutex(gX11Mutex);
92 ev.key.chr = buffer[0];
93
94 gKeyboard->handleEvent(ev);
95 break;
96 }
97 case KeyPress: {
98 char buffer[4];
99 XComposeStatus compose;
100 KeySym keysym;
101
102 SystemEvent ev;
103 ev.key.keycode = x11_key_to_adb_key[event.xkey.keycode];
104 if ((ev.key.keycode & 0xff) == 0xff) break;
105 ev.type = sysevKey;
106 ev.key.pressed = true;
107 ev.key.keycode = x11_key_to_adb_key[event.xkey.keycode];
108
109 sys_lock_mutex(gX11Mutex);
110 XLookupString((XKeyEvent*)&event, buffer, sizeof buffer, &keysym, &compose);
111 sys_unlock_mutex(gX11Mutex);
112 ev.key.chr = buffer[0];
113
114 gKeyboard->handleEvent(ev);
115 break;
116 }
117 case ButtonPress: {
118 SystemEvent ev;
119 ev.type = sysevMouse;
120 memcpy(tmpMouseButton, mouseButton, sizeof (tmpMouseButton));
121 switch (((XButtonEvent *)&event)->button) {
122 case Button1:
123 mouseButton[0] = true;
124 break;
125 case Button2:
126 mouseButton[2] = true;
127 break;
128 case Button3:
129 mouseButton[1] = true;
130 break;
131 }
132 ev.mouse.type = sme_buttonPressed;
133 ev.mouse.button1 = mouseButton[0];
134 ev.mouse.button2 = mouseButton[1];
135 ev.mouse.button3 = mouseButton[2];
136 if (mouseButton[0] != tmpMouseButton[0]) {
137 ev.mouse.dbutton = 1;
138 } else if (mouseButton[1] != tmpMouseButton[1]) {
139 ev.mouse.dbutton = 2;
140 } else if (mouseButton[2] != tmpMouseButton[2]) {
141 ev.mouse.dbutton = 3;
142 } else {
143 ev.mouse.dbutton = 0;
144 }
145 ev.mouse.x = gDisplay->mCurMouseX;
146 ev.mouse.y = gDisplay->mCurMouseY;
147 ev.mouse.relx = 0;
148 ev.mouse.rely = 0;
149
150 gMouse->handleEvent(ev);
151 break;
152 }
153 case ButtonRelease: {
154 SystemEvent ev;
155 ev.type = sysevMouse;
156 memcpy(tmpMouseButton, mouseButton, sizeof (tmpMouseButton));
157 switch (((XButtonEvent *)&event)->button) {
158 case Button1:
159 mouseButton[0] = false;
160 break;
161 case Button2:
162 mouseButton[2] = false;
163 break;
164 case Button3:
165 mouseButton[1] = false;
166 break;
167 }
168 ev.mouse.type = sme_buttonReleased;
169 ev.mouse.button1 = mouseButton[0];
170 ev.mouse.button2 = mouseButton[1];
171 ev.mouse.button3 = mouseButton[2];
172 if (mouseButton[0] != tmpMouseButton[0]) {
173 ev.mouse.dbutton = 1;
174 } else if (mouseButton[1] != tmpMouseButton[1]) {
175 ev.mouse.dbutton = 2;
176 } else if (mouseButton[2] != tmpMouseButton[2]) {
177 ev.mouse.dbutton = 3;
178 } else {
179 ev.mouse.dbutton = 0;
180 }
181 ev.mouse.x = gDisplay->mCurMouseX;
182 ev.mouse.y = gDisplay->mCurMouseY;
183 ev.mouse.relx = 0;
184 ev.mouse.rely = 0;
185
186 gMouse->handleEvent(ev);
187 break;
188 }
189 case MotionNotify: {
190 SystemEvent ev;
191 gDisplay->mCurMouseX = ev.mouse.x = ((XPointerMovedEvent *)&event)->x;
192 gDisplay->mCurMouseY = ev.mouse.y = ((XPointerMovedEvent *)&event)->y;
193 if (gDisplay->mCurMouseX == gDisplay->mHomeMouseX && gDisplay->mCurMouseY == gDisplay->mHomeMouseY) break;
194 if (gDisplay->mCurMouseX == -1) break;
195 ev.type = sysevMouse;
196 ev.mouse.type = sme_motionNotify;
197 ev.mouse.button1 = mouseButton[0];
198 ev.mouse.button2 = mouseButton[1];
199 ev.mouse.button3 = mouseButton[2];
200 ev.mouse.dbutton = 0;
201 ev.mouse.relx = gDisplay->mCurMouseX - gDisplay->mHomeMouseX;
202 ev.mouse.rely = gDisplay->mCurMouseY - gDisplay->mHomeMouseY;
203 if (gDisplay->isMouseGrabbed()) {
204 sys_lock_mutex(gX11Mutex);
205 XWarpPointer(gX11Display, gX11Window, gX11Window, 0, 0, 0, 0, gDisplay->mHomeMouseX, gDisplay->mHomeMouseY);
206 sys_unlock_mutex(gX11Mutex);
207 }
208
209 gMouse->handleEvent(ev);
210 break;
211 }
212 case EnterNotify:
213 gDisplay->mCurMouseX = ((XEnterWindowEvent *)&event)->x;
214 gDisplay->mCurMouseY = ((XEnterWindowEvent *)&event)->y;
215 break;
216 case LeaveNotify:
217 gDisplay->mCurMouseX = gDisplay->mCurMouseY = -1;
218 break;
219 case FocusOut:
220 if (gDisplay->isMouseGrabbed()) gDisplay->setMouseGrab(false);
221 break;
222 case MapNotify:
223 mapped = true;
224 gDisplay->setExposed(visible);
225 break;
226 case UnmapNotify:
227 mapped = false;
228 gDisplay->setExposed(false);
229 break;
230 case VisibilityNotify:
231 visible = (event.xvisibility.state != VisibilityFullyObscured);
232 gDisplay->setExposed(mapped && visible);
233 break;
234 }
235 }
236
237 static inline bool checkHandleX11Event()
238 {
239 XEvent event;
240 uint xevmask = KeyPressMask | KeyReleaseMask | ExposureMask
241 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask
242 | EnterWindowMask | LeaveWindowMask | StructureNotifyMask
243 | VisibilityChangeMask;
244
245 sys_lock_mutex(gX11Mutex);
246 if (!XCheckWindowEvent(gX11Display, gX11Window,
247 xevmask, &event)) {
248 sys_unlock_mutex(gX11Mutex);
249 return false;
250 }
251 sys_unlock_mutex(gX11Mutex);
252
253 handleX11Event(event);
254 return true;
255 }
256
257 static void *X11eventLoop(void *p)
258 {
259 int fd = ConnectionNumber(gX11Display);
260
261 int redraw_interval_msec = gDisplay->mRedraw_ms;
262 uint64 redraw_interval_clk = redraw_interval_msec*sys_get_hiresclk_ticks_per_second()/1000;
263 uint64 clk_per_sec = sys_get_hiresclk_ticks_per_second();
264 uint64 next_redraw_clk = sys_get_hiresclk_ticks();
265
266 while (1) {
267 while (1) {
268 uint64 clk = sys_get_hiresclk_ticks();
269
270 if (clk >= next_redraw_clk) {
271 uint64 d = clk - next_redraw_clk;
272 // We may have missed some scheduled display
273 // redraws. We'll just ignore this and
274 // keep drawing every 'redraw_interval_msec' msecs
275 d %= redraw_interval_clk;
276 next_redraw_clk = clk + redraw_interval_clk - d;
277 gDisplay->displayShow();
278 }
279 struct timeval tm;
280 fd_set zerofds;
281 fd_set xfds;
282
283 FD_ZERO(&zerofds);
284 FD_ZERO(&xfds);
285 FD_SET(fd, &xfds);
286
287 uint64 x = (next_redraw_clk - clk) * 1000000 / clk_per_sec;
288 tm.tv_sec = 0;
289 tm.tv_usec = x;
290
291 if (checkHandleX11Event()) break;
292 if (select(fd+1, &xfds, &zerofds, &zerofds, &tm)) break;
293 }
294
295 // kind of limit the number of X events we handle to give the above
296 // code a chance
297 for (int i=0; i<500; i++) {
298 if (!checkHandleX11Event()) break;
299 }
300 }
301 return NULL;
302 }
303
304 extern SystemDisplay *allocSystemDisplay(const char *title, const DisplayCharacteristics &chr, int redraw_ms, bool fullscreen);
305 extern SystemMouse *allocSystemMouse();
306 extern SystemKeyboard *allocSystemKeyboard();
307
308 void initUI(const char *title, const DisplayCharacteristics &aCharacteristics, int redraw_ms, const KeyboardCharacteristics &keyConfig, bool fullscreen)
309 {
310 // connect to X server
311 char *display = getenv("DISPLAY");
312 if (display == NULL) {
313 display = ":0.0";
314 }
315 gX11Display = XOpenDisplay(display);
316 if (!gX11Display) {
317 ht_printf("can't open X11 display (%s)!\n", display);
318 exit(1);
319 }
320
321 sys_create_mutex(&gX11Mutex);
322
323 gDisplay = allocSystemDisplay(title, aCharacteristics, redraw_ms, fullscreen);
324 gMouse = allocSystemMouse();
325 gKeyboard = allocSystemKeyboard();
326 if(!gKeyboard->setKeyConfig(keyConfig)) {
327 ht_printf("no keyConfig, or is empty");
328 exit(1);
329 }
330 gDisplay->updateTitle();
331
332 sys_thread X11eventLoopThread;
333
334 if (sys_create_thread(&X11eventLoopThread, 0, X11eventLoop, NULL)) {
335 ht_printf("can't create x11 event thread!\n");
336 exit(1);
337 }
338 }
339
340 void doneUI()
341 {
342 XCloseDisplay(gX11Display);
343 }

  ViewVC Help
Powered by ViewVC 1.1.26