/[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 376 - (hide annotations)
Mon May 19 21:36:33 2003 UTC (20 years, 11 months ago) by jsorg71
File MIME type: text/plain
File size: 38278 byte(s)
changes so it compiles with g++(mainly for ports)

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

  ViewVC Help
Powered by ViewVC 1.1.26