/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 332 - (hide annotations)
Tue Feb 18 13:51:43 2003 UTC (21 years, 3 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 36603 byte(s)
Prevent restoring by double click 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 332 /* Check from right to left: */
862    
863     if (xevent.xbutton.x >= width - win_button_size)
864 astrand 328 {
865 astrand 331 /* The close button, continue */
866 astrand 328 ;
867     }
868     else if (xevent.xbutton.x >= width - win_button_size * 2)
869     {
870     /* The maximize/restore button. Do not send to
871     server. It might be a good idea to change the
872     cursor or give some other visible indication
873     that rdesktop inhibited this click */
874     break;
875     }
876     else if (xevent.xbutton.x >= width - win_button_size * 3)
877     {
878     /* The minimize button. Iconify window. */
879     XIconifyWindow(display, wnd,
880     DefaultScreen(display));
881     break;
882     }
883 astrand 332 else
884     {
885     /* Ignore clicks to the rest of the border. This includes
886     the system menu, but also inhibits double clicks on the
887     border itself. */
888     break;
889     }
890 astrand 328 }
891    
892 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
893 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
894 matty 10 break;
895    
896     case MotionNotify:
897 jsorg71 288 if (fullscreen && !focused)
898     XSetInputFocus(display, wnd, RevertToPointerRoot,
899     CurrentTime);
900 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
901 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
902 matty 28 break;
903    
904 matthewc 194 case FocusIn:
905 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
906     break;
907     focused = True;
908 astrand 261 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
909     &dummy, &dummy, &state);
910 matthewc 203 reset_modifier_keys(state);
911 jsorg71 257 if (grab_keyboard && mouse_in_wnd)
912 astrand 76 XGrabKeyboard(display, wnd, True,
913 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
914 matty 28 break;
915    
916 matthewc 194 case FocusOut:
917 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
918     break;
919     focused = False;
920 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
921 astrand 76 XUngrabKeyboard(display, CurrentTime);
922 matty 28 break;
923 matty 31
924 matthewc 250 case EnterNotify:
925     /* we only register for this event when in fullscreen mode */
926 jsorg71 257 /* or grab_keyboard */
927     mouse_in_wnd = True;
928     if (fullscreen)
929     {
930 astrand 261 XSetInputFocus(display, wnd, RevertToPointerRoot,
931     CurrentTime);
932 jsorg71 257 break;
933     }
934     if (focused)
935     XGrabKeyboard(display, wnd, True,
936     GrabModeAsync, GrabModeAsync, CurrentTime);
937 matthewc 250 break;
938    
939 matthewc 253 case LeaveNotify:
940 jsorg71 257 /* we only register for this event when grab_keyboard */
941     mouse_in_wnd = False;
942 matthewc 253 XUngrabKeyboard(display, CurrentTime);
943     break;
944    
945 matty 31 case Expose:
946     XCopyArea(display, backstore, wnd, gc,
947 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
948 astrand 64 xevent.xexpose.width,
949     xevent.xexpose.height,
950 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
951 matty 31 break;
952 astrand 119
953     case MappingNotify:
954     /* Refresh keyboard mapping if it has changed. This is important for
955     Xvnc, since it allocates keycodes dynamically */
956     if (xevent.xmapping.request == MappingKeyboard
957     || xevent.xmapping.request == MappingModifier)
958     XRefreshKeyboardMapping(&xevent.xmapping);
959 matthewc 203
960     if (xevent.xmapping.request == MappingModifier)
961     {
962 matthewc 204 XFreeModifiermap(mod_map);
963 matthewc 203 mod_map = XGetModifierMapping(display);
964     }
965 astrand 119 break;
966    
967 matty 9 }
968     }
969 astrand 275 /* Keep going */
970     return 1;
971 matty 9 }
972    
973 astrand 275 /* Returns 0 after user quit, 1 otherwise */
974     int
975 matty 33 ui_select(int rdp_socket)
976     {
977 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
978 matty 33 fd_set rfds;
979    
980     FD_ZERO(&rfds);
981    
982     while (True)
983     {
984 matthewc 121 /* Process any events already waiting */
985 astrand 275 if (!xwin_process_events())
986     /* User quit */
987     return 0;
988 astrand 119
989 matty 33 FD_ZERO(&rfds);
990     FD_SET(rdp_socket, &rfds);
991 matthewc 121 FD_SET(x_socket, &rfds);
992 matty 33
993     switch (select(n, &rfds, NULL, NULL, NULL))
994     {
995     case -1:
996     error("select: %s\n", strerror(errno));
997    
998     case 0:
999     continue;
1000     }
1001    
1002     if (FD_ISSET(rdp_socket, &rfds))
1003 astrand 275 return 1;
1004 matty 33 }
1005     }
1006    
1007     void
1008 matty 25 ui_move_pointer(int x, int y)
1009 matty 9 {
1010 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
1011 matty 9 }
1012    
1013 matty 25 HBITMAP
1014 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1015 matty 6 {
1016     XImage *image;
1017 matty 9 Pixmap bitmap;
1018 matty 28 uint8 *tdata;
1019 matty 29
1020 n-ki 279 tdata = (owncolmap ? data : translate_image(width, height, data));
1021 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
1022 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1023 jsorg71 311 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1024 matty 6
1025 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1026 matty 9
1027     XFree(image);
1028 n-ki 279 if (!owncolmap)
1029     xfree(tdata);
1030 matty 24 return (HBITMAP) bitmap;
1031 matty 6 }
1032    
1033 matty 25 void
1034 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1035 matty 6 {
1036 matty 10 XImage *image;
1037 matty 29 uint8 *tdata;
1038 n-ki 279 tdata = (owncolmap ? data : translate_image(width, height, data));
1039 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1040 jsorg71 311 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1041 matty 28
1042 matty 31 if (ownbackstore)
1043     {
1044     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1045     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1046     }
1047     else
1048     {
1049     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1050     }
1051 matty 29
1052 matty 24 XFree(image);
1053 n-ki 279 if (!owncolmap)
1054     xfree(tdata);
1055 matty 6 }
1056    
1057 matty 25 void
1058     ui_destroy_bitmap(HBITMAP bmp)
1059 matty 6 {
1060 astrand 64 XFreePixmap(display, (Pixmap) bmp);
1061 matty 10 }
1062    
1063 matty 25 HGLYPH
1064 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1065 matty 10 {
1066 matty 9 XImage *image;
1067     Pixmap bitmap;
1068     int scanline;
1069     GC gc;
1070 matty 6
1071 matty 9 scanline = (width + 7) / 8;
1072 matty 6
1073 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
1074     gc = XCreateGC(display, bitmap, 0, NULL);
1075 matty 9
1076 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1077 astrand 73 width, height, 8, scanline);
1078 matty 23 image->byte_order = MSBFirst;
1079     image->bitmap_bit_order = MSBFirst;
1080     XInitImage(image);
1081    
1082 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1083 matty 29
1084 matty 9 XFree(image);
1085 matty 10 XFreeGC(display, gc);
1086 astrand 64 return (HGLYPH) bitmap;
1087 matty 6 }
1088 matty 7
1089 matty 25 void
1090     ui_destroy_glyph(HGLYPH glyph)
1091 matty 7 {
1092 astrand 64 XFreePixmap(display, (Pixmap) glyph);
1093 matty 9 }
1094    
1095 matty 29 HCURSOR
1096 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1097     uint8 * andmask, uint8 * xormask)
1098 matty 9 {
1099 matty 29 HGLYPH maskglyph, cursorglyph;
1100     XColor bg, fg;
1101     Cursor xcursor;
1102     uint8 *cursor, *pcursor;
1103     uint8 *mask, *pmask;
1104     uint8 nextbit;
1105     int scanline, offset;
1106     int i, j;
1107    
1108     scanline = (width + 7) / 8;
1109     offset = scanline * height;
1110    
1111     cursor = xmalloc(offset);
1112     memset(cursor, 0, offset);
1113    
1114     mask = xmalloc(offset);
1115     memset(mask, 0, offset);
1116    
1117     /* approximate AND and XOR masks with a monochrome X pointer */
1118     for (i = 0; i < height; i++)
1119 matty 7 {
1120 matty 29 offset -= scanline;
1121     pcursor = &cursor[offset];
1122     pmask = &mask[offset];
1123    
1124     for (j = 0; j < scanline; j++)
1125 matty 28 {
1126 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1127     {
1128     if (xormask[0] || xormask[1] || xormask[2])
1129     {
1130     *pcursor |= (~(*andmask) & nextbit);
1131     *pmask |= nextbit;
1132     }
1133     else
1134     {
1135     *pcursor |= ((*andmask) & nextbit);
1136     *pmask |= (~(*andmask) & nextbit);
1137     }
1138    
1139     xormask += 3;
1140     }
1141    
1142     andmask++;
1143     pcursor++;
1144     pmask++;
1145 matty 28 }
1146 matty 7 }
1147 matty 29
1148     fg.red = fg.blue = fg.green = 0xffff;
1149     bg.red = bg.blue = bg.green = 0x0000;
1150     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1151    
1152     cursorglyph = ui_create_glyph(width, height, cursor);
1153     maskglyph = ui_create_glyph(width, height, mask);
1154    
1155 astrand 66 xcursor =
1156     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1157     (Pixmap) maskglyph, &fg, &bg, x, y);
1158 astrand 64
1159 matty 29 ui_destroy_glyph(maskglyph);
1160     ui_destroy_glyph(cursorglyph);
1161     xfree(mask);
1162     xfree(cursor);
1163 astrand 64 return (HCURSOR) xcursor;
1164 matty 29 }
1165    
1166     void
1167     ui_set_cursor(HCURSOR cursor)
1168     {
1169 matthewc 188 current_cursor = (Cursor) cursor;
1170     XDefineCursor(display, wnd, current_cursor);
1171 matty 29 }
1172    
1173     void
1174     ui_destroy_cursor(HCURSOR cursor)
1175     {
1176 astrand 64 XFreeCursor(display, (Cursor) cursor);
1177 matty 29 }
1178    
1179     #define MAKE_XCOLOR(xc,c) \
1180     (xc)->red = ((c)->red << 8) | (c)->red; \
1181     (xc)->green = ((c)->green << 8) | (c)->green; \
1182     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1183     (xc)->flags = DoRed | DoGreen | DoBlue;
1184    
1185 n-ki 279
1186 matty 29 HCOLOURMAP
1187 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1188 matty 29 {
1189     COLOURENTRY *entry;
1190     int i, ncolours = colours->ncolours;
1191 n-ki 279 if (!owncolmap)
1192 matty 28 {
1193 n-ki 279 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1194     XColor xentry;
1195     XColor xc_cache[256];
1196     uint32 colour;
1197     int colLookup = 256;
1198     for (i = 0; i < ncolours; i++)
1199 matty 28 {
1200 n-ki 279 entry = &colours->colours[i];
1201     MAKE_XCOLOR(&xentry, entry);
1202 matty 7
1203 n-ki 279 if (XAllocColor(display, xcolmap, &xentry) == 0)
1204 astrand 196 {
1205 n-ki 279 /* Allocation failed, find closest match. */
1206     int j = 256;
1207     int nMinDist = 3 * 256 * 256;
1208     long nDist = nMinDist;
1209 matty 28
1210 n-ki 279 /* only get the colors once */
1211     while (colLookup--)
1212 astrand 196 {
1213 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1214     xc_cache[colLookup].red = xc_cache[colLookup].green =
1215     xc_cache[colLookup].blue = 0;
1216     xc_cache[colLookup].flags = 0;
1217     XQueryColor(display,
1218     DefaultColormap(display,
1219     DefaultScreen(display)),
1220     &xc_cache[colLookup]);
1221 n-ki 185 }
1222 n-ki 279 colLookup = 0;
1223    
1224     /* approximate the pixel */
1225     while (j--)
1226 astrand 196 {
1227 n-ki 279 if (xc_cache[j].flags)
1228     {
1229     nDist = ((long) (xc_cache[j].red >> 8) -
1230     (long) (xentry.red >> 8)) *
1231     ((long) (xc_cache[j].red >> 8) -
1232     (long) (xentry.red >> 8)) +
1233     ((long) (xc_cache[j].green >> 8) -
1234     (long) (xentry.green >> 8)) *
1235     ((long) (xc_cache[j].green >> 8) -
1236     (long) (xentry.green >> 8)) +
1237     ((long) (xc_cache[j].blue >> 8) -
1238     (long) (xentry.blue >> 8)) *
1239     ((long) (xc_cache[j].blue >> 8) -
1240     (long) (xentry.blue >> 8));
1241     }
1242     if (nDist < nMinDist)
1243     {
1244     nMinDist = nDist;
1245     xentry.pixel = j;
1246     }
1247 n-ki 185 }
1248     }
1249 n-ki 279 colour = xentry.pixel;
1250    
1251     /* update our cache */
1252     if (xentry.pixel < 256)
1253     {
1254     xc_cache[xentry.pixel].red = xentry.red;
1255     xc_cache[xentry.pixel].green = xentry.green;
1256     xc_cache[xentry.pixel].blue = xentry.blue;
1257    
1258     }
1259    
1260    
1261     /* byte swap here to make translate_image faster */
1262     map[i] = translate_colour(colour);
1263 n-ki 185 }
1264 n-ki 279 return map;
1265     }
1266     else
1267     {
1268     XColor *xcolours, *xentry;
1269     Colormap map;
1270 matty 29
1271 n-ki 279 xcolours = xmalloc(sizeof(XColor) * ncolours);
1272     for (i = 0; i < ncolours; i++)
1273 astrand 196 {
1274 n-ki 279 entry = &colours->colours[i];
1275     xentry = &xcolours[i];
1276     xentry->pixel = i;
1277     MAKE_XCOLOR(xentry, entry);
1278 matty 29 }
1279    
1280 n-ki 279 map = XCreateColormap(display, wnd, visual, AllocAll);
1281     XStoreColors(display, map, xcolours, ncolours);
1282 n-ki 185
1283 n-ki 279 xfree(xcolours);
1284     return (HCOLOURMAP) map;
1285 matty 29 }
1286 matty 7 }
1287    
1288 matty 25 void
1289     ui_destroy_colourmap(HCOLOURMAP map)
1290 matty 7 {
1291 n-ki 279 if (!owncolmap)
1292     xfree(map);
1293     else
1294     XFreeColormap(display, (Colormap) map);
1295 matty 7 }
1296    
1297 matty 25 void
1298     ui_set_colourmap(HCOLOURMAP map)
1299 matty 7 {
1300 n-ki 279 if (!owncolmap)
1301     colmap = map;
1302     else
1303     XSetWindowColormap(display, wnd, (Colormap) map);
1304 matty 7 }
1305    
1306 matty 25 void
1307     ui_set_clip(int x, int y, int cx, int cy)
1308 matty 7 {
1309 matty 9 XRectangle rect;
1310 matty 7
1311 matty 9 rect.x = x;
1312     rect.y = y;
1313     rect.width = cx;
1314     rect.height = cy;
1315 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1316 matty 9 }
1317 matty 7
1318 matty 25 void
1319 matthewc 192 ui_reset_clip(void)
1320 matty 9 {
1321     XRectangle rect;
1322    
1323     rect.x = 0;
1324     rect.y = 0;
1325 matty 10 rect.width = width;
1326     rect.height = height;
1327     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1328 matty 7 }
1329    
1330 matty 25 void
1331 matthewc 192 ui_bell(void)
1332 matty 10 {
1333     XBell(display, 0);
1334     }
1335    
1336 matty 25 void
1337     ui_destblt(uint8 opcode,
1338     /* dest */ int x, int y, int cx, int cy)
1339 matty 9 {
1340 matty 29 SET_FUNCTION(opcode);
1341 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1342 matty 29 RESET_FUNCTION(opcode);
1343 matty 9 }
1344    
1345 matty 25 void
1346     ui_patblt(uint8 opcode,
1347     /* dest */ int x, int y, int cx, int cy,
1348 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1349 matty 9 {
1350     Pixmap fill;
1351 jsorg71 59 uint8 i, ipattern[8];
1352 matty 9
1353 matty 29 SET_FUNCTION(opcode);
1354 matty 9
1355     switch (brush->style)
1356     {
1357 matty 24 case 0: /* Solid */
1358 matty 29 SET_FOREGROUND(fgcolour);
1359 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1360 matty 9 break;
1361    
1362 matty 24 case 3: /* Pattern */
1363 jsorg71 59 for (i = 0; i != 8; i++)
1364     ipattern[7 - i] = brush->pattern[i];
1365     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1366 matty 9
1367 matty 29 SET_FOREGROUND(bgcolour);
1368     SET_BACKGROUND(fgcolour);
1369     XSetFillStyle(display, gc, FillOpaqueStippled);
1370     XSetStipple(display, gc, fill);
1371 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1372 matty 9
1373 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1374 matty 9
1375 matty 29 XSetFillStyle(display, gc, FillSolid);
1376 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
1377 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1378 matty 9 break;
1379    
1380     default:
1381 matty 30 unimpl("brush %d\n", brush->style);
1382 matty 9 }
1383 matty 29
1384     RESET_FUNCTION(opcode);
1385 matty 9 }
1386    
1387 matty 25 void
1388     ui_screenblt(uint8 opcode,
1389     /* dest */ int x, int y, int cx, int cy,
1390     /* src */ int srcx, int srcy)
1391 matty 9 {
1392 matty 29 SET_FUNCTION(opcode);
1393 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1394 matty 31 if (ownbackstore)
1395 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1396 matty 29 RESET_FUNCTION(opcode);
1397 matty 9 }
1398    
1399 matty 25 void
1400     ui_memblt(uint8 opcode,
1401     /* dest */ int x, int y, int cx, int cy,
1402     /* src */ HBITMAP src, int srcx, int srcy)
1403 matty 9 {
1404 matty 29 SET_FUNCTION(opcode);
1405 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1406 matty 31 if (ownbackstore)
1407 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1408 matty 29 RESET_FUNCTION(opcode);
1409 matty 9 }
1410    
1411 matty 25 void
1412     ui_triblt(uint8 opcode,
1413     /* dest */ int x, int y, int cx, int cy,
1414     /* src */ HBITMAP src, int srcx, int srcy,
1415 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1416 matty 9 {
1417     /* This is potentially difficult to do in general. Until someone
1418 matty 10 comes up with a more efficient way of doing it I am using cases. */
1419 matty 9
1420     switch (opcode)
1421     {
1422 matty 24 case 0x69: /* PDSxxn */
1423 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1424 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1425 matty 16 break;
1426    
1427 matty 24 case 0xb8: /* PSDPxax */
1428 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1429 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1430 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1431 matty 9 break;
1432    
1433 matty 29 case 0xc0: /* PSa */
1434 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1435 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1436 matty 28 break;
1437    
1438 matty 9 default:
1439 matty 30 unimpl("triblt 0x%x\n", opcode);
1440 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1441 matty 9 }
1442     }
1443    
1444 matty 25 void
1445     ui_line(uint8 opcode,
1446     /* dest */ int startx, int starty, int endx, int endy,
1447 astrand 64 /* pen */ PEN * pen)
1448 matty 9 {
1449 matty 29 SET_FUNCTION(opcode);
1450     SET_FOREGROUND(pen->colour);
1451 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1452 matty 31 if (ownbackstore)
1453     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1454 matty 29 RESET_FUNCTION(opcode);
1455 matty 9 }
1456    
1457 matty 25 void
1458     ui_rect(
1459     /* dest */ int x, int y, int cx, int cy,
1460     /* brush */ int colour)
1461 matty 9 {
1462 matty 29 SET_FOREGROUND(colour);
1463 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1464 matty 9 }
1465    
1466 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1467 matty 25 void
1468     ui_draw_glyph(int mixmode,
1469     /* dest */ int x, int y, int cx, int cy,
1470 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1471     int bgcolour, int fgcolour)
1472 matty 9 {
1473 matty 29 SET_FOREGROUND(fgcolour);
1474     SET_BACKGROUND(bgcolour);
1475 matty 9
1476 astrand 66 XSetFillStyle(display, gc,
1477 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1478 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1479 matty 29 XSetTSOrigin(display, gc, x, y);
1480 matty 9
1481 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1482 matty 9
1483 matty 29 XSetFillStyle(display, gc, FillSolid);
1484 matty 9 }
1485    
1486 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1487     {\
1488     glyph = cache_get_font (font, ttext[idx]);\
1489     if (!(flags & TEXT2_IMPLICIT_X))\
1490     {\
1491     xyoffset = ttext[++idx];\
1492     if ((xyoffset & 0x80))\
1493     {\
1494     if (flags & TEXT2_VERTICAL) \
1495 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1496 mmihalik 49 else\
1497 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1498     idx += 2;\
1499 mmihalik 49 }\
1500     else\
1501     {\
1502     if (flags & TEXT2_VERTICAL) \
1503     y += xyoffset;\
1504     else\
1505     x += xyoffset;\
1506     }\
1507     }\
1508     if (glyph != NULL)\
1509     {\
1510 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1511     y + glyph->baseline,\
1512 mmihalik 49 glyph->width, glyph->height,\
1513     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1514     if (flags & TEXT2_IMPLICIT_X)\
1515     x += glyph->width;\
1516     }\
1517     }
1518    
1519 matty 25 void
1520     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1521 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1522     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1523 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1524 matty 9 {
1525 matty 10 FONTGLYPH *glyph;
1526 mmihalik 49 int i, j, xyoffset;
1527     DATABLOB *entry;
1528 matty 9
1529 matty 29 SET_FOREGROUND(bgcolour);
1530 matty 28
1531 matty 9 if (boxcx > 1)
1532 matty 31 {
1533 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1534 matty 31 }
1535 matty 17 else if (mixmode == MIX_OPAQUE)
1536 matty 31 {
1537 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1538 matty 31 }
1539 matty 9
1540     /* Paint text, character by character */
1541 astrand 64 for (i = 0; i < length;)
1542     {
1543     switch (text[i])
1544     {
1545     case 0xff:
1546     if (i + 2 < length)
1547 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1548 astrand 64 else
1549     {
1550     error("this shouldn't be happening\n");
1551 astrand 265 exit(1);
1552 astrand 64 }
1553     /* this will move pointer from start to first character after FF command */
1554     length -= i + 3;
1555     text = &(text[i + 3]);
1556     i = 0;
1557 mmihalik 49 break;
1558 matty 9
1559 astrand 64 case 0xfe:
1560     entry = cache_get_text(text[i + 1]);
1561     if (entry != NULL)
1562     {
1563     if ((((uint8 *) (entry->data))[1] ==
1564 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1565 astrand 64 {
1566     if (flags & TEXT2_VERTICAL)
1567     y += text[i + 2];
1568     else
1569     x += text[i + 2];
1570     }
1571     for (j = 0; j < entry->size; j++)
1572 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1573 matthewc 44 }
1574 jsorg71 286 if (i + 2 < length)
1575     i += 3;
1576     else
1577     i += 2;
1578     length -= i;
1579     /* this will move pointer from start to first character after FE command */
1580     text = &(text[i]);
1581     i = 0;
1582 astrand 64 break;
1583 matty 17
1584 astrand 64 default:
1585     DO_GLYPH(text, i);
1586     i++;
1587     break;
1588 matty 29 }
1589 mmihalik 49 }
1590 jsorg71 278 if (ownbackstore)
1591     {
1592     if (boxcx > 1)
1593     XCopyArea(display, backstore, wnd, gc, boxx,
1594     boxy, boxcx, boxcy, boxx, boxy);
1595     else
1596     XCopyArea(display, backstore, wnd, gc, clipx,
1597     clipy, clipcx, clipcy, clipx, clipy);
1598     }
1599 matty 9 }
1600    
1601 matty 25 void
1602     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1603 matty 9 {
1604 matty 28 Pixmap pix;
1605 matty 9 XImage *image;
1606    
1607 matty 31 if (ownbackstore)
1608     {
1609 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1610 matty 31 }
1611     else
1612     {
1613     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1614     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1615 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1616 matty 31 XFreePixmap(display, pix);
1617     }
1618 matty 28
1619 astrand 64 offset *= bpp / 8;
1620 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1621 matty 28
1622     XDestroyImage(image);
1623 matty 9 }
1624    
1625 matty 25 void
1626     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1627 matty 9 {
1628     XImage *image;
1629 matty 10 uint8 *data;
1630 matty 9
1631 astrand 64 offset *= bpp / 8;
1632     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1633 matty 10 if (data == NULL)
1634     return;
1635 matty 29
1636 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1637 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1638 matty 29
1639 matty 31 if (ownbackstore)
1640     {
1641     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1642     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1643     }
1644     else
1645     {
1646     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1647     }
1648    
1649 matty 9 XFree(image);
1650     }

  ViewVC Help
Powered by ViewVC 1.1.26