/[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 449 - (hide annotations)
Wed Aug 27 09:42:55 2003 UTC (20 years, 8 months ago) by astrand
File MIME type: text/plain
File size: 39099 byte(s)
kbd: Restoring changed remote modifiers after keypress. Fixes problem with shift & altgr 'stuck' down after typing, for example, A

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

  ViewVC Help
Powered by ViewVC 1.1.26