/[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 592 - (hide annotations)
Fri Jan 30 14:10:32 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 44749 byte(s)
reworked the asyncio some and completed it. parallel and serial uses it now. disk.c is a likely candidate for the future, but there are some problems with disk.c that we will have to look into first. parallel and serial works better, they do not hang the session, but are still yerky at large chunks... possibly we could split the chunks, but the terminal server does not seem to like partial transfers, i've tried some variations.. :) fns->write() could be split in smaller pieces, but what should the thresholds be.

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

  ViewVC Help
Powered by ViewVC 1.1.26