/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide 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 dpavlin 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