/[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 331 - (hide annotations)
Tue Feb 18 13:44:27 2003 UTC (21 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 36498 byte(s)
Prevent access to sys menu in single app mode

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

  ViewVC Help
Powered by ViewVC 1.1.26