/[pearpc]/src/system/ui/x11/sysdisplay.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/sysdisplay.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: 14279 byte(s)
import upstream CVS
1 dpavlin 1 /*
2     * PearPC
3     * sysdisplay.cc - screen access functions for X11
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 <csignal>
23     #include <cstdlib>
24     #include <unistd.h>
25     #include <cstring>
26    
27     #include <X11/Xutil.h>
28    
29     #include "system/display.h"
30     #include "system/types.h"
31     #include "system/systhread.h"
32     #include "system/sysexcept.h"
33     #include "system/sysvaccel.h"
34     #include "tools/data.h"
35     #include "tools/snprintf.h"
36     //#include "configparser.h"
37    
38     #include "sysx11.h"
39    
40     #define DPRINTF(a...)
41     //#define DPRINTF(a...) ht_printf(a)
42    
43     static void findMaskShiftAndSize(int &shift, int &size, uint bitmask)
44     {
45     if (!bitmask) {
46     shift = 0;
47     size = 0;
48     return;
49     }
50     shift = 0;
51     while (!(bitmask & 1)) {
52     shift++;
53     bitmask >>= 1;
54     }
55     size = 0;
56     while (bitmask & 1) {
57     size++;
58     bitmask >>= 1;
59     }
60     }
61    
62     class X11SystemDisplay: public SystemDisplay
63     {
64     byte * mXFrameBuffer;
65     GC mXGC;
66     XImage * mXImage;
67     XImage * mMenuXImage;
68     XImage * mMouseXImage;
69     Colormap mDefaultColormap;
70    
71     DisplayCharacteristics mXChar;
72     char *mTitle;
73     char mCurTitle[200];
74     byte *mouseData;
75     byte *menuData;
76    
77     int bitsPerPixelToXBitmapPad(int bitsPerPixel)
78     {
79     if (bitsPerPixel <= 8) {
80     return 8;
81     } else if (bitsPerPixel <= 16) {
82     return 16;
83     } else {
84     return 32;
85     }
86     }
87     public:
88     X11SystemDisplay(const char *name, const DisplayCharacteristics &aClientChar, int redraw_ms)
89     :SystemDisplay(aClientChar, redraw_ms)
90     {
91     if (bitsPerPixelToXBitmapPad(mClientChar.bytesPerPixel*8) != mClientChar.bytesPerPixel*8) {
92     ht_printf("nope. bytes per pixel is: %d. only 1,2 or 4 are allowed.\n", mClientChar.bytesPerPixel);
93     exit(1);
94     }
95    
96     // mouse
97     mouseData = (byte*)malloc(2 * 2 * mClientChar.bytesPerPixel);
98     memset(mouseData, 0, 2 * 2 * mClientChar.bytesPerPixel);
99    
100     // menu
101     // mMenuHeight = 28;
102     mMenuHeight = 0;
103     menuData = NULL;
104    
105     mXImage = NULL;
106    
107     mClientChar = aClientChar;
108     convertCharacteristicsToHost(mXChar, mClientChar);
109    
110     int screen_num = DefaultScreen(gX11Display);
111     gX11Window = XCreateSimpleWindow(gX11Display,
112     RootWindow(gX11Display, screen_num), 0, 0,
113     mClientChar.width, mClientChar.height+mMenuHeight,
114     0, BlackPixel(gX11Display, screen_num),
115     BlackPixel(gX11Display, screen_num));
116    
117     XStoreName(gX11Display, gX11Window, name);
118    
119     XSetWindowAttributes attr;
120     attr.save_under = 1;
121     attr.backing_store = Always;
122     XChangeWindowAttributes(gX11Display, gX11Window, CWSaveUnder|CWBackingStore, &attr);
123    
124     mDefaultColormap = DefaultColormap(gX11Display, screen_num);
125    
126     XSelectInput(gX11Display, gX11Window,
127     ExposureMask | KeyPressMask | KeyReleaseMask
128     | ButtonPressMask | ButtonReleaseMask | PointerMotionMask
129     | EnterWindowMask | LeaveWindowMask | StructureNotifyMask
130     | VisibilityChangeMask | FocusChangeMask);
131    
132     XMapWindow(gX11Display, gX11Window);
133    
134     XEvent event;
135     XNextEvent(gX11Display, &event);
136    
137     uint XDepth = mXChar.redSize + mXChar.greenSize + mXChar.blueSize;
138    
139     mMouseXImage = XCreateImage(gX11Display, DefaultVisual(gX11Display, screen_num),
140     XDepth, ZPixmap, 0, (char*)mouseData,
141     2, 2,
142     mXChar.bytesPerPixel*8, 0);
143    
144     mXGC = DefaultGC(gX11Display, screen_num);
145    
146     // setup interna
147     gFrameBuffer = NULL;
148     reinitChar();
149    
150     // clear fb once on startup
151     memset(gFrameBuffer, 0, mClientChar.width *
152     mClientChar.height * mClientChar.bytesPerPixel);
153    
154     #if 0
155     fprintf(stderr, "X Server display characteristics:\n");
156     dumpDisplayChar(mXChar);
157     fprintf(stderr, "Client display characteristics:\n");
158     dumpDisplayChar(mClientChar);
159     #endif
160    
161     // finally set title
162     mTitle = strdup(name);
163     }
164    
165     virtual ~X11SystemDisplay()
166     {
167     gX11Display = NULL;
168     free(mTitle);
169     free(mouseData);
170     free(gFrameBuffer);
171     if (menuData) free(menuData);
172     }
173    
174     virtual void finishMenu()
175     {
176     menuData = (byte*)malloc(mXChar.width *
177     mMenuHeight * mXChar.bytesPerPixel);
178     mMenuXImage = XCreateImage(gX11Display, DefaultVisual(gX11Display, DefaultScreen(gX11Display)),
179     mXChar.redSize+mXChar.greenSize+mXChar.blueSize, ZPixmap, 0, (char*)menuData,
180     mXChar.width, mMenuHeight,
181     mXChar.bytesPerPixel*8, 0);
182    
183     // Is this ugly? Yes!
184     fillRGB(0, 0, mClientChar.width, mClientChar.height, MK_RGB(0xff, 0xff, 0xff));
185     drawMenu();
186     // convertDisplayClientToServer(0, mClientChar.height-1);
187     if (mXFrameBuffer) {
188     sys_convert_display(mClientChar, mXChar, gFrameBuffer, mXFrameBuffer, 0, mClientChar.height-1);
189     memmove(menuData, mXFrameBuffer, mXChar.width * mMenuHeight
190     * mXChar.bytesPerPixel);
191     } else {
192     memmove(menuData, gFrameBuffer, mXChar.width * mMenuHeight
193     * mXChar.bytesPerPixel);
194     }
195     }
196    
197     /*
198     * must be called with gX11Mutex locked
199     */
200     void reinitChar()
201     {
202     gFrameBuffer = (byte*)realloc(gFrameBuffer, mClientChar.width *
203     mClientChar.height * mClientChar.bytesPerPixel);
204     damageFrameBufferAll();
205    
206     mHomeMouseX = mClientChar.width / 2;
207     mHomeMouseY = mClientChar.height / 2;
208    
209     uint XDepth = mXChar.redSize + mXChar.greenSize + mXChar.blueSize;
210     int screen_num = DefaultScreen(gX11Display);
211    
212     if (mXImage) XDestroyImage(mXImage); // no need to free gXFrameBuffer. XDeleteImage does this.
213    
214     // Maybe client and (X-)server display characteristics match
215     if (0 && memcmp(&mClientChar, &mXChar, sizeof (mClientChar)) == 0) {
216     // fprintf(stderr, "client and server display characteristics match!!\n");
217     mXFrameBuffer = NULL;
218    
219     mXImage = XCreateImage(gX11Display, DefaultVisual(gX11Display, screen_num),
220     XDepth, ZPixmap, 0, (char*)gFrameBuffer,
221     mXChar.width, mXChar.height,
222     mXChar.bytesPerPixel*8, 0);
223     } else {
224     // Otherwise we need a second framebuffer
225     // fprintf(stderr, "client and server display characteristics DONT match :-(\n");
226     mXFrameBuffer = (byte*)malloc(mXChar.width
227     * mXChar.height * mXChar.bytesPerPixel);
228    
229     mXImage = XCreateImage(gX11Display, DefaultVisual(gX11Display, screen_num),
230     XDepth, ZPixmap, 0, (char*)mXFrameBuffer,
231     mXChar.width, mXChar.height,
232     mXChar.bytesPerPixel*8, 0);
233     }
234     }
235    
236     virtual void convertCharacteristicsToHost(DisplayCharacteristics &aHostChar, const DisplayCharacteristics &aClientChar)
237     {
238     sys_lock_mutex(gX11Mutex);
239     int screen_num = DefaultScreen(gX11Display);
240    
241     XVisualInfo info_tmpl;
242     int ninfo;
243     info_tmpl.screen = screen_num;
244     info_tmpl.visualid = XVisualIDFromVisual(DefaultVisual(gX11Display, screen_num));
245     XVisualInfo *info = XGetVisualInfo(gX11Display,
246     VisualScreenMask | VisualIDMask, &info_tmpl, &ninfo);
247     /*
248     fprintf(stderr, "got %d XVisualInfo's:\n", ninfo);
249     for (int i=0; i<ninfo; i++) {
250     fprintf(stderr, "XVisualInfo %d:\n", i);
251     fprintf(stderr, "\tscreen = %d:\n", info[i].screen);
252     fprintf(stderr, "\tdepth = %d:\n", info[i].depth);
253     fprintf(stderr, "\tred = %x:\n", info[i].red_mask);
254     fprintf(stderr, "\tgreen = %x:\n", info[i].green_mask);
255     fprintf(stderr, "\tblue = %x:\n", info[i].blue_mask);
256     }
257     */
258     // generate X characteristics from visual info
259     aHostChar = aClientChar;
260     if (ninfo) {
261     aHostChar.bytesPerPixel = bitsPerPixelToXBitmapPad(info->depth) >> 3;
262     aHostChar.scanLineLength = aHostChar.bytesPerPixel * aHostChar.width;
263     findMaskShiftAndSize(aHostChar.redShift, aHostChar.redSize, info->red_mask);
264     findMaskShiftAndSize(aHostChar.greenShift, aHostChar.greenSize, info->green_mask);
265     findMaskShiftAndSize(aHostChar.blueShift, aHostChar.blueSize, info->blue_mask);
266     } else {
267     sys_unlock_mutex(gX11Mutex);
268     printf("ARGH! Couldn't get XVisualInfo...\n");
269     exit(1);
270     }
271     XFree(info);
272     sys_unlock_mutex(gX11Mutex);
273     }
274    
275     virtual bool changeResolution(const DisplayCharacteristics &aClientChar)
276     {
277     if (aClientChar.width == mClientChar.width
278     && aClientChar.height == mClientChar.height
279     && aClientChar.bytesPerPixel == mClientChar.bytesPerPixel) {
280     return true;
281     } else {
282     return false;
283     }
284     }
285    
286     virtual bool doChangeResolution(const DisplayCharacteristics &aClientChar)
287     {
288     /*
289     * I don't understand how XResizeWindow is supposed to work
290     * If you understand, feel free to fix this:
291     */
292     DisplayCharacteristics oldClientChar = mClientChar;
293     DisplayCharacteristics oldHostChar = mXChar;
294     DisplayCharacteristics newXChar;
295    
296     convertCharacteristicsToHost(newXChar, aClientChar);
297     sys_lock_mutex(gX11Mutex);
298     mXChar = newXChar;
299     mClientChar = aClientChar;
300     if (bitsPerPixelToXBitmapPad(mXChar.bytesPerPixel*8) != mXChar.bytesPerPixel*8) {
301     fprintf(stderr, "bitsPerPixelToXBitmapPad(%d) failed\n", mXChar.bytesPerPixel*8);
302     mClientChar = oldClientChar;
303     mXChar = oldHostChar;
304     sys_unlock_mutex(gX11Mutex);
305     return false;
306     }
307    
308     XResizeWindow(gX11Display, gX11Window, mXChar.width, mXChar.height+mMenuHeight);
309    
310     XSync(gX11Display, False);
311    
312     XWindowAttributes attr;
313     if (!XGetWindowAttributes(gX11Display, gX11Window, &attr)) {
314     fprintf(stderr, "Couldn't get X window size\n");
315     mClientChar = oldClientChar;
316     mXChar = oldHostChar;
317     XResizeWindow(gX11Display, gX11Window, mXChar.width, mXChar.height+mMenuHeight);
318     sys_unlock_mutex(gX11Mutex);
319     return false;
320     }
321    
322     if ((int)attr.width < mXChar.width || (int)attr.height < (mXChar.height+mMenuHeight)) {
323     fprintf(stderr, "Couldn't change X window size to %dx%d\n", mXChar.width, mXChar.height);
324     fprintf(stderr, "Reported new size: %dx(%d+%d)\n", attr.width, attr.height-mMenuHeight, mMenuHeight);
325     mClientChar = oldClientChar;
326     mXChar = oldHostChar;
327     XResizeWindow(gX11Display, gX11Window, mXChar.width, mXChar.height+mMenuHeight);
328     sys_unlock_mutex(gX11Mutex);
329     return false;
330     }
331    
332     reinitChar();
333     sys_unlock_mutex(gX11Mutex);
334     fprintf(stderr, "Change resolution OK\n");
335     return true;
336     }
337    
338     virtual void getHostCharacteristics(Container &modes)
339     {
340     // FIXME: implement me
341     }
342    
343     virtual int getKeybLEDs()
344     {
345     return 0;
346     }
347    
348     virtual void setKeybLEDs(int leds)
349     {
350     }
351    
352     virtual void updateTitle()
353     {
354     String key;
355     int key_toggle_mouse_grab = gKeyboard->getKeyConfig().key_toggle_mouse_grab;
356     SystemKeyboard::convertKeycodeToString(key, key_toggle_mouse_grab);
357     ht_snprintf(mCurTitle, sizeof mCurTitle, "%s - [%s %s mouse]", mTitle,key.contentChar(), (isMouseGrabbed() ? "disables" : "enables"));
358     XTextProperty name_prop;
359     char *mCurTitlep = mCurTitle;
360     XStringListToTextProperty(&mCurTitlep, 1, &name_prop);
361     XSetWMName(gX11Display, gX11Window, &name_prop);
362     }
363    
364     virtual int toString(char *buf, int buflen) const
365     {
366     return snprintf(buf, buflen, "POSIX X11");
367     }
368    
369     virtual void setMouseGrab(bool enable)
370     {
371     SystemDisplay::setMouseGrab(enable);
372     updateTitle();
373     if (enable) {
374     mResetMouseX = mCurMouseX;
375     mResetMouseY = mCurMouseY;
376    
377     static Cursor cursor;
378     static bool cursor_created = false;
379    
380     static char shape_bits[16*16] = {0, };
381     static char mask_bits[16*16] = {0, };
382    
383     if (!cursor_created) {
384     Pixmap shape, mask;
385     XColor white, black;
386     shape = XCreatePixmapFromBitmapData(gX11Display,
387     RootWindow(gX11Display, DefaultScreen(gX11Display)),
388     shape_bits, 16, 16, 1, 0, 1);
389     mask = XCreatePixmapFromBitmapData(gX11Display,
390     RootWindow(gX11Display, DefaultScreen(gX11Display)),
391     mask_bits, 16, 16, 1, 0, 1);
392     XParseColor(gX11Display, mDefaultColormap, "black", &black);
393     XParseColor(gX11Display, mDefaultColormap, "white", &white);
394     cursor = XCreatePixmapCursor(gX11Display, shape, mask,
395     &white, &black, 1, 1);
396     cursor_created = true;
397     }
398    
399     XDefineCursor(gX11Display, gX11Window, cursor);
400     XWarpPointer(gX11Display, gX11Window, gX11Window, 0, 0, 0, 0, mHomeMouseX, mHomeMouseY);
401     } else {
402     XWarpPointer(gX11Display, gX11Window, gX11Window, 0, 0, 0, 0, mResetMouseX, mResetMouseY);
403     XUndefineCursor(gX11Display, gX11Window);
404     }
405     }
406    
407     virtual void displayShow()
408     {
409     if (!isExposed()) return;
410    
411     int firstDamagedLine, lastDamagedLine;
412     // We've got problems with races here because gcard_write1/2/4
413     // might set gDamageAreaFirstAddr, gDamageAreaLastAddr.
414     // We can't use mutexes in gcard for speed reasons. So we'll
415     // try to minimize the probability of loosing the race.
416     if (gDamageAreaFirstAddr > gDamageAreaLastAddr+3) {
417     return;
418     }
419     uint damageAreaFirstAddr = gDamageAreaFirstAddr;
420     uint damageAreaLastAddr = gDamageAreaLastAddr;
421     healFrameBuffer();
422     // end of race
423     damageAreaLastAddr += 3; // this is a hack. For speed reasons we
424     // inaccurately set gDamageAreaLastAddr
425     // to the first (not last) byte accessed
426     // accesses are up to 4 bytes "long".
427    
428     firstDamagedLine = damageAreaFirstAddr / (mClientChar.width * mClientChar.bytesPerPixel);
429     lastDamagedLine = damageAreaLastAddr / (mClientChar.width * mClientChar.bytesPerPixel);
430     // Overflow may happen, because of the hack used above
431     // and others, that set lastAddr = 0xfffffff0 (damageFrameBufferAll())
432     if (lastDamagedLine >= mClientChar.height) {
433     lastDamagedLine = mClientChar.height-1;
434     }
435    
436     if (mXFrameBuffer) {
437     sys_convert_display(mClientChar, mXChar, gFrameBuffer, mXFrameBuffer, firstDamagedLine, lastDamagedLine);
438     }
439    
440     sys_lock_mutex(gX11Mutex);
441     // draw menu
442     /* XPutImage(gX11Display, gX11Window, mXGC, mMenuXImage, 0, 0, 0, 0,
443     mClientChar.width,
444     mMenuHeight);*/
445    
446     XPutImage(gX11Display, gX11Window, mXGC, mXImage,
447     0,
448     firstDamagedLine,
449     0,
450     mMenuHeight+firstDamagedLine,
451     mClientChar.width,
452     lastDamagedLine-firstDamagedLine+1);
453    
454     /* if (mHWCursorVisible) {
455     XPutImage(gX11Display, gX11Window, mXGC, mMouseXImage, 0, 0,
456     mHWCursorX, mHWCursorY, 2, 2);
457     }*/
458     sys_unlock_mutex(gX11Mutex);
459     }
460     };
461    
462     SystemDisplay *allocSystemDisplay(const char *title, const DisplayCharacteristics &chr, int redraw_ms, bool fullscreen)
463     {
464     if (gDisplay) return NULL;
465     return new X11SystemDisplay(title, chr, redraw_ms);
466     }

  ViewVC Help
Powered by ViewVC 1.1.26