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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 474 - (hide annotations)
Tue Sep 30 09:11:08 2003 UTC (20 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 41013 byte(s)
Preliminary sound support (PCM only).
Based on code from GuoJunBo <guojunbo@ict.ac.cn>

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     FD_ZERO(&rfds);
1089    
1090     while (True)
1091     {
1092 matthewc 121 /* Process any events already waiting */
1093 astrand 275 if (!xwin_process_events())
1094     /* User quit */
1095     return 0;
1096 astrand 119
1097 matty 33 FD_ZERO(&rfds);
1098 matthewc 474 FD_ZERO(&wfds);
1099 matty 33 FD_SET(rdp_socket, &rfds);
1100 jsorg71 450 FD_SET(g_x_socket, &rfds);
1101 matty 33
1102 matthewc 474 #ifdef WITH_RDPSND
1103     /* FIXME: there should be an API for registering fds */
1104     if (g_dsp_busy)
1105 matty 33 {
1106 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1107     n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1108     }
1109     #endif
1110    
1111     switch (select(n, &rfds, &wfds, NULL, NULL))
1112     {
1113 matty 33 case -1:
1114     error("select: %s\n", strerror(errno));
1115    
1116     case 0:
1117     continue;
1118     }
1119    
1120     if (FD_ISSET(rdp_socket, &rfds))
1121 astrand 275 return 1;
1122 matthewc 474
1123     #ifdef WITH_RDPSND
1124     if (FD_ISSET(g_dsp_fd, &wfds))
1125     wave_out_play();
1126     #endif
1127 matty 33 }
1128     }
1129    
1130     void
1131 matty 25 ui_move_pointer(int x, int y)
1132 matty 9 {
1133 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1134 matty 9 }
1135    
1136 matty 25 HBITMAP
1137 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1138 matty 6 {
1139     XImage *image;
1140 matty 9 Pixmap bitmap;
1141 matty 28 uint8 *tdata;
1142 matty 29
1143 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1144     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1145     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1146     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1147 matty 6
1148 jsorg71 450 XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1149 matty 9
1150     XFree(image);
1151 jsorg71 450 if (!g_owncolmap)
1152 n-ki 279 xfree(tdata);
1153 matty 24 return (HBITMAP) bitmap;
1154 matty 6 }
1155    
1156 matty 25 void
1157 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1158 matty 6 {
1159 matty 10 XImage *image;
1160 matty 29 uint8 *tdata;
1161 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1162     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1163     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1164 matty 28
1165 jsorg71 450 if (g_ownbackstore)
1166 matty 31 {
1167 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1168     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1169 matty 31 }
1170     else
1171     {
1172 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1173 matty 31 }
1174 matty 29
1175 matty 24 XFree(image);
1176 jsorg71 450 if (!g_owncolmap)
1177 n-ki 279 xfree(tdata);
1178 matty 6 }
1179    
1180 matty 25 void
1181     ui_destroy_bitmap(HBITMAP bmp)
1182 matty 6 {
1183 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1184 matty 10 }
1185    
1186 matty 25 HGLYPH
1187 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1188 matty 10 {
1189 matty 9 XImage *image;
1190     Pixmap bitmap;
1191     int scanline;
1192     GC gc;
1193 matty 6
1194 matty 9 scanline = (width + 7) / 8;
1195 matty 6
1196 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1197     gc = XCreateGC(g_display, bitmap, 0, NULL);
1198 matty 9
1199 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1200 astrand 73 width, height, 8, scanline);
1201 matty 23 image->byte_order = MSBFirst;
1202     image->bitmap_bit_order = MSBFirst;
1203     XInitImage(image);
1204    
1205 jsorg71 450 XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1206 matty 29
1207 matty 9 XFree(image);
1208 jsorg71 450 XFreeGC(g_display, gc);
1209 astrand 64 return (HGLYPH) bitmap;
1210 matty 6 }
1211 matty 7
1212 matty 25 void
1213     ui_destroy_glyph(HGLYPH glyph)
1214 matty 7 {
1215 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1216 matty 9 }
1217    
1218 matty 29 HCURSOR
1219 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1220     uint8 * andmask, uint8 * xormask)
1221 matty 9 {
1222 matty 29 HGLYPH maskglyph, cursorglyph;
1223     XColor bg, fg;
1224     Cursor xcursor;
1225     uint8 *cursor, *pcursor;
1226     uint8 *mask, *pmask;
1227     uint8 nextbit;
1228     int scanline, offset;
1229     int i, j;
1230    
1231     scanline = (width + 7) / 8;
1232     offset = scanline * height;
1233    
1234 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1235 matty 29 memset(cursor, 0, offset);
1236    
1237 forsberg 415 mask = (uint8 *) xmalloc(offset);
1238 matty 29 memset(mask, 0, offset);
1239    
1240     /* approximate AND and XOR masks with a monochrome X pointer */
1241     for (i = 0; i < height; i++)
1242 matty 7 {
1243 matty 29 offset -= scanline;
1244     pcursor = &cursor[offset];
1245     pmask = &mask[offset];
1246    
1247     for (j = 0; j < scanline; j++)
1248 matty 28 {
1249 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1250     {
1251     if (xormask[0] || xormask[1] || xormask[2])
1252     {
1253     *pcursor |= (~(*andmask) & nextbit);
1254     *pmask |= nextbit;
1255     }
1256     else
1257     {
1258     *pcursor |= ((*andmask) & nextbit);
1259     *pmask |= (~(*andmask) & nextbit);
1260     }
1261    
1262     xormask += 3;
1263     }
1264    
1265     andmask++;
1266     pcursor++;
1267     pmask++;
1268 matty 28 }
1269 matty 7 }
1270 matty 29
1271     fg.red = fg.blue = fg.green = 0xffff;
1272     bg.red = bg.blue = bg.green = 0x0000;
1273     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1274    
1275     cursorglyph = ui_create_glyph(width, height, cursor);
1276     maskglyph = ui_create_glyph(width, height, mask);
1277    
1278 astrand 66 xcursor =
1279 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1280 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1281 astrand 64
1282 matty 29 ui_destroy_glyph(maskglyph);
1283     ui_destroy_glyph(cursorglyph);
1284     xfree(mask);
1285     xfree(cursor);
1286 astrand 64 return (HCURSOR) xcursor;
1287 matty 29 }
1288    
1289     void
1290     ui_set_cursor(HCURSOR cursor)
1291     {
1292 jsorg71 450 g_current_cursor = (Cursor) cursor;
1293     XDefineCursor(g_display, g_wnd, g_current_cursor);
1294 matty 29 }
1295    
1296     void
1297     ui_destroy_cursor(HCURSOR cursor)
1298     {
1299 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1300 matty 29 }
1301    
1302     #define MAKE_XCOLOR(xc,c) \
1303     (xc)->red = ((c)->red << 8) | (c)->red; \
1304     (xc)->green = ((c)->green << 8) | (c)->green; \
1305     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1306     (xc)->flags = DoRed | DoGreen | DoBlue;
1307    
1308 n-ki 279
1309 matty 29 HCOLOURMAP
1310 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1311 matty 29 {
1312     COLOURENTRY *entry;
1313     int i, ncolours = colours->ncolours;
1314 jsorg71 450 if (!g_owncolmap)
1315 matty 28 {
1316 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1317 n-ki 279 XColor xentry;
1318     XColor xc_cache[256];
1319     uint32 colour;
1320     int colLookup = 256;
1321     for (i = 0; i < ncolours; i++)
1322 matty 28 {
1323 n-ki 279 entry = &colours->colours[i];
1324     MAKE_XCOLOR(&xentry, entry);
1325 matty 7
1326 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1327 astrand 196 {
1328 n-ki 279 /* Allocation failed, find closest match. */
1329     int j = 256;
1330     int nMinDist = 3 * 256 * 256;
1331     long nDist = nMinDist;
1332 matty 28
1333 n-ki 279 /* only get the colors once */
1334     while (colLookup--)
1335 astrand 196 {
1336 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1337     xc_cache[colLookup].red = xc_cache[colLookup].green =
1338     xc_cache[colLookup].blue = 0;
1339     xc_cache[colLookup].flags = 0;
1340 jsorg71 450 XQueryColor(g_display,
1341     DefaultColormap(g_display,
1342     DefaultScreen(g_display)),
1343 n-ki 279 &xc_cache[colLookup]);
1344 n-ki 185 }
1345 n-ki 279 colLookup = 0;
1346    
1347     /* approximate the pixel */
1348     while (j--)
1349 astrand 196 {
1350 n-ki 279 if (xc_cache[j].flags)
1351     {
1352     nDist = ((long) (xc_cache[j].red >> 8) -
1353     (long) (xentry.red >> 8)) *
1354     ((long) (xc_cache[j].red >> 8) -
1355     (long) (xentry.red >> 8)) +
1356     ((long) (xc_cache[j].green >> 8) -
1357     (long) (xentry.green >> 8)) *
1358     ((long) (xc_cache[j].green >> 8) -
1359     (long) (xentry.green >> 8)) +
1360     ((long) (xc_cache[j].blue >> 8) -
1361     (long) (xentry.blue >> 8)) *
1362     ((long) (xc_cache[j].blue >> 8) -
1363     (long) (xentry.blue >> 8));
1364     }
1365     if (nDist < nMinDist)
1366     {
1367     nMinDist = nDist;
1368     xentry.pixel = j;
1369     }
1370 n-ki 185 }
1371     }
1372 n-ki 279 colour = xentry.pixel;
1373    
1374     /* update our cache */
1375     if (xentry.pixel < 256)
1376     {
1377     xc_cache[xentry.pixel].red = xentry.red;
1378     xc_cache[xentry.pixel].green = xentry.green;
1379     xc_cache[xentry.pixel].blue = xentry.blue;
1380    
1381     }
1382    
1383    
1384     /* byte swap here to make translate_image faster */
1385     map[i] = translate_colour(colour);
1386 n-ki 185 }
1387 n-ki 279 return map;
1388     }
1389     else
1390     {
1391     XColor *xcolours, *xentry;
1392     Colormap map;
1393 matty 29
1394 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1395 n-ki 279 for (i = 0; i < ncolours; i++)
1396 astrand 196 {
1397 n-ki 279 entry = &colours->colours[i];
1398     xentry = &xcolours[i];
1399     xentry->pixel = i;
1400     MAKE_XCOLOR(xentry, entry);
1401 matty 29 }
1402    
1403 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1404     XStoreColors(g_display, map, xcolours, ncolours);
1405 n-ki 185
1406 n-ki 279 xfree(xcolours);
1407     return (HCOLOURMAP) map;
1408 matty 29 }
1409 matty 7 }
1410    
1411 matty 25 void
1412     ui_destroy_colourmap(HCOLOURMAP map)
1413 matty 7 {
1414 jsorg71 450 if (!g_owncolmap)
1415 n-ki 279 xfree(map);
1416     else
1417 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1418 matty 7 }
1419    
1420 matty 25 void
1421     ui_set_colourmap(HCOLOURMAP map)
1422 matty 7 {
1423 jsorg71 450 if (!g_owncolmap)
1424 astrand 448 {
1425 jsorg71 450 if (g_colmap)
1426     xfree(g_colmap);
1427 astrand 448
1428 jsorg71 450 g_colmap = (uint32 *) map;
1429 astrand 448 }
1430 n-ki 279 else
1431 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1432 matty 7 }
1433    
1434 matty 25 void
1435     ui_set_clip(int x, int y, int cx, int cy)
1436 matty 7 {
1437 matty 9 XRectangle rect;
1438 matty 7
1439 matty 9 rect.x = x;
1440     rect.y = y;
1441     rect.width = cx;
1442     rect.height = cy;
1443 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1444 matty 9 }
1445 matty 7
1446 matty 25 void
1447 matthewc 192 ui_reset_clip(void)
1448 matty 9 {
1449     XRectangle rect;
1450    
1451     rect.x = 0;
1452     rect.y = 0;
1453 jsorg71 447 rect.width = g_width;
1454     rect.height = g_height;
1455 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1456 matty 7 }
1457    
1458 matty 25 void
1459 matthewc 192 ui_bell(void)
1460 matty 10 {
1461 jsorg71 450 XBell(g_display, 0);
1462 matty 10 }
1463    
1464 matty 25 void
1465     ui_destblt(uint8 opcode,
1466     /* dest */ int x, int y, int cx, int cy)
1467 matty 9 {
1468 matty 29 SET_FUNCTION(opcode);
1469 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1470 matty 29 RESET_FUNCTION(opcode);
1471 matty 9 }
1472    
1473 jsorg71 373 static uint8 hatch_patterns[] = {
1474 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1475     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1476     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1477     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1478     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1479     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1480 jsorg71 373 };
1481    
1482 matty 25 void
1483     ui_patblt(uint8 opcode,
1484     /* dest */ int x, int y, int cx, int cy,
1485 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1486 matty 9 {
1487     Pixmap fill;
1488 jsorg71 59 uint8 i, ipattern[8];
1489 matty 9
1490 matty 29 SET_FUNCTION(opcode);
1491 matty 9
1492     switch (brush->style)
1493     {
1494 matty 24 case 0: /* Solid */
1495 matty 29 SET_FOREGROUND(fgcolour);
1496 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1497 matty 9 break;
1498    
1499 jsorg71 373 case 2: /* Hatch */
1500 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1501     hatch_patterns + brush->pattern[0] * 8);
1502 jsorg71 373 SET_FOREGROUND(bgcolour);
1503     SET_BACKGROUND(fgcolour);
1504 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1505     XSetStipple(g_display, g_gc, fill);
1506     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1507 jsorg71 373 FILL_RECTANGLE(x, y, cx, cy);
1508 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1509     XSetTSOrigin(g_display, g_gc, 0, 0);
1510 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1511     break;
1512    
1513 matty 24 case 3: /* Pattern */
1514 jsorg71 59 for (i = 0; i != 8; i++)
1515     ipattern[7 - i] = brush->pattern[i];
1516     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1517 matty 9
1518 matty 29 SET_FOREGROUND(bgcolour);
1519     SET_BACKGROUND(fgcolour);
1520 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1521     XSetStipple(g_display, g_gc, fill);
1522     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1523 matty 9
1524 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1525 matty 9
1526 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1527     XSetTSOrigin(g_display, g_gc, 0, 0);
1528 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1529 matty 9 break;
1530    
1531     default:
1532 matty 30 unimpl("brush %d\n", brush->style);
1533 matty 9 }
1534 matty 29
1535     RESET_FUNCTION(opcode);
1536 matty 9 }
1537    
1538 matty 25 void
1539     ui_screenblt(uint8 opcode,
1540     /* dest */ int x, int y, int cx, int cy,
1541     /* src */ int srcx, int srcy)
1542 matty 9 {
1543 matty 29 SET_FUNCTION(opcode);
1544 jsorg71 450 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1545     if (g_ownbackstore)
1546     XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1547 matty 29 RESET_FUNCTION(opcode);
1548 matty 9 }
1549    
1550 matty 25 void
1551     ui_memblt(uint8 opcode,
1552     /* dest */ int x, int y, int cx, int cy,
1553     /* src */ HBITMAP src, int srcx, int srcy)
1554 matty 9 {
1555 matty 29 SET_FUNCTION(opcode);
1556 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1557     if (g_ownbackstore)
1558     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1559 matty 29 RESET_FUNCTION(opcode);
1560 matty 9 }
1561    
1562 matty 25 void
1563     ui_triblt(uint8 opcode,
1564     /* dest */ int x, int y, int cx, int cy,
1565     /* src */ HBITMAP src, int srcx, int srcy,
1566 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1567 matty 9 {
1568     /* This is potentially difficult to do in general. Until someone
1569 matty 10 comes up with a more efficient way of doing it I am using cases. */
1570 matty 9
1571     switch (opcode)
1572     {
1573 matty 24 case 0x69: /* PDSxxn */
1574 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1575 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1576 matty 16 break;
1577    
1578 matty 24 case 0xb8: /* PSDPxax */
1579 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1580 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1581 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1582 matty 9 break;
1583    
1584 matty 29 case 0xc0: /* PSa */
1585 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1586 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1587 matty 28 break;
1588    
1589 matty 9 default:
1590 matty 30 unimpl("triblt 0x%x\n", opcode);
1591 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1592 matty 9 }
1593     }
1594    
1595 matty 25 void
1596     ui_line(uint8 opcode,
1597     /* dest */ int startx, int starty, int endx, int endy,
1598 astrand 64 /* pen */ PEN * pen)
1599 matty 9 {
1600 matty 29 SET_FUNCTION(opcode);
1601     SET_FOREGROUND(pen->colour);
1602 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1603     if (g_ownbackstore)
1604     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1605 matty 29 RESET_FUNCTION(opcode);
1606 matty 9 }
1607    
1608 matty 25 void
1609     ui_rect(
1610     /* dest */ int x, int y, int cx, int cy,
1611     /* brush */ int colour)
1612 matty 9 {
1613 matty 29 SET_FOREGROUND(colour);
1614 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1615 matty 9 }
1616    
1617 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1618 matty 25 void
1619     ui_draw_glyph(int mixmode,
1620     /* dest */ int x, int y, int cx, int cy,
1621 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1622     int bgcolour, int fgcolour)
1623 matty 9 {
1624 matty 29 SET_FOREGROUND(fgcolour);
1625     SET_BACKGROUND(bgcolour);
1626 matty 9
1627 jsorg71 450 XSetFillStyle(g_display, g_gc,
1628 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1629 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
1630     XSetTSOrigin(g_display, g_gc, x, y);
1631 matty 9
1632 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1633 matty 9
1634 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1635 matty 9 }
1636    
1637 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1638     {\
1639     glyph = cache_get_font (font, ttext[idx]);\
1640     if (!(flags & TEXT2_IMPLICIT_X))\
1641     {\
1642     xyoffset = ttext[++idx];\
1643     if ((xyoffset & 0x80))\
1644     {\
1645     if (flags & TEXT2_VERTICAL) \
1646 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1647 mmihalik 49 else\
1648 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1649     idx += 2;\
1650 mmihalik 49 }\
1651     else\
1652     {\
1653     if (flags & TEXT2_VERTICAL) \
1654     y += xyoffset;\
1655     else\
1656     x += xyoffset;\
1657     }\
1658     }\
1659     if (glyph != NULL)\
1660     {\
1661 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1662     y + glyph->baseline,\
1663 mmihalik 49 glyph->width, glyph->height,\
1664     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1665     if (flags & TEXT2_IMPLICIT_X)\
1666     x += glyph->width;\
1667     }\
1668     }
1669    
1670 matty 25 void
1671     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1672 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1673     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1674 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1675 matty 9 {
1676 matty 10 FONTGLYPH *glyph;
1677 mmihalik 49 int i, j, xyoffset;
1678     DATABLOB *entry;
1679 matty 9
1680 matty 29 SET_FOREGROUND(bgcolour);
1681 matty 28
1682 matty 9 if (boxcx > 1)
1683 matty 31 {
1684 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1685 matty 31 }
1686 matty 17 else if (mixmode == MIX_OPAQUE)
1687 matty 31 {
1688 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1689 matty 31 }
1690 matty 9
1691     /* Paint text, character by character */
1692 astrand 64 for (i = 0; i < length;)
1693     {
1694     switch (text[i])
1695     {
1696     case 0xff:
1697     if (i + 2 < length)
1698 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1699 astrand 64 else
1700     {
1701     error("this shouldn't be happening\n");
1702 astrand 265 exit(1);
1703 astrand 64 }
1704     /* this will move pointer from start to first character after FF command */
1705     length -= i + 3;
1706     text = &(text[i + 3]);
1707     i = 0;
1708 mmihalik 49 break;
1709 matty 9
1710 astrand 64 case 0xfe:
1711     entry = cache_get_text(text[i + 1]);
1712     if (entry != NULL)
1713     {
1714     if ((((uint8 *) (entry->data))[1] ==
1715 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1716 astrand 64 {
1717     if (flags & TEXT2_VERTICAL)
1718     y += text[i + 2];
1719     else
1720     x += text[i + 2];
1721     }
1722     for (j = 0; j < entry->size; j++)
1723 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1724 matthewc 44 }
1725 jsorg71 286 if (i + 2 < length)
1726     i += 3;
1727     else
1728     i += 2;
1729     length -= i;
1730     /* this will move pointer from start to first character after FE command */
1731     text = &(text[i]);
1732     i = 0;
1733 astrand 64 break;
1734 matty 17
1735 astrand 64 default:
1736     DO_GLYPH(text, i);
1737     i++;
1738     break;
1739 matty 29 }
1740 mmihalik 49 }
1741 jsorg71 450 if (g_ownbackstore)
1742 jsorg71 278 {
1743     if (boxcx > 1)
1744 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1745 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
1746     else
1747 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1748 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
1749     }
1750 matty 9 }
1751    
1752 matty 25 void
1753     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1754 matty 9 {
1755 matty 28 Pixmap pix;
1756 matty 9 XImage *image;
1757    
1758 jsorg71 450 if (g_ownbackstore)
1759 matty 31 {
1760 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1761 matty 31 }
1762     else
1763     {
1764 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1765     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1766     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1767     XFreePixmap(g_display, pix);
1768 matty 31 }
1769 matty 28
1770 jsorg71 450 offset *= g_bpp / 8;
1771     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
1772 matty 28
1773     XDestroyImage(image);
1774 matty 9 }
1775    
1776 matty 25 void
1777     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1778 matty 9 {
1779     XImage *image;
1780 matty 10 uint8 *data;
1781 matty 9
1782 jsorg71 450 offset *= g_bpp / 8;
1783     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1784 matty 10 if (data == NULL)
1785     return;
1786 matty 29
1787 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1788     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
1789 matty 29
1790 jsorg71 450 if (g_ownbackstore)
1791 matty 31 {
1792 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1793     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1794 matty 31 }
1795     else
1796     {
1797 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1798 matty 31 }
1799    
1800 matty 9 XFree(image);
1801     }

  ViewVC Help
Powered by ViewVC 1.1.26