/[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 435 - (hide annotations)
Wed Jul 9 09:18:20 2003 UTC (20 years, 10 months ago) by astrand
File MIME type: text/plain
File size: 38856 byte(s)
Indent fixes

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 matty 10 extern int width;
29     extern int height;
30 matty 29 extern BOOL sendmotion;
31 matty 28 extern BOOL fullscreen;
32 astrand 76 extern BOOL grab_keyboard;
33 astrand 262 extern BOOL hide_decorations;
34 jsorg71 100 extern char title[];
35 jsorg71 309 extern int server_bpp;
36 astrand 328 extern int win_button_size;
37 matthewc 188 BOOL enable_compose = False;
38 jsorg71 257 BOOL focused;
39     BOOL 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 matty 28 static uint32 *colmap;
107 matty 10
108 jsorg71 311 #define TRANSLATE(col) ( 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     switch (server_bpp)
222     {
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 316 switch (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 astrand 263 if ((width == 0) || (height == 0))
574     {
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 matthewc 300 width = cx;
581     height = cy;
582     }
583     else
584     {
585 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
586 astrand 274 width = 800;
587     height = 600;
588 astrand 263 }
589     }
590    
591 astrand 82 if (fullscreen)
592 jsorg71 81 {
593     width = WidthOfScreen(screen);
594     height = HeightOfScreen(screen);
595     }
596 matthewc 121
597 matthewc 160 /* make sure width is a multiple of 4 */
598     width = (width + 3) & ~3;
599    
600 matthewc 188 if (ownbackstore)
601     {
602 astrand 196 backstore =
603     XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
604 matthewc 188
605     /* clear to prevent rubbish being exposed at startup */
606     XSetForeground(display, gc, BlackPixelOfScreen(screen));
607     XFillRectangle(display, backstore, gc, 0, 0, width, height);
608     }
609    
610 matthewc 203 mod_map = XGetModifierMapping(display);
611    
612 matthewc 188 if (enable_compose)
613     IM = XOpenIM(display, NULL, NULL, NULL);
614    
615 matthewc 121 xkeymap_init();
616 matthewc 432 xclip_init();
617 jsorg71 316
618     /* todo take this out when high colour is done */
619     printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
620    
621 jsorg71 81 return True;
622     }
623 astrand 66
624 matthewc 188 void
625 matthewc 192 ui_deinit(void)
626 matthewc 188 {
627     if (IM != NULL)
628     XCloseIM(IM);
629    
630 matthewc 204 XFreeModifiermap(mod_map);
631 matthewc 203
632 matthewc 188 if (ownbackstore)
633     XFreePixmap(display, backstore);
634    
635     XFreeGC(display, gc);
636     XCloseDisplay(display);
637     display = NULL;
638     }
639    
640 matthewc 121 BOOL
641 matthewc 192 ui_create_window(void)
642 matty 6 {
643 matthewc 121 XSetWindowAttributes attribs;
644 matty 28 XClassHint *classhints;
645     XSizeHints *sizehints;
646 matthewc 188 int wndwidth, wndheight;
647 matthewc 432 long input_mask, ic_input_mask;
648 jsorg71 100 XEvent xevent;
649    
650 astrand 196 wndwidth = fullscreen ? WidthOfScreen(screen) : width;
651 matthewc 188 wndheight = fullscreen ? HeightOfScreen(screen) : height;
652    
653 matthewc 121 attribs.background_pixel = BlackPixelOfScreen(screen);
654     attribs.backing_store = ownbackstore ? NotUseful : Always;
655     attribs.override_redirect = fullscreen;
656 matthewc 188
657     wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
658 matthewc 121 0, CopyFromParent, InputOutput, CopyFromParent,
659     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
660 jsorg71 100
661     XStoreName(display, wnd, title);
662    
663 astrand 262 if (hide_decorations)
664     mwm_hide_decorations();
665    
666 jsorg71 100 classhints = XAllocClassHint();
667     if (classhints != NULL)
668     {
669     classhints->res_name = classhints->res_class = "rdesktop";
670     XSetClassHint(display, wnd, classhints);
671     XFree(classhints);
672     }
673    
674     sizehints = XAllocSizeHints();
675     if (sizehints)
676     {
677     sizehints->flags = PMinSize | PMaxSize;
678     sizehints->min_width = sizehints->max_width = width;
679     sizehints->min_height = sizehints->max_height = height;
680     XSetWMNormalHints(display, wnd, sizehints);
681     XFree(sizehints);
682     }
683    
684 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
685 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
686 matthewc 121
687     if (sendmotion)
688     input_mask |= PointerMotionMask;
689     if (ownbackstore)
690     input_mask |= ExposureMask;
691 jsorg71 257 if (fullscreen || grab_keyboard)
692 matthewc 250 input_mask |= EnterWindowMask;
693 jsorg71 257 if (grab_keyboard)
694     input_mask |= LeaveWindowMask;
695 jsorg71 100
696 matthewc 188 if (IM != NULL)
697     {
698     IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
699     XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
700    
701 astrand 196 if ((IC != NULL)
702     && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
703 matthewc 188 input_mask |= ic_input_mask;
704     }
705    
706 jsorg71 100 XSelectInput(display, wnd, input_mask);
707 matthewc 188 XMapWindow(display, wnd);
708 jsorg71 100
709 matthewc 208 /* wait for VisibilityNotify */
710 astrand 196 do
711     {
712 matthewc 208 XMaskEvent(display, VisibilityChangeMask, &xevent);
713 astrand 196 }
714 matthewc 208 while (xevent.type != VisibilityNotify);
715 matthewc 123
716 jsorg71 257 focused = False;
717     mouse_in_wnd = False;
718    
719 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
720     protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
721     kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
722     XSetWMProtocols(display, wnd, &kill_atom, 1);
723    
724 matty 10 return True;
725 matty 6 }
726    
727 matty 25 void
728 matthewc 192 ui_destroy_window(void)
729 matty 6 {
730 matthewc 188 if (IC != NULL)
731     XDestroyIC(IC);
732 matty 31
733 matty 10 XDestroyWindow(display, wnd);
734 matty 6 }
735    
736 jsorg71 100 void
737 matthewc 192 xwin_toggle_fullscreen(void)
738 jsorg71 100 {
739 matthewc 188 Pixmap contents = 0;
740 matthewc 123
741 matthewc 188 if (!ownbackstore)
742     {
743     /* need to save contents of window */
744     contents = XCreatePixmap(display, wnd, width, height, depth);
745     XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
746     }
747    
748     ui_destroy_window();
749 matthewc 123 fullscreen = !fullscreen;
750 matthewc 188 ui_create_window();
751 matthewc 123
752 matthewc 188 XDefineCursor(display, wnd, current_cursor);
753    
754     if (!ownbackstore)
755     {
756     XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
757     XFreePixmap(display, contents);
758     }
759 jsorg71 100 }
760    
761 astrand 275 /* Process all events in Xlib queue
762     Returns 0 after user quit, 1 otherwise */
763     static int
764 matthewc 192 xwin_process_events(void)
765 matty 9 {
766 n-ki 54 XEvent xevent;
767 matthewc 38 KeySym keysym;
768 matthewc 50 uint16 button, flags;
769 matty 10 uint32 ev_time;
770 astrand 66 key_translation tr;
771     char str[256];
772     Status status;
773 matthewc 203 unsigned int state;
774     Window wdummy;
775     int dummy;
776 matty 9
777 matthewc 123 while (XPending(display) > 0)
778 matty 9 {
779 matthewc 123 XNextEvent(display, &xevent);
780    
781 matthewc 188 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
782 astrand 66 {
783 astrand 84 DEBUG_KBD(("Filtering event\n"));
784 astrand 66 continue;
785     }
786    
787 matthewc 50 flags = 0;
788 matty 10
789 n-ki 54 switch (xevent.type)
790 matty 9 {
791 astrand 275 case ClientMessage:
792     /* the window manager told us to quit */
793     if ((xevent.xclient.message_type == protocol_atom)
794 forsberg 415 && ((Atom) xevent.xclient.data.l[0] == kill_atom))
795 astrand 275 /* Quit */
796     return 0;
797     break;
798    
799 matty 9 case KeyPress:
800 matthewc 432 last_gesturetime = xevent.xkey.time;
801 astrand 66 if (IC != NULL)
802     /* Multi_key compatible version */
803     {
804     XmbLookupString(IC,
805 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
806     &status);
807 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
808 astrand 66 {
809 astrand 82 error("XmbLookupString failed with status 0x%x\n",
810     status);
811 astrand 66 break;
812     }
813     }
814     else
815     {
816     /* Plain old XLookupString */
817 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
818 astrand 66 XLookupString((XKeyEvent *) & xevent,
819 astrand 82 str, sizeof(str), &keysym, NULL);
820 astrand 66 }
821    
822 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
823     get_ksname(keysym)));
824 astrand 66
825 matthewc 203 ev_time = time(NULL);
826     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
827 astrand 118 break;
828    
829 astrand 66 tr = xkeymap_translate_key(keysym,
830 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
831 astrand 69
832 astrand 66 if (tr.scancode == 0)
833 n-ki 52 break;
834    
835 astrand 115 ensure_remote_modifiers(ev_time, tr);
836    
837 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
838 astrand 66 break;
839 matthewc 203
840 astrand 66 case KeyRelease:
841 matthewc 432 last_gesturetime = xevent.xkey.time;
842 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
843     sizeof(str), &keysym, NULL);
844 n-ki 52
845 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
846 matthewc 203 get_ksname(keysym)));
847 n-ki 52
848 matthewc 203 ev_time = time(NULL);
849     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
850 astrand 118 break;
851    
852 astrand 66 tr = xkeymap_translate_key(keysym,
853 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
854 astrand 66
855     if (tr.scancode == 0)
856     break;
857    
858 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
859 matty 9 break;
860    
861     case ButtonPress:
862 matthewc 50 flags = MOUSE_FLAG_DOWN;
863     /* fall through */
864 matty 9
865     case ButtonRelease:
866 matthewc 432 last_gesturetime = xevent.xbutton.time;
867 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
868 matty 9 if (button == 0)
869     break;
870    
871 astrand 328 /* If win_button_size is nonzero, enable single app mode */
872     if (xevent.xbutton.y < win_button_size)
873     {
874 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
875     if (moving_wnd && (xevent.type == ButtonRelease))
876     moving_wnd = False;
877 astrand 332
878 astrand 342 /* Check from right to left: */
879    
880 astrand 332 if (xevent.xbutton.x >= width - win_button_size)
881 astrand 328 {
882 astrand 331 /* The close button, continue */
883 astrand 328 ;
884     }
885     else if (xevent.xbutton.x >= width - win_button_size * 2)
886     {
887     /* The maximize/restore button. Do not send to
888     server. It might be a good idea to change the
889     cursor or give some other visible indication
890     that rdesktop inhibited this click */
891     break;
892     }
893     else if (xevent.xbutton.x >= width - win_button_size * 3)
894     {
895     /* The minimize button. Iconify window. */
896     XIconifyWindow(display, wnd,
897     DefaultScreen(display));
898     break;
899     }
900 astrand 342 else if (xevent.xbutton.x <= win_button_size)
901     {
902     /* The system menu. Ignore. */
903     break;
904     }
905 astrand 332 else
906     {
907 astrand 342 /* The title bar. */
908     if ((xevent.type == ButtonPress) && !fullscreen
909     && hide_decorations)
910     {
911     moving_wnd = True;
912     move_x_offset = xevent.xbutton.x;
913     move_y_offset = xevent.xbutton.y;
914     }
915 astrand 332 break;
916 astrand 342
917 astrand 332 }
918 astrand 328 }
919    
920 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
921 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
922 matty 10 break;
923    
924     case MotionNotify:
925 astrand 342 if (moving_wnd)
926     {
927     XMoveWindow(display, wnd,
928     xevent.xmotion.x_root - move_x_offset,
929     xevent.xmotion.y_root - move_y_offset);
930     break;
931     }
932    
933 jsorg71 288 if (fullscreen && !focused)
934     XSetInputFocus(display, wnd, RevertToPointerRoot,
935     CurrentTime);
936 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
937 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
938 matty 28 break;
939    
940 matthewc 194 case FocusIn:
941 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
942     break;
943     focused = True;
944 astrand 261 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
945     &dummy, &dummy, &state);
946 matthewc 203 reset_modifier_keys(state);
947 jsorg71 257 if (grab_keyboard && mouse_in_wnd)
948 astrand 76 XGrabKeyboard(display, wnd, True,
949 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
950 matty 28 break;
951    
952 matthewc 194 case FocusOut:
953 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
954     break;
955     focused = False;
956 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
957 astrand 76 XUngrabKeyboard(display, CurrentTime);
958 matty 28 break;
959 matty 31
960 matthewc 250 case EnterNotify:
961     /* we only register for this event when in fullscreen mode */
962 jsorg71 257 /* or grab_keyboard */
963     mouse_in_wnd = True;
964     if (fullscreen)
965     {
966 astrand 261 XSetInputFocus(display, wnd, RevertToPointerRoot,
967     CurrentTime);
968 jsorg71 257 break;
969     }
970     if (focused)
971     XGrabKeyboard(display, wnd, True,
972     GrabModeAsync, GrabModeAsync, CurrentTime);
973 matthewc 250 break;
974    
975 matthewc 253 case LeaveNotify:
976 jsorg71 257 /* we only register for this event when grab_keyboard */
977     mouse_in_wnd = False;
978 matthewc 253 XUngrabKeyboard(display, CurrentTime);
979     break;
980    
981 matty 31 case Expose:
982     XCopyArea(display, backstore, wnd, gc,
983 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
984 astrand 64 xevent.xexpose.width,
985     xevent.xexpose.height,
986 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
987 matty 31 break;
988 astrand 119
989     case MappingNotify:
990     /* Refresh keyboard mapping if it has changed. This is important for
991     Xvnc, since it allocates keycodes dynamically */
992     if (xevent.xmapping.request == MappingKeyboard
993     || xevent.xmapping.request == MappingModifier)
994     XRefreshKeyboardMapping(&xevent.xmapping);
995 matthewc 203
996     if (xevent.xmapping.request == MappingModifier)
997     {
998 matthewc 204 XFreeModifiermap(mod_map);
999 matthewc 203 mod_map = XGetModifierMapping(display);
1000     }
1001 astrand 119 break;
1002 matthewc 432
1003 astrand 435 /* clipboard stuff */
1004 forsberg 415 case SelectionNotify:
1005 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1006 forsberg 415 break;
1007     case SelectionRequest:
1008 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1009 forsberg 415 break;
1010 matthewc 432 case SelectionClear:
1011     xclip_handle_SelectionClear();
1012     break;
1013 forsberg 415 case PropertyNotify:
1014 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1015 forsberg 415 break;
1016 matty 9 }
1017     }
1018 astrand 275 /* Keep going */
1019     return 1;
1020 matty 9 }
1021    
1022 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1023     int
1024 matty 33 ui_select(int rdp_socket)
1025     {
1026 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1027 matty 33 fd_set rfds;
1028    
1029     FD_ZERO(&rfds);
1030    
1031     while (True)
1032     {
1033 matthewc 121 /* Process any events already waiting */
1034 astrand 275 if (!xwin_process_events())
1035     /* User quit */
1036     return 0;
1037 astrand 119
1038 matty 33 FD_ZERO(&rfds);
1039     FD_SET(rdp_socket, &rfds);
1040 matthewc 121 FD_SET(x_socket, &rfds);
1041 matty 33
1042     switch (select(n, &rfds, NULL, NULL, NULL))
1043     {
1044     case -1:
1045     error("select: %s\n", strerror(errno));
1046    
1047     case 0:
1048     continue;
1049     }
1050    
1051     if (FD_ISSET(rdp_socket, &rfds))
1052 astrand 275 return 1;
1053 matty 33 }
1054     }
1055    
1056     void
1057 matty 25 ui_move_pointer(int x, int y)
1058 matty 9 {
1059 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
1060 matty 9 }
1061    
1062 matty 25 HBITMAP
1063 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1064 matty 6 {
1065     XImage *image;
1066 matty 9 Pixmap bitmap;
1067 matty 28 uint8 *tdata;
1068 matty 29
1069 n-ki 279 tdata = (owncolmap ? data : translate_image(width, height, data));
1070 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
1071 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1072 jsorg71 311 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1073 matty 6
1074 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1075 matty 9
1076     XFree(image);
1077 n-ki 279 if (!owncolmap)
1078     xfree(tdata);
1079 matty 24 return (HBITMAP) bitmap;
1080 matty 6 }
1081    
1082 matty 25 void
1083 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1084 matty 6 {
1085 matty 10 XImage *image;
1086 matty 29 uint8 *tdata;
1087 n-ki 279 tdata = (owncolmap ? data : translate_image(width, height, data));
1088 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1089 jsorg71 311 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1090 matty 28
1091 matty 31 if (ownbackstore)
1092     {
1093     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1094     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1095     }
1096     else
1097     {
1098     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1099     }
1100 matty 29
1101 matty 24 XFree(image);
1102 n-ki 279 if (!owncolmap)
1103     xfree(tdata);
1104 matty 6 }
1105    
1106 matty 25 void
1107     ui_destroy_bitmap(HBITMAP bmp)
1108 matty 6 {
1109 astrand 64 XFreePixmap(display, (Pixmap) bmp);
1110 matty 10 }
1111    
1112 matty 25 HGLYPH
1113 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1114 matty 10 {
1115 matty 9 XImage *image;
1116     Pixmap bitmap;
1117     int scanline;
1118     GC gc;
1119 matty 6
1120 matty 9 scanline = (width + 7) / 8;
1121 matty 6
1122 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
1123     gc = XCreateGC(display, bitmap, 0, NULL);
1124 matty 9
1125 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1126 astrand 73 width, height, 8, scanline);
1127 matty 23 image->byte_order = MSBFirst;
1128     image->bitmap_bit_order = MSBFirst;
1129     XInitImage(image);
1130    
1131 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1132 matty 29
1133 matty 9 XFree(image);
1134 matty 10 XFreeGC(display, gc);
1135 astrand 64 return (HGLYPH) bitmap;
1136 matty 6 }
1137 matty 7
1138 matty 25 void
1139     ui_destroy_glyph(HGLYPH glyph)
1140 matty 7 {
1141 astrand 64 XFreePixmap(display, (Pixmap) glyph);
1142 matty 9 }
1143    
1144 matty 29 HCURSOR
1145 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1146     uint8 * andmask, uint8 * xormask)
1147 matty 9 {
1148 matty 29 HGLYPH maskglyph, cursorglyph;
1149     XColor bg, fg;
1150     Cursor xcursor;
1151     uint8 *cursor, *pcursor;
1152     uint8 *mask, *pmask;
1153     uint8 nextbit;
1154     int scanline, offset;
1155     int i, j;
1156    
1157     scanline = (width + 7) / 8;
1158     offset = scanline * height;
1159    
1160 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1161 matty 29 memset(cursor, 0, offset);
1162    
1163 forsberg 415 mask = (uint8 *) xmalloc(offset);
1164 matty 29 memset(mask, 0, offset);
1165    
1166     /* approximate AND and XOR masks with a monochrome X pointer */
1167     for (i = 0; i < height; i++)
1168 matty 7 {
1169 matty 29 offset -= scanline;
1170     pcursor = &cursor[offset];
1171     pmask = &mask[offset];
1172    
1173     for (j = 0; j < scanline; j++)
1174 matty 28 {
1175 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1176     {
1177     if (xormask[0] || xormask[1] || xormask[2])
1178     {
1179     *pcursor |= (~(*andmask) & nextbit);
1180     *pmask |= nextbit;
1181     }
1182     else
1183     {
1184     *pcursor |= ((*andmask) & nextbit);
1185     *pmask |= (~(*andmask) & nextbit);
1186     }
1187    
1188     xormask += 3;
1189     }
1190    
1191     andmask++;
1192     pcursor++;
1193     pmask++;
1194 matty 28 }
1195 matty 7 }
1196 matty 29
1197     fg.red = fg.blue = fg.green = 0xffff;
1198     bg.red = bg.blue = bg.green = 0x0000;
1199     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1200    
1201     cursorglyph = ui_create_glyph(width, height, cursor);
1202     maskglyph = ui_create_glyph(width, height, mask);
1203    
1204 astrand 66 xcursor =
1205     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1206     (Pixmap) maskglyph, &fg, &bg, x, y);
1207 astrand 64
1208 matty 29 ui_destroy_glyph(maskglyph);
1209     ui_destroy_glyph(cursorglyph);
1210     xfree(mask);
1211     xfree(cursor);
1212 astrand 64 return (HCURSOR) xcursor;
1213 matty 29 }
1214    
1215     void
1216     ui_set_cursor(HCURSOR cursor)
1217     {
1218 matthewc 188 current_cursor = (Cursor) cursor;
1219     XDefineCursor(display, wnd, current_cursor);
1220 matty 29 }
1221    
1222     void
1223     ui_destroy_cursor(HCURSOR cursor)
1224     {
1225 astrand 64 XFreeCursor(display, (Cursor) cursor);
1226 matty 29 }
1227    
1228     #define MAKE_XCOLOR(xc,c) \
1229     (xc)->red = ((c)->red << 8) | (c)->red; \
1230     (xc)->green = ((c)->green << 8) | (c)->green; \
1231     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1232     (xc)->flags = DoRed | DoGreen | DoBlue;
1233    
1234 n-ki 279
1235 matty 29 HCOLOURMAP
1236 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1237 matty 29 {
1238     COLOURENTRY *entry;
1239     int i, ncolours = colours->ncolours;
1240 n-ki 279 if (!owncolmap)
1241 matty 28 {
1242 forsberg 415 uint32 *map = (uint32 *) xmalloc(sizeof(*colmap) * ncolours);
1243 n-ki 279 XColor xentry;
1244     XColor xc_cache[256];
1245     uint32 colour;
1246     int colLookup = 256;
1247     for (i = 0; i < ncolours; i++)
1248 matty 28 {
1249 n-ki 279 entry = &colours->colours[i];
1250     MAKE_XCOLOR(&xentry, entry);
1251 matty 7
1252 n-ki 279 if (XAllocColor(display, xcolmap, &xentry) == 0)
1253 astrand 196 {
1254 n-ki 279 /* Allocation failed, find closest match. */
1255     int j = 256;
1256     int nMinDist = 3 * 256 * 256;
1257     long nDist = nMinDist;
1258 matty 28
1259 n-ki 279 /* only get the colors once */
1260     while (colLookup--)
1261 astrand 196 {
1262 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1263     xc_cache[colLookup].red = xc_cache[colLookup].green =
1264     xc_cache[colLookup].blue = 0;
1265     xc_cache[colLookup].flags = 0;
1266     XQueryColor(display,
1267     DefaultColormap(display,
1268     DefaultScreen(display)),
1269     &xc_cache[colLookup]);
1270 n-ki 185 }
1271 n-ki 279 colLookup = 0;
1272    
1273     /* approximate the pixel */
1274     while (j--)
1275 astrand 196 {
1276 n-ki 279 if (xc_cache[j].flags)
1277     {
1278     nDist = ((long) (xc_cache[j].red >> 8) -
1279     (long) (xentry.red >> 8)) *
1280     ((long) (xc_cache[j].red >> 8) -
1281     (long) (xentry.red >> 8)) +
1282     ((long) (xc_cache[j].green >> 8) -
1283     (long) (xentry.green >> 8)) *
1284     ((long) (xc_cache[j].green >> 8) -
1285     (long) (xentry.green >> 8)) +
1286     ((long) (xc_cache[j].blue >> 8) -
1287     (long) (xentry.blue >> 8)) *
1288     ((long) (xc_cache[j].blue >> 8) -
1289     (long) (xentry.blue >> 8));
1290     }
1291     if (nDist < nMinDist)
1292     {
1293     nMinDist = nDist;
1294     xentry.pixel = j;
1295     }
1296 n-ki 185 }
1297     }
1298 n-ki 279 colour = xentry.pixel;
1299    
1300     /* update our cache */
1301     if (xentry.pixel < 256)
1302     {
1303     xc_cache[xentry.pixel].red = xentry.red;
1304     xc_cache[xentry.pixel].green = xentry.green;
1305     xc_cache[xentry.pixel].blue = xentry.blue;
1306    
1307     }
1308    
1309    
1310     /* byte swap here to make translate_image faster */
1311     map[i] = translate_colour(colour);
1312 n-ki 185 }
1313 n-ki 279 return map;
1314     }
1315     else
1316     {
1317     XColor *xcolours, *xentry;
1318     Colormap map;
1319 matty 29
1320 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1321 n-ki 279 for (i = 0; i < ncolours; i++)
1322 astrand 196 {
1323 n-ki 279 entry = &colours->colours[i];
1324     xentry = &xcolours[i];
1325     xentry->pixel = i;
1326     MAKE_XCOLOR(xentry, entry);
1327 matty 29 }
1328    
1329 n-ki 279 map = XCreateColormap(display, wnd, visual, AllocAll);
1330     XStoreColors(display, map, xcolours, ncolours);
1331 n-ki 185
1332 n-ki 279 xfree(xcolours);
1333     return (HCOLOURMAP) map;
1334 matty 29 }
1335 matty 7 }
1336    
1337 matty 25 void
1338     ui_destroy_colourmap(HCOLOURMAP map)
1339 matty 7 {
1340 n-ki 279 if (!owncolmap)
1341     xfree(map);
1342     else
1343     XFreeColormap(display, (Colormap) map);
1344 matty 7 }
1345    
1346 matty 25 void
1347     ui_set_colourmap(HCOLOURMAP map)
1348 matty 7 {
1349 n-ki 279 if (!owncolmap)
1350 forsberg 415 colmap = (uint32 *) map;
1351 n-ki 279 else
1352     XSetWindowColormap(display, wnd, (Colormap) map);
1353 matty 7 }
1354    
1355 matty 25 void
1356     ui_set_clip(int x, int y, int cx, int cy)
1357 matty 7 {
1358 matty 9 XRectangle rect;
1359 matty 7
1360 matty 9 rect.x = x;
1361     rect.y = y;
1362     rect.width = cx;
1363     rect.height = cy;
1364 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1365 matty 9 }
1366 matty 7
1367 matty 25 void
1368 matthewc 192 ui_reset_clip(void)
1369 matty 9 {
1370     XRectangle rect;
1371    
1372     rect.x = 0;
1373     rect.y = 0;
1374 matty 10 rect.width = width;
1375     rect.height = height;
1376     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1377 matty 7 }
1378    
1379 matty 25 void
1380 matthewc 192 ui_bell(void)
1381 matty 10 {
1382     XBell(display, 0);
1383     }
1384    
1385 matty 25 void
1386     ui_destblt(uint8 opcode,
1387     /* dest */ int x, int y, int cx, int cy)
1388 matty 9 {
1389 matty 29 SET_FUNCTION(opcode);
1390 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1391 matty 29 RESET_FUNCTION(opcode);
1392 matty 9 }
1393    
1394 jsorg71 373 static uint8 hatch_patterns[] = {
1395 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1396     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1397     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1398     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1399     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1400     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1401 jsorg71 373 };
1402    
1403 matty 25 void
1404     ui_patblt(uint8 opcode,
1405     /* dest */ int x, int y, int cx, int cy,
1406 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1407 matty 9 {
1408     Pixmap fill;
1409 jsorg71 59 uint8 i, ipattern[8];
1410 matty 9
1411 matty 29 SET_FUNCTION(opcode);
1412 matty 9
1413     switch (brush->style)
1414     {
1415 matty 24 case 0: /* Solid */
1416 matty 29 SET_FOREGROUND(fgcolour);
1417 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1418 matty 9 break;
1419    
1420 jsorg71 373 case 2: /* Hatch */
1421 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1422     hatch_patterns + brush->pattern[0] * 8);
1423 jsorg71 373 SET_FOREGROUND(bgcolour);
1424     SET_BACKGROUND(fgcolour);
1425     XSetFillStyle(display, gc, FillOpaqueStippled);
1426     XSetStipple(display, gc, fill);
1427     XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1428     FILL_RECTANGLE(x, y, cx, cy);
1429     XSetFillStyle(display, gc, FillSolid);
1430     XSetTSOrigin(display, gc, 0, 0);
1431     ui_destroy_glyph((HGLYPH) fill);
1432     break;
1433    
1434 matty 24 case 3: /* Pattern */
1435 jsorg71 59 for (i = 0; i != 8; i++)
1436     ipattern[7 - i] = brush->pattern[i];
1437     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1438 matty 9
1439 matty 29 SET_FOREGROUND(bgcolour);
1440     SET_BACKGROUND(fgcolour);
1441     XSetFillStyle(display, gc, FillOpaqueStippled);
1442     XSetStipple(display, gc, fill);
1443 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1444 matty 9
1445 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1446 matty 9
1447 matty 29 XSetFillStyle(display, gc, FillSolid);
1448 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
1449 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1450 matty 9 break;
1451    
1452     default:
1453 matty 30 unimpl("brush %d\n", brush->style);
1454 matty 9 }
1455 matty 29
1456     RESET_FUNCTION(opcode);
1457 matty 9 }
1458    
1459 matty 25 void
1460     ui_screenblt(uint8 opcode,
1461     /* dest */ int x, int y, int cx, int cy,
1462     /* src */ int srcx, int srcy)
1463 matty 9 {
1464 matty 29 SET_FUNCTION(opcode);
1465 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1466 matty 31 if (ownbackstore)
1467 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1468 matty 29 RESET_FUNCTION(opcode);
1469 matty 9 }
1470    
1471 matty 25 void
1472     ui_memblt(uint8 opcode,
1473     /* dest */ int x, int y, int cx, int cy,
1474     /* src */ HBITMAP src, int srcx, int srcy)
1475 matty 9 {
1476 matty 29 SET_FUNCTION(opcode);
1477 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1478 matty 31 if (ownbackstore)
1479 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1480 matty 29 RESET_FUNCTION(opcode);
1481 matty 9 }
1482    
1483 matty 25 void
1484     ui_triblt(uint8 opcode,
1485     /* dest */ int x, int y, int cx, int cy,
1486     /* src */ HBITMAP src, int srcx, int srcy,
1487 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1488 matty 9 {
1489     /* This is potentially difficult to do in general. Until someone
1490 matty 10 comes up with a more efficient way of doing it I am using cases. */
1491 matty 9
1492     switch (opcode)
1493     {
1494 matty 24 case 0x69: /* PDSxxn */
1495 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1496 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1497 matty 16 break;
1498    
1499 matty 24 case 0xb8: /* PSDPxax */
1500 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1501 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1502 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1503 matty 9 break;
1504    
1505 matty 29 case 0xc0: /* PSa */
1506 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1507 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1508 matty 28 break;
1509    
1510 matty 9 default:
1511 matty 30 unimpl("triblt 0x%x\n", opcode);
1512 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1513 matty 9 }
1514     }
1515    
1516 matty 25 void
1517     ui_line(uint8 opcode,
1518     /* dest */ int startx, int starty, int endx, int endy,
1519 astrand 64 /* pen */ PEN * pen)
1520 matty 9 {
1521 matty 29 SET_FUNCTION(opcode);
1522     SET_FOREGROUND(pen->colour);
1523 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1524 matty 31 if (ownbackstore)
1525     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1526 matty 29 RESET_FUNCTION(opcode);
1527 matty 9 }
1528    
1529 matty 25 void
1530     ui_rect(
1531     /* dest */ int x, int y, int cx, int cy,
1532     /* brush */ int colour)
1533 matty 9 {
1534 matty 29 SET_FOREGROUND(colour);
1535 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1536 matty 9 }
1537    
1538 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1539 matty 25 void
1540     ui_draw_glyph(int mixmode,
1541     /* dest */ int x, int y, int cx, int cy,
1542 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1543     int bgcolour, int fgcolour)
1544 matty 9 {
1545 matty 29 SET_FOREGROUND(fgcolour);
1546     SET_BACKGROUND(bgcolour);
1547 matty 9
1548 astrand 66 XSetFillStyle(display, gc,
1549 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1550 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1551 matty 29 XSetTSOrigin(display, gc, x, y);
1552 matty 9
1553 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1554 matty 9
1555 matty 29 XSetFillStyle(display, gc, FillSolid);
1556 matty 9 }
1557    
1558 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1559     {\
1560     glyph = cache_get_font (font, ttext[idx]);\
1561     if (!(flags & TEXT2_IMPLICIT_X))\
1562     {\
1563     xyoffset = ttext[++idx];\
1564     if ((xyoffset & 0x80))\
1565     {\
1566     if (flags & TEXT2_VERTICAL) \
1567 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1568 mmihalik 49 else\
1569 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1570     idx += 2;\
1571 mmihalik 49 }\
1572     else\
1573     {\
1574     if (flags & TEXT2_VERTICAL) \
1575     y += xyoffset;\
1576     else\
1577     x += xyoffset;\
1578     }\
1579     }\
1580     if (glyph != NULL)\
1581     {\
1582 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1583     y + glyph->baseline,\
1584 mmihalik 49 glyph->width, glyph->height,\
1585     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1586     if (flags & TEXT2_IMPLICIT_X)\
1587     x += glyph->width;\
1588     }\
1589     }
1590    
1591 matty 25 void
1592     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1593 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1594     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1595 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1596 matty 9 {
1597 matty 10 FONTGLYPH *glyph;
1598 mmihalik 49 int i, j, xyoffset;
1599     DATABLOB *entry;
1600 matty 9
1601 matty 29 SET_FOREGROUND(bgcolour);
1602 matty 28
1603 matty 9 if (boxcx > 1)
1604 matty 31 {
1605 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1606 matty 31 }
1607 matty 17 else if (mixmode == MIX_OPAQUE)
1608 matty 31 {
1609 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1610 matty 31 }
1611 matty 9
1612     /* Paint text, character by character */
1613 astrand 64 for (i = 0; i < length;)
1614     {
1615     switch (text[i])
1616     {
1617     case 0xff:
1618     if (i + 2 < length)
1619 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1620 astrand 64 else
1621     {
1622     error("this shouldn't be happening\n");
1623 astrand 265 exit(1);
1624 astrand 64 }
1625     /* this will move pointer from start to first character after FF command */
1626     length -= i + 3;
1627     text = &(text[i + 3]);
1628     i = 0;
1629 mmihalik 49 break;
1630 matty 9
1631 astrand 64 case 0xfe:
1632     entry = cache_get_text(text[i + 1]);
1633     if (entry != NULL)
1634     {
1635     if ((((uint8 *) (entry->data))[1] ==
1636 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1637 astrand 64 {
1638     if (flags & TEXT2_VERTICAL)
1639     y += text[i + 2];
1640     else
1641     x += text[i + 2];
1642     }
1643     for (j = 0; j < entry->size; j++)
1644 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1645 matthewc 44 }
1646 jsorg71 286 if (i + 2 < length)
1647     i += 3;
1648     else
1649     i += 2;
1650     length -= i;
1651     /* this will move pointer from start to first character after FE command */
1652     text = &(text[i]);
1653     i = 0;
1654 astrand 64 break;
1655 matty 17
1656 astrand 64 default:
1657     DO_GLYPH(text, i);
1658     i++;
1659     break;
1660 matty 29 }
1661 mmihalik 49 }
1662 jsorg71 278 if (ownbackstore)
1663     {
1664     if (boxcx > 1)
1665     XCopyArea(display, backstore, wnd, gc, boxx,
1666     boxy, boxcx, boxcy, boxx, boxy);
1667     else
1668     XCopyArea(display, backstore, wnd, gc, clipx,
1669     clipy, clipcx, clipcy, clipx, clipy);
1670     }
1671 matty 9 }
1672    
1673 matty 25 void
1674     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1675 matty 9 {
1676 matty 28 Pixmap pix;
1677 matty 9 XImage *image;
1678    
1679 matty 31 if (ownbackstore)
1680     {
1681 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1682 matty 31 }
1683     else
1684     {
1685     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1686     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1687 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1688 matty 31 XFreePixmap(display, pix);
1689     }
1690 matty 28
1691 astrand 64 offset *= bpp / 8;
1692 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1693 matty 28
1694     XDestroyImage(image);
1695 matty 9 }
1696    
1697 matty 25 void
1698     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1699 matty 9 {
1700     XImage *image;
1701 matty 10 uint8 *data;
1702 matty 9
1703 astrand 64 offset *= bpp / 8;
1704     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1705 matty 10 if (data == NULL)
1706     return;
1707 matty 29
1708 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1709 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1710 matty 29
1711 matty 31 if (ownbackstore)
1712     {
1713     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1714     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1715     }
1716     else
1717     {
1718     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1719     }
1720    
1721 matty 9 XFree(image);
1722     }

  ViewVC Help
Powered by ViewVC 1.1.26