/[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 328 - (hide annotations)
Tue Feb 18 13:03:51 2003 UTC (21 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 36372 byte(s)
New option for running single applications maximized

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

  ViewVC Help
Powered by ViewVC 1.1.26