/[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 606 - (hide annotations)
Sat Feb 14 23:20:24 2004 UTC (20 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 44861 byte(s)
fix select errors due to exploding fdnum n

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

  ViewVC Help
Powered by ViewVC 1.1.26