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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 448 - (hide annotations)
Wed Aug 27 08:21:53 2003 UTC (20 years, 8 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 39038 byte(s)
Fixed memory leak with colormap allocation.

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

  ViewVC Help
Powered by ViewVC 1.1.26