/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
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 /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 478 - (hide annotations)
Sun Oct 5 12:07:56 2003 UTC (20 years, 7 months ago) by matthewc
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 41009 byte(s)
Fix crash bug when dsp_fd = -1.

1 forsberg 415 /* -*- c-basic-offset: 8 -*-
2 matty 6 rdesktop: A Remote Desktop Protocol client.
3 matthewc 38 User interface services - X Window System
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
5 n-ki 52
6 matty 6 This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 n-ki 52
11 matty 6 This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15 n-ki 52
16 matty 6 You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21 matty 10 #include <X11/Xlib.h>
22 matty 28 #include <X11/Xutil.h>
23 matty 10 #include <time.h>
24 matty 33 #include <errno.h>
25 matty 10 #include "rdesktop.h"
26 forsberg 415 #include "xproto.h"
27 matty 6
28 jsorg71 447 extern int g_width;
29     extern int g_height;
30     extern BOOL g_sendmotion;
31     extern BOOL g_fullscreen;
32 jsorg71 450 extern BOOL g_grab_keyboard;
33     extern BOOL g_hide_decorations;
34     extern char g_title[];
35 jsorg71 438 extern int g_server_bpp;
36 jsorg71 450 extern int g_win_button_size;
37 jsorg71 447 BOOL g_enable_compose = False;
38     BOOL g_focused;
39     BOOL g_mouse_in_wnd;
40 matty 10
41 jsorg71 450 Display *g_display;
42     Time g_last_gesturetime;
43     static int g_x_socket;
44     static Screen *g_screen;
45     Window g_wnd;
46     static GC g_gc;
47     static Visual *g_visual;
48     static int g_depth;
49     static int g_bpp;
50     static XIM g_IM;
51     static XIC g_IC;
52     static XModifierKeymap *g_mod_map;
53     static Cursor g_current_cursor;
54     static Atom g_protocol_atom, g_kill_atom;
55 matty 29
56 matty 33 /* endianness */
57 jsorg71 450 static BOOL g_host_be;
58     static BOOL g_xserver_be;
59 matty 33
60     /* software backing store */
61 jsorg71 450 static BOOL g_ownbackstore;
62     static Pixmap g_backstore;
63 matty 31
64 astrand 342 /* Moving in single app mode */
65 jsorg71 450 static BOOL g_moving_wnd;
66     static int g_move_x_offset = 0;
67     static int g_move_y_offset = 0;
68 astrand 342
69 matthewc 474 #ifdef WITH_RDPSND
70     extern int g_dsp_fd;
71     extern BOOL g_dsp_busy;
72     #endif
73    
74 astrand 262 /* MWM decorations */
75     #define MWM_HINTS_DECORATIONS (1L << 1)
76     #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
77     typedef struct
78     {
79 matthewc 301 uint32 flags;
80     uint32 functions;
81     uint32 decorations;
82     sint32 inputMode;
83     uint32 status;
84 astrand 262 }
85     PropMotifWmHints;
86    
87 jsorg71 316 typedef struct
88     {
89     uint32 red;
90     uint32 green;
91     uint32 blue;
92     }
93     PixelColour;
94 astrand 262
95 forsberg 415
96 matty 31 #define FILL_RECTANGLE(x,y,cx,cy)\
97     { \
98 jsorg71 450 XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
99     if (g_ownbackstore) \
100     XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
101 matty 31 }
102    
103 matthewc 296 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
104 jsorg71 281 { \
105 jsorg71 450 XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
106 jsorg71 281 }
107    
108 matty 33 /* colour maps */
109 jsorg71 450 BOOL g_owncolmap = False;
110     static Colormap g_xcolmap;
111     static uint32 *g_colmap = NULL;
112 matty 10
113 jsorg71 450 #define TRANSLATE(col) ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : translate_colour(g_colmap[col]) )
114     #define SET_FOREGROUND(col) XSetForeground(g_display, g_gc, TRANSLATE(col));
115     #define SET_BACKGROUND(col) XSetBackground(g_display, g_gc, TRANSLATE(col));
116 matty 28
117     static int rop2_map[] = {
118     GXclear, /* 0 */
119     GXnor, /* DPon */
120     GXandInverted, /* DPna */
121     GXcopyInverted, /* Pn */
122     GXandReverse, /* PDna */
123     GXinvert, /* Dn */
124     GXxor, /* DPx */
125     GXnand, /* DPan */
126     GXand, /* DPa */
127     GXequiv, /* DPxn */
128     GXnoop, /* D */
129     GXorInverted, /* DPno */
130     GXcopy, /* P */
131     GXorReverse, /* PDno */
132     GXor, /* DPo */
133     GXset /* 1 */
134     };
135    
136 jsorg71 450 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
137     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
138 matty 29
139 astrand 319 static void
140 astrand 262 mwm_hide_decorations(void)
141     {
142     PropMotifWmHints motif_hints;
143     Atom hintsatom;
144    
145     /* setup the property */
146     motif_hints.flags = MWM_HINTS_DECORATIONS;
147     motif_hints.decorations = 0;
148    
149     /* get the atom for the property */
150 jsorg71 450 hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
151 astrand 262 if (!hintsatom)
152     {
153 matthewc 297 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
154 astrand 262 return;
155     }
156    
157 jsorg71 450 XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
158 astrand 262 (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
159     }
160    
161 astrand 319 static PixelColour
162 jsorg71 316 split_colour15(uint32 colour)
163 jsorg71 311 {
164 jsorg71 316 PixelColour rv;
165     rv.red = (colour & 0x7c00) >> 10;
166     rv.red = (rv.red * 0xff) / 0x1f;
167     rv.green = (colour & 0x03e0) >> 5;
168     rv.green = (rv.green * 0xff) / 0x1f;
169     rv.blue = (colour & 0x1f);
170     rv.blue = (rv.blue * 0xff) / 0x1f;
171     return rv;
172 jsorg71 311 }
173    
174 astrand 319 static PixelColour
175 jsorg71 316 split_colour16(uint32 colour)
176 jsorg71 311 {
177 jsorg71 316 PixelColour rv;
178     rv.red = (colour & 0xf800) >> 11;
179     rv.red = (rv.red * 0xff) / 0x1f;
180     rv.green = (colour & 0x07e0) >> 5;
181     rv.green = (rv.green * 0xff) / 0x3f;
182     rv.blue = (colour & 0x001f);
183     rv.blue = (rv.blue * 0xff) / 0x1f;
184     return rv;
185 jsorg71 311 }
186    
187 astrand 319 static PixelColour
188 jsorg71 316 split_colour24(uint32 colour)
189 jsorg71 311 {
190 jsorg71 316 PixelColour rv;
191     rv.blue = (colour & 0xff0000) >> 16;
192     rv.green = (colour & 0xff00) >> 8;
193     rv.red = (colour & 0xff);
194     return rv;
195 jsorg71 311 }
196    
197 astrand 319 static uint32
198 astrand 318 make_colour16(PixelColour pc)
199 jsorg71 316 {
200     pc.red = (pc.red * 0x1f) / 0xff;
201     pc.green = (pc.green * 0x3f) / 0xff;
202     pc.blue = (pc.blue * 0x1f) / 0xff;
203     return (pc.red << 11) | (pc.green << 5) | pc.blue;
204     }
205    
206 astrand 319 static uint32
207 astrand 318 make_colour24(PixelColour pc)
208 jsorg71 316 {
209 jsorg71 472 if (g_xserver_be)
210     {
211     return pc.red | (pc.green << 8) | (pc.blue << 16);
212     }
213     else
214     {
215     return (pc.red << 16) | (pc.green << 8) | pc.blue;
216     }
217 jsorg71 316 }
218    
219 astrand 319 static uint32
220 astrand 318 make_colour32(PixelColour pc)
221 jsorg71 316 {
222 jsorg71 472 if (g_xserver_be)
223     {
224     return pc.red | (pc.green << 8) | (pc.blue << 16);
225     }
226     else
227     {
228     return (pc.red << 16) | (pc.green << 8) | pc.blue;
229     }
230 jsorg71 316 }
231    
232 jsorg71 311 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
233     #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
234     #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
235     x = (x << 16) | (x >> 16); }
236    
237     static uint32
238     translate_colour(uint32 colour)
239     {
240 jsorg71 438 switch (g_server_bpp)
241 jsorg71 311 {
242 jsorg71 316 case 15:
243 jsorg71 450 switch (g_bpp)
244 jsorg71 316 {
245     case 16:
246     colour = make_colour16(split_colour15(colour));
247     break;
248     case 24:
249     colour = make_colour24(split_colour15(colour));
250     break;
251     case 32:
252     colour = make_colour32(split_colour15(colour));
253     break;
254     }
255     break;
256 jsorg71 311 case 16:
257 jsorg71 450 switch (g_bpp)
258 jsorg71 311 {
259     case 16:
260     break;
261     case 24:
262 jsorg71 316 colour = make_colour24(split_colour16(colour));
263 jsorg71 311 break;
264     case 32:
265 jsorg71 316 colour = make_colour32(split_colour16(colour));
266 jsorg71 311 break;
267     }
268     break;
269     case 24:
270 jsorg71 450 switch (g_bpp)
271 jsorg71 311 {
272 jsorg71 316 case 16:
273     colour = make_colour16(split_colour24(colour));
274     break;
275 jsorg71 311 case 24:
276     break;
277     case 32:
278 jsorg71 316 colour = make_colour32(split_colour24(colour));
279 jsorg71 311 break;
280     }
281     break;
282     }
283 jsorg71 450 switch (g_bpp)
284 jsorg71 311 {
285     case 16:
286 jsorg71 450 if (g_host_be != g_xserver_be)
287 jsorg71 311 BSWAP16(colour);
288     break;
289    
290     case 24:
291 jsorg71 450 if (g_xserver_be)
292 jsorg71 311 BSWAP24(colour);
293     break;
294    
295     case 32:
296 jsorg71 450 if (g_host_be != g_xserver_be)
297 jsorg71 311 BSWAP32(colour);
298     break;
299     }
300    
301     return colour;
302     }
303    
304 matty 28 static void
305 jsorg71 311 translate8to8(uint8 * data, uint8 * out, uint8 * end)
306 matty 28 {
307 matty 29 while (out < end)
308 jsorg71 450 *(out++) = (uint8) g_colmap[*(data++)];
309 matty 29 }
310 matty 28
311 matty 29 static void
312 jsorg71 311 translate8to16(uint8 * data, uint16 * out, uint16 * end)
313 matty 29 {
314     while (out < end)
315 jsorg71 450 *(out++) = (uint16) g_colmap[*(data++)];
316 matty 29 }
317    
318 jsorg71 316 /* little endian - conversion happens when colourmap is built */
319 jsorg71 311 static void
320 jsorg71 316 translate8to24(uint8 * data, uint8 * out, uint8 * end)
321 jsorg71 311 {
322 jsorg71 316 uint32 value;
323    
324 jsorg71 311 while (out < end)
325 jsorg71 316 {
326 jsorg71 450 value = g_colmap[*(data++)];
327 jsorg71 316 *(out++) = value;
328     *(out++) = value >> 8;
329     *(out++) = value >> 16;
330     }
331 jsorg71 311 }
332    
333 matty 29 static void
334 jsorg71 316 translate8to32(uint8 * data, uint32 * out, uint32 * end)
335 matty 29 {
336 jsorg71 316 while (out < end)
337 jsorg71 450 *(out++) = g_colmap[*(data++)];
338 jsorg71 316 }
339    
340     /* todo the remaining translate function might need some big endian check ?? */
341    
342     static void
343     translate15to16(uint16 * data, uint16 * out, uint16 * end)
344     {
345     while (out < end)
346     *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
347     }
348    
349     static void
350     translate15to24(uint16 * data, uint8 * out, uint8 * end)
351     {
352 matty 29 uint32 value;
353    
354     while (out < end)
355 matty 28 {
356 jsorg71 316 value = make_colour24(split_colour15(*(data++)));
357 matty 29 *(out++) = value;
358     *(out++) = value >> 8;
359     *(out++) = value >> 16;
360 matty 28 }
361     }
362    
363     static void
364 jsorg71 316 translate15to32(uint16 * data, uint32 * out, uint32 * end)
365     {
366 jsorg71 472 uint16 pixel;
367    
368 jsorg71 316 while (out < end)
369 jsorg71 472 {
370     if (g_host_be)
371     {
372     pixel = *(data++);
373     pixel = (pixel & 0xff) << 8 | (pixel & 0xff00) >> 8;
374     *(out++) = make_colour32(split_colour15(pixel));
375     }
376     else
377     {
378     *(out++) = make_colour32(split_colour15(*(data++)));
379     }
380     }
381 jsorg71 316 }
382    
383     static void
384     translate16to16(uint16 * data, uint16 * out, uint16 * end)
385     {
386     while (out < end)
387     *(out++) = (uint16) (*(data++));
388     }
389    
390    
391     static void
392 jsorg71 311 translate16to24(uint16 * data, uint8 * out, uint8 * end)
393 matty 28 {
394 jsorg71 311 uint32 value;
395    
396 matty 29 while (out < end)
397 jsorg71 311 {
398 jsorg71 316 value = make_colour24(split_colour16(*(data++)));
399 jsorg71 311 *(out++) = value;
400     *(out++) = value >> 8;
401     *(out++) = value >> 16;
402     }
403     }
404    
405     static void
406 jsorg71 316 translate16to32(uint16 * data, uint32 * out, uint32 * end)
407 jsorg71 311 {
408 jsorg71 472 uint16 pixel;
409    
410 jsorg71 311 while (out < end)
411 jsorg71 472 {
412     if (g_host_be)
413     {
414     pixel = *(data++);
415     pixel = (pixel & 0xff) << 8 | (pixel & 0xff00) >> 8;
416     *(out++) = make_colour32(split_colour16(pixel));
417     }
418     else
419     {
420     *(out++) = make_colour32(split_colour16(*(data++)));
421     }
422     }
423 matty 28 }
424    
425 jsorg71 311 static void
426 jsorg71 316 translate24to16(uint8 * data, uint16 * out, uint16 * end)
427 jsorg71 311 {
428 jsorg71 316 uint32 pixel = 0;
429 jsorg71 311 while (out < end)
430 jsorg71 316 {
431     pixel = *(data++) << 16;
432     pixel |= *(data++) << 8;
433     pixel |= *(data++);
434     *(out++) = (uint16) make_colour16(split_colour24(pixel));
435     }
436 jsorg71 311 }
437    
438 jsorg71 316 static void
439     translate24to24(uint8 * data, uint8 * out, uint8 * end)
440     {
441     while (out < end)
442     {
443     *(out++) = (*(data++));
444     }
445     }
446    
447     static void
448     translate24to32(uint8 * data, uint32 * out, uint32 * end)
449     {
450     uint32 pixel = 0;
451     while (out < end)
452     {
453 jsorg71 472 if (g_host_be)
454     {
455     pixel = *(data++) << 16;
456     pixel |= *(data++) << 8;
457     pixel |= *(data++);
458     }
459     else
460     {
461     pixel = *(data++);
462     pixel |= *(data++) << 8;
463     pixel |= *(data++) << 16;
464     }
465 jsorg71 316 *(out++) = pixel;
466     }
467     }
468    
469 matty 29 static uint8 *
470 astrand 64 translate_image(int width, int height, uint8 * data)
471 matty 28 {
472 jsorg71 450 int size = width * height * g_bpp / 8;
473 forsberg 415 uint8 *out = (uint8 *) xmalloc(size);
474 matty 29 uint8 *end = out + size;
475    
476 jsorg71 438 switch (g_server_bpp)
477 jsorg71 311 {
478 jsorg71 316 case 24:
479 jsorg71 450 switch (g_bpp)
480 jsorg71 316 {
481     case 32:
482     translate24to32(data, (uint32 *) out, (uint32 *) end);
483     break;
484     case 24:
485     translate24to24(data, out, end);
486     break;
487     case 16:
488     translate24to16(data, (uint16 *) out, (uint16 *) end);
489     break;
490     }
491 matty 29 break;
492     case 16:
493 jsorg71 450 switch (g_bpp)
494 jsorg71 316 {
495     case 32:
496 astrand 318 translate16to32((uint16 *) data, (uint32 *) out,
497     (uint32 *) end);
498 jsorg71 316 break;
499     case 24:
500     translate16to24((uint16 *) data, out, end);
501     break;
502     case 16:
503 astrand 318 translate16to16((uint16 *) data, (uint16 *) out,
504     (uint16 *) end);
505 jsorg71 316 break;
506     }
507 matty 29 break;
508 jsorg71 316 case 15:
509 jsorg71 450 switch (g_bpp)
510 jsorg71 316 {
511     case 32:
512 astrand 318 translate15to32((uint16 *) data, (uint32 *) out,
513     (uint32 *) end);
514 jsorg71 316 break;
515     case 24:
516     translate15to24((uint16 *) data, out, end);
517     break;
518     case 16:
519 astrand 318 translate15to16((uint16 *) data, (uint16 *) out,
520     (uint16 *) end);
521 jsorg71 316 break;
522     }
523 matty 29 break;
524 jsorg71 316 case 8:
525 jsorg71 450 switch (g_bpp)
526 jsorg71 316 {
527     case 8:
528     translate8to8(data, out, end);
529     break;
530     case 16:
531     translate8to16(data, (uint16 *) out, (uint16 *) end);
532     break;
533     case 24:
534     translate8to24(data, out, end);
535     break;
536     case 32:
537     translate8to32(data, (uint32 *) out, (uint32 *) end);
538     break;
539     }
540 matty 29 break;
541     }
542     return out;
543 matty 28 }
544    
545 astrand 118 BOOL
546 matthewc 209 get_key_state(unsigned int state, uint32 keysym)
547 astrand 102 {
548 matthewc 203 int modifierpos, key, keysymMask = 0;
549 astrand 102 int offset;
550    
551 jsorg71 450 KeyCode keycode = XKeysymToKeycode(g_display, keysym);
552 astrand 102
553     if (keycode == NoSymbol)
554     return False;
555    
556     for (modifierpos = 0; modifierpos < 8; modifierpos++)
557     {
558 jsorg71 450 offset = g_mod_map->max_keypermod * modifierpos;
559 astrand 102
560 jsorg71 450 for (key = 0; key < g_mod_map->max_keypermod; key++)
561 astrand 102 {
562 jsorg71 450 if (g_mod_map->modifiermap[offset + key] == keycode)
563 matthewc 203 keysymMask |= 1 << modifierpos;
564 astrand 102 }
565     }
566    
567 matthewc 203 return (state & keysymMask) ? True : False;
568 astrand 102 }
569    
570 jsorg71 81 BOOL
571 matthewc 192 ui_init(void)
572 jsorg71 81 {
573 matthewc 121 XPixmapFormatValues *pfm;
574     uint16 test;
575     int i;
576    
577 jsorg71 450 g_display = XOpenDisplay(NULL);
578     if (g_display == NULL)
579 jsorg71 81 {
580 matthewc 210 error("Failed to open display: %s\n", XDisplayName(NULL));
581 jsorg71 81 return False;
582     }
583 matthewc 121
584 jsorg71 450 g_x_socket = ConnectionNumber(g_display);
585     g_screen = DefaultScreenOfDisplay(g_display);
586     g_visual = DefaultVisualOfScreen(g_screen);
587     g_depth = DefaultDepthOfScreen(g_screen);
588 matthewc 121
589 jsorg71 450 pfm = XListPixmapFormats(g_display, &i);
590 matthewc 121 if (pfm != NULL)
591     {
592     /* Use maximum bpp for this depth - this is generally
593     desirable, e.g. 24 bits->32 bits. */
594     while (i--)
595     {
596 jsorg71 450 if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
597 matthewc 121 {
598 jsorg71 450 g_bpp = pfm[i].bits_per_pixel;
599 matthewc 121 }
600     }
601     XFree(pfm);
602     }
603    
604 jsorg71 450 if (g_bpp < 8)
605 matthewc 121 {
606     error("Less than 8 bpp not currently supported.\n");
607 jsorg71 450 XCloseDisplay(g_display);
608 matthewc 121 return False;
609     }
610    
611 jsorg71 450 if (g_owncolmap != True)
612 n-ki 279 {
613 jsorg71 450 g_xcolmap = DefaultColormapOfScreen(g_screen);
614     if (g_depth <= 8)
615 matthewc 297 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
616 n-ki 279 }
617    
618 jsorg71 450 g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);
619 matthewc 121
620 jsorg71 450 if (DoesBackingStore(g_screen) != Always)
621     g_ownbackstore = True;
622 matthewc 121
623     test = 1;
624 jsorg71 450 g_host_be = !(BOOL) (*(uint8 *) (&test));
625     g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
626 matthewc 121
627 jsorg71 447 if ((g_width == 0) || (g_height == 0))
628 astrand 263 {
629     /* Fetch geometry from _NET_WORKAREA */
630 matthewc 300 uint32 x, y, cx, cy;
631 astrand 263
632 matthewc 300 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
633 astrand 263 {
634 jsorg71 447 g_width = cx;
635     g_height = cy;
636 matthewc 300 }
637     else
638     {
639 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
640 jsorg71 447 g_width = 800;
641     g_height = 600;
642 astrand 263 }
643     }
644    
645 jsorg71 447 if (g_fullscreen)
646 jsorg71 81 {
647 jsorg71 450 g_width = WidthOfScreen(g_screen);
648     g_height = HeightOfScreen(g_screen);
649 jsorg71 81 }
650 matthewc 121
651 matthewc 160 /* make sure width is a multiple of 4 */
652 jsorg71 447 g_width = (g_width + 3) & ~3;
653 matthewc 160
654 jsorg71 450 if (g_ownbackstore)
655 matthewc 188 {
656 jsorg71 450 g_backstore =
657     XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,
658     g_depth);
659 matthewc 188
660     /* clear to prevent rubbish being exposed at startup */
661 jsorg71 450 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
662     XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
663 matthewc 188 }
664    
665 jsorg71 450 g_mod_map = XGetModifierMapping(g_display);
666 matthewc 203
667 jsorg71 447 if (g_enable_compose)
668 jsorg71 450 g_IM = XOpenIM(g_display, NULL, NULL, NULL);
669 matthewc 188
670 matthewc 121 xkeymap_init();
671 matthewc 432 xclip_init();
672 jsorg71 316
673     /* todo take this out when high colour is done */
674 jsorg71 450 printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth);
675 jsorg71 316
676 jsorg71 81 return True;
677     }
678 astrand 66
679 matthewc 188 void
680 matthewc 192 ui_deinit(void)
681 matthewc 188 {
682 jsorg71 450 if (g_IM != NULL)
683     XCloseIM(g_IM);
684 matthewc 188
685 jsorg71 450 XFreeModifiermap(g_mod_map);
686 matthewc 203
687 jsorg71 450 if (g_ownbackstore)
688     XFreePixmap(g_display, g_backstore);
689 matthewc 188
690 jsorg71 450 XFreeGC(g_display, g_gc);
691     XCloseDisplay(g_display);
692     g_display = NULL;
693 matthewc 188 }
694    
695 matthewc 121 BOOL
696 matthewc 192 ui_create_window(void)
697 matty 6 {
698 matthewc 121 XSetWindowAttributes attribs;
699 matty 28 XClassHint *classhints;
700     XSizeHints *sizehints;
701 matthewc 188 int wndwidth, wndheight;
702 matthewc 432 long input_mask, ic_input_mask;
703 jsorg71 100 XEvent xevent;
704    
705 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
706     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
707 matthewc 188
708 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
709     attribs.backing_store = g_ownbackstore ? NotUseful : Always;
710 jsorg71 447 attribs.override_redirect = g_fullscreen;
711 matthewc 188
712 jsorg71 450 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
713 astrand 456 0, CopyFromParent, InputOutput, CopyFromParent,
714     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
715 jsorg71 100
716 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
717 jsorg71 100
718 jsorg71 450 if (g_hide_decorations)
719 astrand 262 mwm_hide_decorations();
720    
721 jsorg71 100 classhints = XAllocClassHint();
722     if (classhints != NULL)
723     {
724     classhints->res_name = classhints->res_class = "rdesktop";
725 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
726 jsorg71 100 XFree(classhints);
727     }
728    
729     sizehints = XAllocSizeHints();
730     if (sizehints)
731     {
732     sizehints->flags = PMinSize | PMaxSize;
733 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
734     sizehints->min_height = sizehints->max_height = g_height;
735 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
736 jsorg71 100 XFree(sizehints);
737     }
738    
739 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
740 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
741 matthewc 121
742 jsorg71 447 if (g_sendmotion)
743 matthewc 121 input_mask |= PointerMotionMask;
744 jsorg71 450 if (g_ownbackstore)
745 matthewc 121 input_mask |= ExposureMask;
746 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
747 matthewc 250 input_mask |= EnterWindowMask;
748 jsorg71 450 if (g_grab_keyboard)
749 jsorg71 257 input_mask |= LeaveWindowMask;
750 jsorg71 100
751 jsorg71 450 if (g_IM != NULL)
752 matthewc 188 {
753 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
754 astrand 456 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
755 matthewc 188
756 jsorg71 450 if ((g_IC != NULL)
757     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
758 matthewc 188 input_mask |= ic_input_mask;
759     }
760    
761 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
762     XMapWindow(g_display, g_wnd);
763 jsorg71 100
764 matthewc 208 /* wait for VisibilityNotify */
765 astrand 196 do
766     {
767 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
768 astrand 196 }
769 matthewc 208 while (xevent.type != VisibilityNotify);
770 matthewc 123
771 jsorg71 447 g_focused = False;
772     g_mouse_in_wnd = False;
773 jsorg71 257
774 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
775 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
776     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
777     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
778 astrand 275
779 matty 10 return True;
780 matty 6 }
781    
782 matty 25 void
783 matthewc 192 ui_destroy_window(void)
784 matty 6 {
785 jsorg71 450 if (g_IC != NULL)
786     XDestroyIC(g_IC);
787 matty 31
788 jsorg71 450 XDestroyWindow(g_display, g_wnd);
789 matty 6 }
790    
791 jsorg71 100 void
792 matthewc 192 xwin_toggle_fullscreen(void)
793 jsorg71 100 {
794 matthewc 188 Pixmap contents = 0;
795 matthewc 123
796 jsorg71 450 if (!g_ownbackstore)
797 matthewc 188 {
798     /* need to save contents of window */
799 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
800     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
801 matthewc 188 }
802    
803     ui_destroy_window();
804 jsorg71 447 g_fullscreen = !g_fullscreen;
805 matthewc 188 ui_create_window();
806 matthewc 123
807 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
808 matthewc 188
809 jsorg71 450 if (!g_ownbackstore)
810 matthewc 188 {
811 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
812     XFreePixmap(g_display, contents);
813 matthewc 188 }
814 jsorg71 100 }
815    
816 jsorg71 447 /* Process all events in Xlib queue
817 astrand 275 Returns 0 after user quit, 1 otherwise */
818     static int
819 matthewc 192 xwin_process_events(void)
820 matty 9 {
821 n-ki 54 XEvent xevent;
822 matthewc 38 KeySym keysym;
823 matthewc 50 uint16 button, flags;
824 matty 10 uint32 ev_time;
825 astrand 66 key_translation tr;
826     char str[256];
827     Status status;
828 matthewc 203 unsigned int state;
829     Window wdummy;
830     int dummy;
831 matty 9
832 jsorg71 450 while (XPending(g_display) > 0)
833 matty 9 {
834 jsorg71 450 XNextEvent(g_display, &xevent);
835 matthewc 123
836 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
837 astrand 66 {
838 astrand 84 DEBUG_KBD(("Filtering event\n"));
839 astrand 66 continue;
840     }
841    
842 matthewc 50 flags = 0;
843 matty 10
844 n-ki 54 switch (xevent.type)
845 matty 9 {
846 astrand 275 case ClientMessage:
847     /* the window manager told us to quit */
848 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
849     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
850 astrand 275 /* Quit */
851     return 0;
852     break;
853    
854 matty 9 case KeyPress:
855 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
856     if (g_IC != NULL)
857 astrand 66 /* Multi_key compatible version */
858     {
859 jsorg71 450 XmbLookupString(g_IC,
860 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
861     &status);
862 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
863 astrand 66 {
864 astrand 82 error("XmbLookupString failed with status 0x%x\n",
865     status);
866 astrand 66 break;
867     }
868     }
869     else
870     {
871     /* Plain old XLookupString */
872 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
873 astrand 66 XLookupString((XKeyEvent *) & xevent,
874 astrand 82 str, sizeof(str), &keysym, NULL);
875 astrand 66 }
876    
877 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
878     get_ksname(keysym)));
879 astrand 66
880 matthewc 203 ev_time = time(NULL);
881     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
882 astrand 118 break;
883    
884 astrand 66 tr = xkeymap_translate_key(keysym,
885 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
886 astrand 69
887 astrand 66 if (tr.scancode == 0)
888 n-ki 52 break;
889    
890 astrand 470 save_remote_modifiers(tr.scancode);
891 astrand 115 ensure_remote_modifiers(ev_time, tr);
892 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
893 astrand 470 restore_remote_modifiers(ev_time, tr.scancode);
894 astrand 115
895 astrand 66 break;
896 matthewc 203
897 astrand 66 case KeyRelease:
898 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
899 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
900     sizeof(str), &keysym, NULL);
901 n-ki 52
902 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
903 matthewc 203 get_ksname(keysym)));
904 n-ki 52
905 matthewc 203 ev_time = time(NULL);
906     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
907 astrand 118 break;
908    
909 astrand 66 tr = xkeymap_translate_key(keysym,
910 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
911 astrand 66
912     if (tr.scancode == 0)
913     break;
914    
915 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
916 matty 9 break;
917    
918     case ButtonPress:
919 matthewc 50 flags = MOUSE_FLAG_DOWN;
920     /* fall through */
921 matty 9
922     case ButtonRelease:
923 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
924 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
925 matty 9 if (button == 0)
926     break;
927    
928 astrand 328 /* If win_button_size is nonzero, enable single app mode */
929 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
930 astrand 328 {
931 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
932 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
933     g_moving_wnd = False;
934 astrand 332
935 astrand 342 /* Check from right to left: */
936    
937 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
938 astrand 328 {
939 astrand 331 /* The close button, continue */
940 astrand 328 ;
941     }
942 astrand 456 else if (xevent.xbutton.x >=
943     g_width - g_win_button_size * 2)
944 astrand 328 {
945     /* The maximize/restore button. Do not send to
946     server. It might be a good idea to change the
947 jsorg71 447 cursor or give some other visible indication
948 astrand 328 that rdesktop inhibited this click */
949     break;
950     }
951 astrand 456 else if (xevent.xbutton.x >=
952     g_width - g_win_button_size * 3)
953 astrand 328 {
954     /* The minimize button. Iconify window. */
955 jsorg71 450 XIconifyWindow(g_display, g_wnd,
956     DefaultScreen(g_display));
957 astrand 328 break;
958     }
959 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
960 astrand 342 {
961     /* The system menu. Ignore. */
962     break;
963     }
964 astrand 332 else
965     {
966 astrand 342 /* The title bar. */
967 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
968 jsorg71 450 && g_hide_decorations)
969 astrand 342 {
970 jsorg71 450 g_moving_wnd = True;
971     g_move_x_offset = xevent.xbutton.x;
972     g_move_y_offset = xevent.xbutton.y;
973 astrand 342 }
974 astrand 332 break;
975 astrand 342
976 astrand 332 }
977 astrand 328 }
978    
979 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
980 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
981 matty 10 break;
982    
983     case MotionNotify:
984 jsorg71 450 if (g_moving_wnd)
985 astrand 342 {
986 jsorg71 450 XMoveWindow(g_display, g_wnd,
987     xevent.xmotion.x_root - g_move_x_offset,
988     xevent.xmotion.y_root - g_move_y_offset);
989 astrand 342 break;
990     }
991    
992 jsorg71 447 if (g_fullscreen && !g_focused)
993 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
994 jsorg71 288 CurrentTime);
995 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
996 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
997 matty 28 break;
998    
999 matthewc 194 case FocusIn:
1000 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
1001     break;
1002 jsorg71 447 g_focused = True;
1003 jsorg71 450 XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,
1004 astrand 261 &dummy, &dummy, &state);
1005 matthewc 203 reset_modifier_keys(state);
1006 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
1007     XGrabKeyboard(g_display, g_wnd, True,
1008 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
1009 matty 28 break;
1010    
1011 matthewc 194 case FocusOut:
1012 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
1013     break;
1014 jsorg71 447 g_focused = False;
1015 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1016 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1017 matty 28 break;
1018 matty 31
1019 matthewc 250 case EnterNotify:
1020     /* we only register for this event when in fullscreen mode */
1021 jsorg71 257 /* or grab_keyboard */
1022 jsorg71 447 g_mouse_in_wnd = True;
1023     if (g_fullscreen)
1024 jsorg71 257 {
1025 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1026 astrand 261 CurrentTime);
1027 jsorg71 257 break;
1028     }
1029 jsorg71 447 if (g_focused)
1030 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
1031 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
1032 matthewc 250 break;
1033    
1034 matthewc 253 case LeaveNotify:
1035 jsorg71 257 /* we only register for this event when grab_keyboard */
1036 jsorg71 447 g_mouse_in_wnd = False;
1037 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1038 matthewc 253 break;
1039    
1040 matty 31 case Expose:
1041 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1042 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
1043 astrand 64 xevent.xexpose.width,
1044     xevent.xexpose.height,
1045 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
1046 matty 31 break;
1047 astrand 119
1048     case MappingNotify:
1049     /* Refresh keyboard mapping if it has changed. This is important for
1050     Xvnc, since it allocates keycodes dynamically */
1051     if (xevent.xmapping.request == MappingKeyboard
1052     || xevent.xmapping.request == MappingModifier)
1053     XRefreshKeyboardMapping(&xevent.xmapping);
1054 matthewc 203
1055     if (xevent.xmapping.request == MappingModifier)
1056     {
1057 jsorg71 450 XFreeModifiermap(g_mod_map);
1058     g_mod_map = XGetModifierMapping(g_display);
1059 matthewc 203 }
1060 astrand 119 break;
1061 matthewc 432
1062 astrand 435 /* clipboard stuff */
1063 forsberg 415 case SelectionNotify:
1064 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1065 forsberg 415 break;
1066     case SelectionRequest:
1067 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1068 forsberg 415 break;
1069 matthewc 432 case SelectionClear:
1070     xclip_handle_SelectionClear();
1071     break;
1072 forsberg 415 case PropertyNotify:
1073 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1074 forsberg 415 break;
1075 matty 9 }
1076     }
1077 astrand 275 /* Keep going */
1078     return 1;
1079 matty 9 }
1080    
1081 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1082     int
1083 matty 33 ui_select(int rdp_socket)
1084     {
1085 jsorg71 450 int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
1086 matthewc 474 fd_set rfds, wfds;
1087 matty 33
1088     while (True)
1089     {
1090 matthewc 121 /* Process any events already waiting */
1091 astrand 275 if (!xwin_process_events())
1092     /* User quit */
1093     return 0;
1094 astrand 119
1095 matty 33 FD_ZERO(&rfds);
1096 matthewc 474 FD_ZERO(&wfds);
1097 matty 33 FD_SET(rdp_socket, &rfds);
1098 jsorg71 450 FD_SET(g_x_socket, &rfds);
1099 matty 33
1100 matthewc 474 #ifdef WITH_RDPSND
1101     /* FIXME: there should be an API for registering fds */
1102     if (g_dsp_busy)
1103 matty 33 {
1104 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1105     n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1106     }
1107     #endif
1108    
1109     switch (select(n, &rfds, &wfds, NULL, NULL))
1110     {
1111 matty 33 case -1:
1112     error("select: %s\n", strerror(errno));
1113    
1114     case 0:
1115     continue;
1116     }
1117    
1118     if (FD_ISSET(rdp_socket, &rfds))
1119 astrand 275 return 1;
1120 matthewc 474
1121     #ifdef WITH_RDPSND
1122 matthewc 478 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1123 matthewc 474 wave_out_play();
1124     #endif
1125 matty 33 }
1126     }
1127    
1128     void
1129 matty 25 ui_move_pointer(int x, int y)
1130 matty 9 {
1131 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1132 matty 9 }
1133    
1134 matty 25 HBITMAP
1135 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1136 matty 6 {
1137     XImage *image;
1138 matty 9 Pixmap bitmap;
1139 matty 28 uint8 *tdata;
1140 matty 29
1141 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1142     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1143     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1144     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1145 matty 6
1146 jsorg71 450 XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1147 matty 9
1148     XFree(image);
1149 jsorg71 450 if (!g_owncolmap)
1150 n-ki 279 xfree(tdata);
1151 matty 24 return (HBITMAP) bitmap;
1152 matty 6 }
1153    
1154 matty 25 void
1155 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1156 matty 6 {
1157 matty 10 XImage *image;
1158 matty 29 uint8 *tdata;
1159 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1160     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1161     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1162 matty 28
1163 jsorg71 450 if (g_ownbackstore)
1164 matty 31 {
1165 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1166     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1167 matty 31 }
1168     else
1169     {
1170 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1171 matty 31 }
1172 matty 29
1173 matty 24 XFree(image);
1174 jsorg71 450 if (!g_owncolmap)
1175 n-ki 279 xfree(tdata);
1176 matty 6 }
1177    
1178 matty 25 void
1179     ui_destroy_bitmap(HBITMAP bmp)
1180 matty 6 {
1181 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1182 matty 10 }
1183    
1184 matty 25 HGLYPH
1185 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1186 matty 10 {
1187 matty 9 XImage *image;
1188     Pixmap bitmap;
1189     int scanline;
1190     GC gc;
1191 matty 6
1192 matty 9 scanline = (width + 7) / 8;
1193 matty 6
1194 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1195     gc = XCreateGC(g_display, bitmap, 0, NULL);
1196 matty 9
1197 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1198 astrand 73 width, height, 8, scanline);
1199 matty 23 image->byte_order = MSBFirst;
1200     image->bitmap_bit_order = MSBFirst;
1201     XInitImage(image);
1202    
1203 jsorg71 450 XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1204 matty 29
1205 matty 9 XFree(image);
1206 jsorg71 450 XFreeGC(g_display, gc);
1207 astrand 64 return (HGLYPH) bitmap;
1208 matty 6 }
1209 matty 7
1210 matty 25 void
1211     ui_destroy_glyph(HGLYPH glyph)
1212 matty 7 {
1213 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1214 matty 9 }
1215    
1216 matty 29 HCURSOR
1217 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1218     uint8 * andmask, uint8 * xormask)
1219 matty 9 {
1220 matty 29 HGLYPH maskglyph, cursorglyph;
1221     XColor bg, fg;
1222     Cursor xcursor;
1223     uint8 *cursor, *pcursor;
1224     uint8 *mask, *pmask;
1225     uint8 nextbit;
1226     int scanline, offset;
1227     int i, j;
1228    
1229     scanline = (width + 7) / 8;
1230     offset = scanline * height;
1231    
1232 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1233 matty 29 memset(cursor, 0, offset);
1234    
1235 forsberg 415 mask = (uint8 *) xmalloc(offset);
1236 matty 29 memset(mask, 0, offset);
1237    
1238     /* approximate AND and XOR masks with a monochrome X pointer */
1239     for (i = 0; i < height; i++)
1240 matty 7 {
1241 matty 29 offset -= scanline;
1242     pcursor = &cursor[offset];
1243     pmask = &mask[offset];
1244    
1245     for (j = 0; j < scanline; j++)
1246 matty 28 {
1247 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1248     {
1249     if (xormask[0] || xormask[1] || xormask[2])
1250     {
1251     *pcursor |= (~(*andmask) & nextbit);
1252     *pmask |= nextbit;
1253     }
1254     else
1255     {
1256     *pcursor |= ((*andmask) & nextbit);
1257     *pmask |= (~(*andmask) & nextbit);
1258     }
1259    
1260     xormask += 3;
1261     }
1262    
1263     andmask++;
1264     pcursor++;
1265     pmask++;
1266 matty 28 }
1267 matty 7 }
1268 matty 29
1269     fg.red = fg.blue = fg.green = 0xffff;
1270     bg.red = bg.blue = bg.green = 0x0000;
1271     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1272    
1273     cursorglyph = ui_create_glyph(width, height, cursor);
1274     maskglyph = ui_create_glyph(width, height, mask);
1275    
1276 astrand 66 xcursor =
1277 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1278 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1279 astrand 64
1280 matty 29 ui_destroy_glyph(maskglyph);
1281     ui_destroy_glyph(cursorglyph);
1282     xfree(mask);
1283     xfree(cursor);
1284 astrand 64 return (HCURSOR) xcursor;
1285 matty 29 }
1286    
1287     void
1288     ui_set_cursor(HCURSOR cursor)
1289     {
1290 jsorg71 450 g_current_cursor = (Cursor) cursor;
1291     XDefineCursor(g_display, g_wnd, g_current_cursor);
1292 matty 29 }
1293    
1294     void
1295     ui_destroy_cursor(HCURSOR cursor)
1296     {
1297 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1298 matty 29 }
1299    
1300     #define MAKE_XCOLOR(xc,c) \
1301     (xc)->red = ((c)->red << 8) | (c)->red; \
1302     (xc)->green = ((c)->green << 8) | (c)->green; \
1303     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1304     (xc)->flags = DoRed | DoGreen | DoBlue;
1305    
1306 n-ki 279
1307 matty 29 HCOLOURMAP
1308 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1309 matty 29 {
1310     COLOURENTRY *entry;
1311     int i, ncolours = colours->ncolours;
1312 jsorg71 450 if (!g_owncolmap)
1313 matty 28 {
1314 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1315 n-ki 279 XColor xentry;
1316     XColor xc_cache[256];
1317     uint32 colour;
1318     int colLookup = 256;
1319     for (i = 0; i < ncolours; i++)
1320 matty 28 {
1321 n-ki 279 entry = &colours->colours[i];
1322     MAKE_XCOLOR(&xentry, entry);
1323 matty 7
1324 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1325 astrand 196 {
1326 n-ki 279 /* Allocation failed, find closest match. */
1327     int j = 256;
1328     int nMinDist = 3 * 256 * 256;
1329     long nDist = nMinDist;
1330 matty 28
1331 n-ki 279 /* only get the colors once */
1332     while (colLookup--)
1333 astrand 196 {
1334 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1335     xc_cache[colLookup].red = xc_cache[colLookup].green =
1336     xc_cache[colLookup].blue = 0;
1337     xc_cache[colLookup].flags = 0;
1338 jsorg71 450 XQueryColor(g_display,
1339     DefaultColormap(g_display,
1340     DefaultScreen(g_display)),
1341 n-ki 279 &xc_cache[colLookup]);
1342 n-ki 185 }
1343 n-ki 279 colLookup = 0;
1344    
1345     /* approximate the pixel */
1346     while (j--)
1347 astrand 196 {
1348 n-ki 279 if (xc_cache[j].flags)
1349     {
1350     nDist = ((long) (xc_cache[j].red >> 8) -
1351     (long) (xentry.red >> 8)) *
1352     ((long) (xc_cache[j].red >> 8) -
1353     (long) (xentry.red >> 8)) +
1354     ((long) (xc_cache[j].green >> 8) -
1355     (long) (xentry.green >> 8)) *
1356     ((long) (xc_cache[j].green >> 8) -
1357     (long) (xentry.green >> 8)) +
1358     ((long) (xc_cache[j].blue >> 8) -
1359     (long) (xentry.blue >> 8)) *
1360     ((long) (xc_cache[j].blue >> 8) -
1361     (long) (xentry.blue >> 8));
1362     }
1363     if (nDist < nMinDist)
1364     {
1365     nMinDist = nDist;
1366     xentry.pixel = j;
1367     }
1368 n-ki 185 }
1369     }
1370 n-ki 279 colour = xentry.pixel;
1371    
1372     /* update our cache */
1373     if (xentry.pixel < 256)
1374     {
1375     xc_cache[xentry.pixel].red = xentry.red;
1376     xc_cache[xentry.pixel].green = xentry.green;
1377     xc_cache[xentry.pixel].blue = xentry.blue;
1378    
1379     }
1380    
1381    
1382     /* byte swap here to make translate_image faster */
1383     map[i] = translate_colour(colour);
1384 n-ki 185 }
1385 n-ki 279 return map;
1386     }
1387     else
1388     {
1389     XColor *xcolours, *xentry;
1390     Colormap map;
1391 matty 29
1392 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1393 n-ki 279 for (i = 0; i < ncolours; i++)
1394 astrand 196 {
1395 n-ki 279 entry = &colours->colours[i];
1396     xentry = &xcolours[i];
1397     xentry->pixel = i;
1398     MAKE_XCOLOR(xentry, entry);
1399 matty 29 }
1400    
1401 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1402     XStoreColors(g_display, map, xcolours, ncolours);
1403 n-ki 185
1404 n-ki 279 xfree(xcolours);
1405     return (HCOLOURMAP) map;
1406 matty 29 }
1407 matty 7 }
1408    
1409 matty 25 void
1410     ui_destroy_colourmap(HCOLOURMAP map)
1411 matty 7 {
1412 jsorg71 450 if (!g_owncolmap)
1413 n-ki 279 xfree(map);
1414     else
1415 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1416 matty 7 }
1417    
1418 matty 25 void
1419     ui_set_colourmap(HCOLOURMAP map)
1420 matty 7 {
1421 jsorg71 450 if (!g_owncolmap)
1422 astrand 448 {
1423 jsorg71 450 if (g_colmap)
1424     xfree(g_colmap);
1425 astrand 448
1426 jsorg71 450 g_colmap = (uint32 *) map;
1427 astrand 448 }
1428 n-ki 279 else
1429 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1430 matty 7 }
1431    
1432 matty 25 void
1433     ui_set_clip(int x, int y, int cx, int cy)
1434 matty 7 {
1435 matty 9 XRectangle rect;
1436 matty 7
1437 matty 9 rect.x = x;
1438     rect.y = y;
1439     rect.width = cx;
1440     rect.height = cy;
1441 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1442 matty 9 }
1443 matty 7
1444 matty 25 void
1445 matthewc 192 ui_reset_clip(void)
1446 matty 9 {
1447     XRectangle rect;
1448    
1449     rect.x = 0;
1450     rect.y = 0;
1451 jsorg71 447 rect.width = g_width;
1452     rect.height = g_height;
1453 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1454 matty 7 }
1455    
1456 matty 25 void
1457 matthewc 192 ui_bell(void)
1458 matty 10 {
1459 jsorg71 450 XBell(g_display, 0);
1460 matty 10 }
1461    
1462 matty 25 void
1463     ui_destblt(uint8 opcode,
1464     /* dest */ int x, int y, int cx, int cy)
1465 matty 9 {
1466 matty 29 SET_FUNCTION(opcode);
1467 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1468 matty 29 RESET_FUNCTION(opcode);
1469 matty 9 }
1470    
1471 jsorg71 373 static uint8 hatch_patterns[] = {
1472 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1473     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1474     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1475     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1476     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1477     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1478 jsorg71 373 };
1479    
1480 matty 25 void
1481     ui_patblt(uint8 opcode,
1482     /* dest */ int x, int y, int cx, int cy,
1483 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1484 matty 9 {
1485     Pixmap fill;
1486 jsorg71 59 uint8 i, ipattern[8];
1487 matty 9
1488 matty 29 SET_FUNCTION(opcode);
1489 matty 9
1490     switch (brush->style)
1491     {
1492 matty 24 case 0: /* Solid */
1493 matty 29 SET_FOREGROUND(fgcolour);
1494 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1495 matty 9 break;
1496    
1497 jsorg71 373 case 2: /* Hatch */
1498 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1499     hatch_patterns + brush->pattern[0] * 8);
1500 jsorg71 373 SET_FOREGROUND(bgcolour);
1501     SET_BACKGROUND(fgcolour);
1502 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1503     XSetStipple(g_display, g_gc, fill);
1504     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1505 jsorg71 373 FILL_RECTANGLE(x, y, cx, cy);
1506 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1507     XSetTSOrigin(g_display, g_gc, 0, 0);
1508 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1509     break;
1510    
1511 matty 24 case 3: /* Pattern */
1512 jsorg71 59 for (i = 0; i != 8; i++)
1513     ipattern[7 - i] = brush->pattern[i];
1514     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1515 matty 9
1516 matty 29 SET_FOREGROUND(bgcolour);
1517     SET_BACKGROUND(fgcolour);
1518 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1519     XSetStipple(g_display, g_gc, fill);
1520     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1521 matty 9
1522 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1523 matty 9
1524 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1525     XSetTSOrigin(g_display, g_gc, 0, 0);
1526 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1527 matty 9 break;
1528    
1529     default:
1530 matty 30 unimpl("brush %d\n", brush->style);
1531 matty 9 }
1532 matty 29
1533     RESET_FUNCTION(opcode);
1534 matty 9 }
1535    
1536 matty 25 void
1537     ui_screenblt(uint8 opcode,
1538     /* dest */ int x, int y, int cx, int cy,
1539     /* src */ int srcx, int srcy)
1540 matty 9 {
1541 matty 29 SET_FUNCTION(opcode);
1542 jsorg71 450 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1543     if (g_ownbackstore)
1544     XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1545 matty 29 RESET_FUNCTION(opcode);
1546 matty 9 }
1547    
1548 matty 25 void
1549     ui_memblt(uint8 opcode,
1550     /* dest */ int x, int y, int cx, int cy,
1551     /* src */ HBITMAP src, int srcx, int srcy)
1552 matty 9 {
1553 matty 29 SET_FUNCTION(opcode);
1554 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1555     if (g_ownbackstore)
1556     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1557 matty 29 RESET_FUNCTION(opcode);
1558 matty 9 }
1559    
1560 matty 25 void
1561     ui_triblt(uint8 opcode,
1562     /* dest */ int x, int y, int cx, int cy,
1563     /* src */ HBITMAP src, int srcx, int srcy,
1564 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1565 matty 9 {
1566     /* This is potentially difficult to do in general. Until someone
1567 matty 10 comes up with a more efficient way of doing it I am using cases. */
1568 matty 9
1569     switch (opcode)
1570     {
1571 matty 24 case 0x69: /* PDSxxn */
1572 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1573 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1574 matty 16 break;
1575    
1576 matty 24 case 0xb8: /* PSDPxax */
1577 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1578 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1579 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1580 matty 9 break;
1581    
1582 matty 29 case 0xc0: /* PSa */
1583 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1584 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1585 matty 28 break;
1586    
1587 matty 9 default:
1588 matty 30 unimpl("triblt 0x%x\n", opcode);
1589 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1590 matty 9 }
1591     }
1592    
1593 matty 25 void
1594     ui_line(uint8 opcode,
1595     /* dest */ int startx, int starty, int endx, int endy,
1596 astrand 64 /* pen */ PEN * pen)
1597 matty 9 {
1598 matty 29 SET_FUNCTION(opcode);
1599     SET_FOREGROUND(pen->colour);
1600 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1601     if (g_ownbackstore)
1602     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1603 matty 29 RESET_FUNCTION(opcode);
1604 matty 9 }
1605    
1606 matty 25 void
1607     ui_rect(
1608     /* dest */ int x, int y, int cx, int cy,
1609     /* brush */ int colour)
1610 matty 9 {
1611 matty 29 SET_FOREGROUND(colour);
1612 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1613 matty 9 }
1614    
1615 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1616 matty 25 void
1617     ui_draw_glyph(int mixmode,
1618     /* dest */ int x, int y, int cx, int cy,
1619 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1620     int bgcolour, int fgcolour)
1621 matty 9 {
1622 matty 29 SET_FOREGROUND(fgcolour);
1623     SET_BACKGROUND(bgcolour);
1624 matty 9
1625 jsorg71 450 XSetFillStyle(g_display, g_gc,
1626 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1627 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
1628     XSetTSOrigin(g_display, g_gc, x, y);
1629 matty 9
1630 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1631 matty 9
1632 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1633 matty 9 }
1634    
1635 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1636     {\
1637     glyph = cache_get_font (font, ttext[idx]);\
1638     if (!(flags & TEXT2_IMPLICIT_X))\
1639     {\
1640     xyoffset = ttext[++idx];\
1641     if ((xyoffset & 0x80))\
1642     {\
1643     if (flags & TEXT2_VERTICAL) \
1644 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1645 mmihalik 49 else\
1646 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1647     idx += 2;\
1648 mmihalik 49 }\
1649     else\
1650     {\
1651     if (flags & TEXT2_VERTICAL) \
1652     y += xyoffset;\
1653     else\
1654     x += xyoffset;\
1655     }\
1656     }\
1657     if (glyph != NULL)\
1658     {\
1659 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1660     y + glyph->baseline,\
1661 mmihalik 49 glyph->width, glyph->height,\
1662     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1663     if (flags & TEXT2_IMPLICIT_X)\
1664     x += glyph->width;\
1665     }\
1666     }
1667    
1668 matty 25 void
1669     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1670 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1671     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1672 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1673 matty 9 {
1674 matty 10 FONTGLYPH *glyph;
1675 mmihalik 49 int i, j, xyoffset;
1676     DATABLOB *entry;
1677 matty 9
1678 matty 29 SET_FOREGROUND(bgcolour);
1679 matty 28
1680 matty 9 if (boxcx > 1)
1681 matty 31 {
1682 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1683 matty 31 }
1684 matty 17 else if (mixmode == MIX_OPAQUE)
1685 matty 31 {
1686 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1687 matty 31 }
1688 matty 9
1689     /* Paint text, character by character */
1690 astrand 64 for (i = 0; i < length;)
1691     {
1692     switch (text[i])
1693     {
1694     case 0xff:
1695     if (i + 2 < length)
1696 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1697 astrand 64 else
1698     {
1699     error("this shouldn't be happening\n");
1700 astrand 265 exit(1);
1701 astrand 64 }
1702     /* this will move pointer from start to first character after FF command */
1703     length -= i + 3;
1704     text = &(text[i + 3]);
1705     i = 0;
1706 mmihalik 49 break;
1707 matty 9
1708 astrand 64 case 0xfe:
1709     entry = cache_get_text(text[i + 1]);
1710     if (entry != NULL)
1711     {
1712     if ((((uint8 *) (entry->data))[1] ==
1713 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1714 astrand 64 {
1715     if (flags & TEXT2_VERTICAL)
1716     y += text[i + 2];
1717     else
1718     x += text[i + 2];
1719     }
1720     for (j = 0; j < entry->size; j++)
1721 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1722 matthewc 44 }
1723 jsorg71 286 if (i + 2 < length)
1724     i += 3;
1725     else
1726     i += 2;
1727     length -= i;
1728     /* this will move pointer from start to first character after FE command */
1729     text = &(text[i]);
1730     i = 0;
1731 astrand 64 break;
1732 matty 17
1733 astrand 64 default:
1734     DO_GLYPH(text, i);
1735     i++;
1736     break;
1737 matty 29 }
1738 mmihalik 49 }
1739 jsorg71 450 if (g_ownbackstore)
1740 jsorg71 278 {
1741     if (boxcx > 1)
1742 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1743 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
1744     else
1745 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1746 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
1747     }
1748 matty 9 }
1749    
1750 matty 25 void
1751     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1752 matty 9 {
1753 matty 28 Pixmap pix;
1754 matty 9 XImage *image;
1755    
1756 jsorg71 450 if (g_ownbackstore)
1757 matty 31 {
1758 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1759 matty 31 }
1760     else
1761     {
1762 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1763     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1764     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1765     XFreePixmap(g_display, pix);
1766 matty 31 }
1767 matty 28
1768 jsorg71 450 offset *= g_bpp / 8;
1769     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
1770 matty 28
1771     XDestroyImage(image);
1772 matty 9 }
1773    
1774 matty 25 void
1775     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1776 matty 9 {
1777     XImage *image;
1778 matty 10 uint8 *data;
1779 matty 9
1780 jsorg71 450 offset *= g_bpp / 8;
1781     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1782 matty 10 if (data == NULL)
1783     return;
1784 matty 29
1785 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1786     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
1787 matty 29
1788 jsorg71 450 if (g_ownbackstore)
1789 matty 31 {
1790 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1791     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1792 matty 31 }
1793     else
1794     {
1795 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1796 matty 31 }
1797    
1798 matty 9 XFree(image);
1799     }

  ViewVC Help
Powered by ViewVC 1.1.26