/[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 368 - (hide annotations)
Wed Apr 16 13:48:17 2003 UTC (21 years ago) by matthewc
File MIME type: text/plain
File size: 37293 byte(s)
Fix an endianness problem.

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 matty 29 uint8 *out = xmalloc(size);
417     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     && (xevent.xclient.data.l[0] == kill_atom))
791     /* 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     cursor = xmalloc(offset);
1141     memset(cursor, 0, offset);
1142    
1143     mask = xmalloc(offset);
1144     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 n-ki 279 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1223     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 n-ki 279 xcolours = xmalloc(sizeof(XColor) * ncolours);
1301     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     colmap = map;
1331     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 matty 25 void
1375     ui_patblt(uint8 opcode,
1376     /* dest */ int x, int y, int cx, int cy,
1377 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1378 matty 9 {
1379     Pixmap fill;
1380 jsorg71 59 uint8 i, ipattern[8];
1381 matty 9
1382 matty 29 SET_FUNCTION(opcode);
1383 matty 9
1384     switch (brush->style)
1385     {
1386 matty 24 case 0: /* Solid */
1387 matty 29 SET_FOREGROUND(fgcolour);
1388 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1389 matty 9 break;
1390    
1391 matty 24 case 3: /* Pattern */
1392 jsorg71 59 for (i = 0; i != 8; i++)
1393     ipattern[7 - i] = brush->pattern[i];
1394     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1395 matty 9
1396 matty 29 SET_FOREGROUND(bgcolour);
1397     SET_BACKGROUND(fgcolour);
1398     XSetFillStyle(display, gc, FillOpaqueStippled);
1399     XSetStipple(display, gc, fill);
1400 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1401 matty 9
1402 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1403 matty 9
1404 matty 29 XSetFillStyle(display, gc, FillSolid);
1405 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
1406 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1407 matty 9 break;
1408    
1409     default:
1410 matty 30 unimpl("brush %d\n", brush->style);
1411 matty 9 }
1412 matty 29
1413     RESET_FUNCTION(opcode);
1414 matty 9 }
1415    
1416 matty 25 void
1417     ui_screenblt(uint8 opcode,
1418     /* dest */ int x, int y, int cx, int cy,
1419     /* src */ int srcx, int srcy)
1420 matty 9 {
1421 matty 29 SET_FUNCTION(opcode);
1422 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1423 matty 31 if (ownbackstore)
1424 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1425 matty 29 RESET_FUNCTION(opcode);
1426 matty 9 }
1427    
1428 matty 25 void
1429     ui_memblt(uint8 opcode,
1430     /* dest */ int x, int y, int cx, int cy,
1431     /* src */ HBITMAP src, int srcx, int srcy)
1432 matty 9 {
1433 matty 29 SET_FUNCTION(opcode);
1434 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1435 matty 31 if (ownbackstore)
1436 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1437 matty 29 RESET_FUNCTION(opcode);
1438 matty 9 }
1439    
1440 matty 25 void
1441     ui_triblt(uint8 opcode,
1442     /* dest */ int x, int y, int cx, int cy,
1443     /* src */ HBITMAP src, int srcx, int srcy,
1444 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1445 matty 9 {
1446     /* This is potentially difficult to do in general. Until someone
1447 matty 10 comes up with a more efficient way of doing it I am using cases. */
1448 matty 9
1449     switch (opcode)
1450     {
1451 matty 24 case 0x69: /* PDSxxn */
1452 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1453 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1454 matty 16 break;
1455    
1456 matty 24 case 0xb8: /* PSDPxax */
1457 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1458 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1459 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1460 matty 9 break;
1461    
1462 matty 29 case 0xc0: /* PSa */
1463 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1464 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1465 matty 28 break;
1466    
1467 matty 9 default:
1468 matty 30 unimpl("triblt 0x%x\n", opcode);
1469 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1470 matty 9 }
1471     }
1472    
1473 matty 25 void
1474     ui_line(uint8 opcode,
1475     /* dest */ int startx, int starty, int endx, int endy,
1476 astrand 64 /* pen */ PEN * pen)
1477 matty 9 {
1478 matty 29 SET_FUNCTION(opcode);
1479     SET_FOREGROUND(pen->colour);
1480 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1481 matty 31 if (ownbackstore)
1482     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1483 matty 29 RESET_FUNCTION(opcode);
1484 matty 9 }
1485    
1486 matty 25 void
1487     ui_rect(
1488     /* dest */ int x, int y, int cx, int cy,
1489     /* brush */ int colour)
1490 matty 9 {
1491 matty 29 SET_FOREGROUND(colour);
1492 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1493 matty 9 }
1494    
1495 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1496 matty 25 void
1497     ui_draw_glyph(int mixmode,
1498     /* dest */ int x, int y, int cx, int cy,
1499 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1500     int bgcolour, int fgcolour)
1501 matty 9 {
1502 matty 29 SET_FOREGROUND(fgcolour);
1503     SET_BACKGROUND(bgcolour);
1504 matty 9
1505 astrand 66 XSetFillStyle(display, gc,
1506 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1507 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1508 matty 29 XSetTSOrigin(display, gc, x, y);
1509 matty 9
1510 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1511 matty 9
1512 matty 29 XSetFillStyle(display, gc, FillSolid);
1513 matty 9 }
1514    
1515 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1516     {\
1517     glyph = cache_get_font (font, ttext[idx]);\
1518     if (!(flags & TEXT2_IMPLICIT_X))\
1519     {\
1520     xyoffset = ttext[++idx];\
1521     if ((xyoffset & 0x80))\
1522     {\
1523     if (flags & TEXT2_VERTICAL) \
1524 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1525 mmihalik 49 else\
1526 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1527     idx += 2;\
1528 mmihalik 49 }\
1529     else\
1530     {\
1531     if (flags & TEXT2_VERTICAL) \
1532     y += xyoffset;\
1533     else\
1534     x += xyoffset;\
1535     }\
1536     }\
1537     if (glyph != NULL)\
1538     {\
1539 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1540     y + glyph->baseline,\
1541 mmihalik 49 glyph->width, glyph->height,\
1542     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1543     if (flags & TEXT2_IMPLICIT_X)\
1544     x += glyph->width;\
1545     }\
1546     }
1547    
1548 matty 25 void
1549     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1550 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1551     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1552 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1553 matty 9 {
1554 matty 10 FONTGLYPH *glyph;
1555 mmihalik 49 int i, j, xyoffset;
1556     DATABLOB *entry;
1557 matty 9
1558 matty 29 SET_FOREGROUND(bgcolour);
1559 matty 28
1560 matty 9 if (boxcx > 1)
1561 matty 31 {
1562 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1563 matty 31 }
1564 matty 17 else if (mixmode == MIX_OPAQUE)
1565 matty 31 {
1566 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1567 matty 31 }
1568 matty 9
1569     /* Paint text, character by character */
1570 astrand 64 for (i = 0; i < length;)
1571     {
1572     switch (text[i])
1573     {
1574     case 0xff:
1575     if (i + 2 < length)
1576 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1577 astrand 64 else
1578     {
1579     error("this shouldn't be happening\n");
1580 astrand 265 exit(1);
1581 astrand 64 }
1582     /* this will move pointer from start to first character after FF command */
1583     length -= i + 3;
1584     text = &(text[i + 3]);
1585     i = 0;
1586 mmihalik 49 break;
1587 matty 9
1588 astrand 64 case 0xfe:
1589     entry = cache_get_text(text[i + 1]);
1590     if (entry != NULL)
1591     {
1592     if ((((uint8 *) (entry->data))[1] ==
1593 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1594 astrand 64 {
1595     if (flags & TEXT2_VERTICAL)
1596     y += text[i + 2];
1597     else
1598     x += text[i + 2];
1599     }
1600     for (j = 0; j < entry->size; j++)
1601 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1602 matthewc 44 }
1603 jsorg71 286 if (i + 2 < length)
1604     i += 3;
1605     else
1606     i += 2;
1607     length -= i;
1608     /* this will move pointer from start to first character after FE command */
1609     text = &(text[i]);
1610     i = 0;
1611 astrand 64 break;
1612 matty 17
1613 astrand 64 default:
1614     DO_GLYPH(text, i);
1615     i++;
1616     break;
1617 matty 29 }
1618 mmihalik 49 }
1619 jsorg71 278 if (ownbackstore)
1620     {
1621     if (boxcx > 1)
1622     XCopyArea(display, backstore, wnd, gc, boxx,
1623     boxy, boxcx, boxcy, boxx, boxy);
1624     else
1625     XCopyArea(display, backstore, wnd, gc, clipx,
1626     clipy, clipcx, clipcy, clipx, clipy);
1627     }
1628 matty 9 }
1629    
1630 matty 25 void
1631     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1632 matty 9 {
1633 matty 28 Pixmap pix;
1634 matty 9 XImage *image;
1635    
1636 matty 31 if (ownbackstore)
1637     {
1638 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1639 matty 31 }
1640     else
1641     {
1642     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1643     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1644 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1645 matty 31 XFreePixmap(display, pix);
1646     }
1647 matty 28
1648 astrand 64 offset *= bpp / 8;
1649 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1650 matty 28
1651     XDestroyImage(image);
1652 matty 9 }
1653    
1654 matty 25 void
1655     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1656 matty 9 {
1657     XImage *image;
1658 matty 10 uint8 *data;
1659 matty 9
1660 astrand 64 offset *= bpp / 8;
1661     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1662 matty 10 if (data == NULL)
1663     return;
1664 matty 29
1665 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1666 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1667 matty 29
1668 matty 31 if (ownbackstore)
1669     {
1670     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1671     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1672     }
1673     else
1674     {
1675     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1676     }
1677    
1678 matty 9 XFree(image);
1679     }

  ViewVC Help
Powered by ViewVC 1.1.26