/[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 603 - (hide annotations)
Sat Feb 7 18:47:06 2004 UTC (20 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 44856 byte(s)
fixes for HP-UX

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 n-ki 592 int n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
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 matthewc 121 /* Process any events already waiting */
1283 astrand 275 if (!xwin_process_events())
1284     /* User quit */
1285     return 0;
1286 astrand 119
1287 matty 33 FD_ZERO(&rfds);
1288 matthewc 474 FD_ZERO(&wfds);
1289 matty 33 FD_SET(rdp_socket, &rfds);
1290 jsorg71 450 FD_SET(g_x_socket, &rfds);
1291 matty 33
1292 matthewc 474 #ifdef WITH_RDPSND
1293     /* FIXME: there should be an API for registering fds */
1294 stargo 504 if (g_dsp_busy)
1295 matty 33 {
1296 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1297 n-ki 592 n = (g_dsp_fd > n) ? g_dsp_fd : n;
1298 astrand 499 }
1299 matthewc 474 #endif
1300 n-ki 592 /* default timeout */
1301     tv.tv_sec = 60;
1302     tv.tv_usec = 0;
1303 matthewc 474
1304 n-ki 592 /* add redirection handles */
1305     rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1306    
1307     n++;
1308    
1309     switch (select(n, &rfds, &wfds, NULL, &tv))
1310 matthewc 474 {
1311 matty 33 case -1:
1312     error("select: %s\n", strerror(errno));
1313    
1314     case 0:
1315 n-ki 594 /* TODO: if tv.tv_sec just times out
1316     * we will segfault.
1317     * FIXME:
1318     */
1319     //s_timeout = True;
1320     //rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1321 matty 33 continue;
1322     }
1323    
1324 n-ki 592 rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1325    
1326 matty 33 if (FD_ISSET(rdp_socket, &rfds))
1327 astrand 275 return 1;
1328 matthewc 474
1329     #ifdef WITH_RDPSND
1330 stargo 504 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1331 matthewc 474 wave_out_play();
1332     #endif
1333 matty 33 }
1334     }
1335    
1336     void
1337 matty 25 ui_move_pointer(int x, int y)
1338 matty 9 {
1339 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1340 matty 9 }
1341    
1342 matty 25 HBITMAP
1343 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1344 matty 6 {
1345     XImage *image;
1346 matty 9 Pixmap bitmap;
1347 matty 28 uint8 *tdata;
1348 stargo 521 int bitmap_pad;
1349 matty 29
1350 stargo 521 if (g_server_bpp == 8)
1351     {
1352     bitmap_pad = 8;
1353     }
1354     else
1355     {
1356     bitmap_pad = g_bpp;
1357    
1358     if (g_bpp == 24)
1359     bitmap_pad = 32;
1360     }
1361    
1362 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1363     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1364     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1365 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1366 matty 6
1367 jsorg71 450 XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1368 matty 9
1369     XFree(image);
1370 jsorg71 450 if (!g_owncolmap)
1371 n-ki 279 xfree(tdata);
1372 matty 24 return (HBITMAP) bitmap;
1373 matty 6 }
1374    
1375 matty 25 void
1376 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1377 matty 6 {
1378 matty 10 XImage *image;
1379 matty 29 uint8 *tdata;
1380 stargo 521 int bitmap_pad;
1381    
1382     if (g_server_bpp == 8)
1383     {
1384     bitmap_pad = 8;
1385     }
1386     else
1387     {
1388     bitmap_pad = g_bpp;
1389    
1390     if (g_bpp == 24)
1391     bitmap_pad = 32;
1392     }
1393    
1394 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1395     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1396 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1397 matty 28
1398 jsorg71 450 if (g_ownbackstore)
1399 matty 31 {
1400 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1401     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1402 matty 31 }
1403     else
1404     {
1405 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1406 matty 31 }
1407 matty 29
1408 matty 24 XFree(image);
1409 jsorg71 450 if (!g_owncolmap)
1410 n-ki 279 xfree(tdata);
1411 matty 6 }
1412    
1413 matty 25 void
1414     ui_destroy_bitmap(HBITMAP bmp)
1415 matty 6 {
1416 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1417 matty 10 }
1418    
1419 matty 25 HGLYPH
1420 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1421 matty 10 {
1422 matty 9 XImage *image;
1423     Pixmap bitmap;
1424     int scanline;
1425     GC gc;
1426 matty 6
1427 matty 9 scanline = (width + 7) / 8;
1428 matty 6
1429 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1430     gc = XCreateGC(g_display, bitmap, 0, NULL);
1431 matty 9
1432 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1433 astrand 73 width, height, 8, scanline);
1434 matty 23 image->byte_order = MSBFirst;
1435     image->bitmap_bit_order = MSBFirst;
1436     XInitImage(image);
1437    
1438 jsorg71 450 XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1439 matty 29
1440 matty 9 XFree(image);
1441 jsorg71 450 XFreeGC(g_display, gc);
1442 astrand 64 return (HGLYPH) bitmap;
1443 matty 6 }
1444 matty 7
1445 matty 25 void
1446     ui_destroy_glyph(HGLYPH glyph)
1447 matty 7 {
1448 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1449 matty 9 }
1450    
1451 matty 29 HCURSOR
1452 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1453     uint8 * andmask, uint8 * xormask)
1454 matty 9 {
1455 matty 29 HGLYPH maskglyph, cursorglyph;
1456     XColor bg, fg;
1457     Cursor xcursor;
1458     uint8 *cursor, *pcursor;
1459     uint8 *mask, *pmask;
1460     uint8 nextbit;
1461     int scanline, offset;
1462     int i, j;
1463    
1464     scanline = (width + 7) / 8;
1465     offset = scanline * height;
1466    
1467 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1468 matty 29 memset(cursor, 0, offset);
1469    
1470 forsberg 415 mask = (uint8 *) xmalloc(offset);
1471 matty 29 memset(mask, 0, offset);
1472    
1473     /* approximate AND and XOR masks with a monochrome X pointer */
1474     for (i = 0; i < height; i++)
1475 matty 7 {
1476 matty 29 offset -= scanline;
1477     pcursor = &cursor[offset];
1478     pmask = &mask[offset];
1479    
1480     for (j = 0; j < scanline; j++)
1481 matty 28 {
1482 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1483     {
1484     if (xormask[0] || xormask[1] || xormask[2])
1485     {
1486     *pcursor |= (~(*andmask) & nextbit);
1487     *pmask |= nextbit;
1488     }
1489     else
1490     {
1491     *pcursor |= ((*andmask) & nextbit);
1492     *pmask |= (~(*andmask) & nextbit);
1493     }
1494    
1495     xormask += 3;
1496     }
1497    
1498     andmask++;
1499     pcursor++;
1500     pmask++;
1501 matty 28 }
1502 matty 7 }
1503 matty 29
1504     fg.red = fg.blue = fg.green = 0xffff;
1505     bg.red = bg.blue = bg.green = 0x0000;
1506     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1507    
1508     cursorglyph = ui_create_glyph(width, height, cursor);
1509     maskglyph = ui_create_glyph(width, height, mask);
1510    
1511 astrand 66 xcursor =
1512 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1513 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1514 astrand 64
1515 matty 29 ui_destroy_glyph(maskglyph);
1516     ui_destroy_glyph(cursorglyph);
1517     xfree(mask);
1518     xfree(cursor);
1519 astrand 64 return (HCURSOR) xcursor;
1520 matty 29 }
1521    
1522     void
1523     ui_set_cursor(HCURSOR cursor)
1524     {
1525 jsorg71 450 g_current_cursor = (Cursor) cursor;
1526     XDefineCursor(g_display, g_wnd, g_current_cursor);
1527 matty 29 }
1528    
1529     void
1530     ui_destroy_cursor(HCURSOR cursor)
1531     {
1532 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1533 matty 29 }
1534    
1535 astrand 508 void
1536     ui_set_null_cursor(void)
1537     {
1538     ui_set_cursor(g_null_cursor);
1539     }
1540    
1541 matty 29 #define MAKE_XCOLOR(xc,c) \
1542     (xc)->red = ((c)->red << 8) | (c)->red; \
1543     (xc)->green = ((c)->green << 8) | (c)->green; \
1544     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1545     (xc)->flags = DoRed | DoGreen | DoBlue;
1546    
1547 n-ki 279
1548 matty 29 HCOLOURMAP
1549 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1550 matty 29 {
1551     COLOURENTRY *entry;
1552     int i, ncolours = colours->ncolours;
1553 jsorg71 450 if (!g_owncolmap)
1554 matty 28 {
1555 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1556 n-ki 279 XColor xentry;
1557     XColor xc_cache[256];
1558     uint32 colour;
1559     int colLookup = 256;
1560     for (i = 0; i < ncolours; i++)
1561 matty 28 {
1562 n-ki 279 entry = &colours->colours[i];
1563     MAKE_XCOLOR(&xentry, entry);
1564 matty 7
1565 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1566 astrand 196 {
1567 n-ki 279 /* Allocation failed, find closest match. */
1568     int j = 256;
1569     int nMinDist = 3 * 256 * 256;
1570     long nDist = nMinDist;
1571 matty 28
1572 n-ki 279 /* only get the colors once */
1573     while (colLookup--)
1574 astrand 196 {
1575 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1576     xc_cache[colLookup].red = xc_cache[colLookup].green =
1577     xc_cache[colLookup].blue = 0;
1578     xc_cache[colLookup].flags = 0;
1579 jsorg71 450 XQueryColor(g_display,
1580     DefaultColormap(g_display,
1581     DefaultScreen(g_display)),
1582 n-ki 279 &xc_cache[colLookup]);
1583 n-ki 185 }
1584 n-ki 279 colLookup = 0;
1585    
1586     /* approximate the pixel */
1587     while (j--)
1588 astrand 196 {
1589 n-ki 279 if (xc_cache[j].flags)
1590     {
1591     nDist = ((long) (xc_cache[j].red >> 8) -
1592     (long) (xentry.red >> 8)) *
1593     ((long) (xc_cache[j].red >> 8) -
1594     (long) (xentry.red >> 8)) +
1595     ((long) (xc_cache[j].green >> 8) -
1596     (long) (xentry.green >> 8)) *
1597     ((long) (xc_cache[j].green >> 8) -
1598     (long) (xentry.green >> 8)) +
1599     ((long) (xc_cache[j].blue >> 8) -
1600     (long) (xentry.blue >> 8)) *
1601     ((long) (xc_cache[j].blue >> 8) -
1602     (long) (xentry.blue >> 8));
1603     }
1604     if (nDist < nMinDist)
1605     {
1606     nMinDist = nDist;
1607     xentry.pixel = j;
1608     }
1609 n-ki 185 }
1610     }
1611 n-ki 279 colour = xentry.pixel;
1612    
1613     /* update our cache */
1614     if (xentry.pixel < 256)
1615     {
1616     xc_cache[xentry.pixel].red = xentry.red;
1617     xc_cache[xentry.pixel].green = xentry.green;
1618     xc_cache[xentry.pixel].blue = xentry.blue;
1619    
1620     }
1621    
1622 matthewc 527 map[i] = colour;
1623 n-ki 185 }
1624 n-ki 279 return map;
1625     }
1626     else
1627     {
1628     XColor *xcolours, *xentry;
1629     Colormap map;
1630 matty 29
1631 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1632 n-ki 279 for (i = 0; i < ncolours; i++)
1633 astrand 196 {
1634 n-ki 279 entry = &colours->colours[i];
1635     xentry = &xcolours[i];
1636     xentry->pixel = i;
1637     MAKE_XCOLOR(xentry, entry);
1638 matty 29 }
1639    
1640 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1641     XStoreColors(g_display, map, xcolours, ncolours);
1642 n-ki 185
1643 n-ki 279 xfree(xcolours);
1644     return (HCOLOURMAP) map;
1645 matty 29 }
1646 matty 7 }
1647    
1648 matty 25 void
1649     ui_destroy_colourmap(HCOLOURMAP map)
1650 matty 7 {
1651 jsorg71 450 if (!g_owncolmap)
1652 n-ki 279 xfree(map);
1653     else
1654 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1655 matty 7 }
1656    
1657 matty 25 void
1658     ui_set_colourmap(HCOLOURMAP map)
1659 matty 7 {
1660 jsorg71 450 if (!g_owncolmap)
1661 astrand 448 {
1662 jsorg71 450 if (g_colmap)
1663     xfree(g_colmap);
1664 astrand 448
1665 jsorg71 450 g_colmap = (uint32 *) map;
1666 astrand 448 }
1667 n-ki 279 else
1668 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1669 matty 7 }
1670    
1671 matty 25 void
1672     ui_set_clip(int x, int y, int cx, int cy)
1673 matty 7 {
1674 matty 9 XRectangle rect;
1675 matty 7
1676 matty 9 rect.x = x;
1677     rect.y = y;
1678     rect.width = cx;
1679     rect.height = cy;
1680 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1681 matty 9 }
1682 matty 7
1683 matty 25 void
1684 matthewc 192 ui_reset_clip(void)
1685 matty 9 {
1686     XRectangle rect;
1687    
1688     rect.x = 0;
1689     rect.y = 0;
1690 jsorg71 447 rect.width = g_width;
1691     rect.height = g_height;
1692 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1693 matty 7 }
1694    
1695 matty 25 void
1696 matthewc 192 ui_bell(void)
1697 matty 10 {
1698 jsorg71 450 XBell(g_display, 0);
1699 matty 10 }
1700    
1701 matty 25 void
1702     ui_destblt(uint8 opcode,
1703     /* dest */ int x, int y, int cx, int cy)
1704 matty 9 {
1705 matty 29 SET_FUNCTION(opcode);
1706 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1707 matty 29 RESET_FUNCTION(opcode);
1708 matty 9 }
1709    
1710 jsorg71 373 static uint8 hatch_patterns[] = {
1711 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1712     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1713     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1714     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1715     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1716     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1717 jsorg71 373 };
1718    
1719 matty 25 void
1720     ui_patblt(uint8 opcode,
1721     /* dest */ int x, int y, int cx, int cy,
1722 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1723 matty 9 {
1724     Pixmap fill;
1725 jsorg71 59 uint8 i, ipattern[8];
1726 matty 9
1727 matty 29 SET_FUNCTION(opcode);
1728 matty 9
1729     switch (brush->style)
1730     {
1731 matty 24 case 0: /* Solid */
1732 matty 29 SET_FOREGROUND(fgcolour);
1733 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1734 matty 9 break;
1735    
1736 jsorg71 373 case 2: /* Hatch */
1737 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1738     hatch_patterns + brush->pattern[0] * 8);
1739 astrand 487 SET_FOREGROUND(fgcolour);
1740     SET_BACKGROUND(bgcolour);
1741 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1742     XSetStipple(g_display, g_gc, fill);
1743     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1744 jsorg71 373 FILL_RECTANGLE(x, y, cx, cy);
1745 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1746     XSetTSOrigin(g_display, g_gc, 0, 0);
1747 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1748     break;
1749    
1750 matty 24 case 3: /* Pattern */
1751 jsorg71 59 for (i = 0; i != 8; i++)
1752     ipattern[7 - i] = brush->pattern[i];
1753     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1754 matty 9
1755 matty 29 SET_FOREGROUND(bgcolour);
1756     SET_BACKGROUND(fgcolour);
1757 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1758     XSetStipple(g_display, g_gc, fill);
1759     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1760 matty 9
1761 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1762 matty 9
1763 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1764     XSetTSOrigin(g_display, g_gc, 0, 0);
1765 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1766 matty 9 break;
1767    
1768     default:
1769 matty 30 unimpl("brush %d\n", brush->style);
1770 matty 9 }
1771 matty 29
1772     RESET_FUNCTION(opcode);
1773 matty 9 }
1774    
1775 matty 25 void
1776     ui_screenblt(uint8 opcode,
1777     /* dest */ int x, int y, int cx, int cy,
1778     /* src */ int srcx, int srcy)
1779 matty 9 {
1780 matty 29 SET_FUNCTION(opcode);
1781 jsorg71 450 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1782     if (g_ownbackstore)
1783     XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1784 matty 29 RESET_FUNCTION(opcode);
1785 matty 9 }
1786    
1787 matty 25 void
1788     ui_memblt(uint8 opcode,
1789     /* dest */ int x, int y, int cx, int cy,
1790     /* src */ HBITMAP src, int srcx, int srcy)
1791 matty 9 {
1792 matty 29 SET_FUNCTION(opcode);
1793 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1794     if (g_ownbackstore)
1795     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1796 matty 29 RESET_FUNCTION(opcode);
1797 matty 9 }
1798    
1799 matty 25 void
1800     ui_triblt(uint8 opcode,
1801     /* dest */ int x, int y, int cx, int cy,
1802     /* src */ HBITMAP src, int srcx, int srcy,
1803 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1804 matty 9 {
1805     /* This is potentially difficult to do in general. Until someone
1806 matty 10 comes up with a more efficient way of doing it I am using cases. */
1807 matty 9
1808     switch (opcode)
1809     {
1810 matty 24 case 0x69: /* PDSxxn */
1811 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1812 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1813 matty 16 break;
1814    
1815 matty 24 case 0xb8: /* PSDPxax */
1816 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1817 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1818 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1819 matty 9 break;
1820    
1821 matty 29 case 0xc0: /* PSa */
1822 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1823 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1824 matty 28 break;
1825    
1826 matty 9 default:
1827 matty 30 unimpl("triblt 0x%x\n", opcode);
1828 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1829 matty 9 }
1830     }
1831    
1832 matty 25 void
1833     ui_line(uint8 opcode,
1834     /* dest */ int startx, int starty, int endx, int endy,
1835 astrand 64 /* pen */ PEN * pen)
1836 matty 9 {
1837 matty 29 SET_FUNCTION(opcode);
1838     SET_FOREGROUND(pen->colour);
1839 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1840     if (g_ownbackstore)
1841     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1842 matty 29 RESET_FUNCTION(opcode);
1843 matty 9 }
1844    
1845 matty 25 void
1846     ui_rect(
1847     /* dest */ int x, int y, int cx, int cy,
1848     /* brush */ int colour)
1849 matty 9 {
1850 matty 29 SET_FOREGROUND(colour);
1851 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1852 matty 9 }
1853    
1854 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1855 matty 25 void
1856     ui_draw_glyph(int mixmode,
1857     /* dest */ int x, int y, int cx, int cy,
1858 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1859     int bgcolour, int fgcolour)
1860 matty 9 {
1861 matty 29 SET_FOREGROUND(fgcolour);
1862     SET_BACKGROUND(bgcolour);
1863 matty 9
1864 jsorg71 450 XSetFillStyle(g_display, g_gc,
1865 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1866 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
1867     XSetTSOrigin(g_display, g_gc, x, y);
1868 matty 9
1869 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1870 matty 9
1871 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1872 matty 9 }
1873    
1874 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1875     {\
1876     glyph = cache_get_font (font, ttext[idx]);\
1877     if (!(flags & TEXT2_IMPLICIT_X))\
1878 jsorg71 564 {\
1879     xyoffset = ttext[++idx];\
1880     if ((xyoffset & 0x80))\
1881 mmihalik 49 {\
1882 jsorg71 564 if (flags & TEXT2_VERTICAL)\
1883     y += ttext[idx+1] | (ttext[idx+2] << 8);\
1884 mmihalik 49 else\
1885 jsorg71 564 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1886     idx += 2;\
1887 mmihalik 49 }\
1888 jsorg71 564 else\
1889 mmihalik 49 {\
1890 jsorg71 564 if (flags & TEXT2_VERTICAL)\
1891     y += xyoffset;\
1892     else\
1893     x += xyoffset;\
1894 mmihalik 49 }\
1895 jsorg71 564 }\
1896     if (glyph != NULL)\
1897     {\
1898     x1 = x + glyph->offset;\
1899     y1 = y + glyph->baseline;\
1900     XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
1901     XSetTSOrigin(g_display, g_gc, x1, y1);\
1902     FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
1903     if (flags & TEXT2_IMPLICIT_X)\
1904     x += glyph->width;\
1905     }\
1906 mmihalik 49 }
1907    
1908 matty 25 void
1909     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1910 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1911     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1912 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1913 matty 9 {
1914 matty 10 FONTGLYPH *glyph;
1915 jsorg71 564 int i, j, xyoffset, x1, y1;
1916 mmihalik 49 DATABLOB *entry;
1917 matty 9
1918 matty 29 SET_FOREGROUND(bgcolour);
1919 matty 28
1920 matty 9 if (boxcx > 1)
1921 matty 31 {
1922 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1923 matty 31 }
1924 matty 17 else if (mixmode == MIX_OPAQUE)
1925 matty 31 {
1926 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1927 matty 31 }
1928 matty 9
1929 jsorg71 564 SET_FOREGROUND(fgcolour);
1930     SET_BACKGROUND(bgcolour);
1931     XSetFillStyle(g_display, g_gc, FillStippled);
1932    
1933 matty 9 /* Paint text, character by character */
1934 astrand 64 for (i = 0; i < length;)
1935     {
1936     switch (text[i])
1937     {
1938     case 0xff:
1939     if (i + 2 < length)
1940 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1941 astrand 64 else
1942     {
1943     error("this shouldn't be happening\n");
1944 astrand 265 exit(1);
1945 astrand 64 }
1946     /* this will move pointer from start to first character after FF command */
1947     length -= i + 3;
1948     text = &(text[i + 3]);
1949     i = 0;
1950 mmihalik 49 break;
1951 matty 9
1952 astrand 64 case 0xfe:
1953     entry = cache_get_text(text[i + 1]);
1954     if (entry != NULL)
1955     {
1956     if ((((uint8 *) (entry->data))[1] ==
1957 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1958 astrand 64 {
1959     if (flags & TEXT2_VERTICAL)
1960     y += text[i + 2];
1961     else
1962     x += text[i + 2];
1963     }
1964     for (j = 0; j < entry->size; j++)
1965 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1966 matthewc 44 }
1967 jsorg71 286 if (i + 2 < length)
1968     i += 3;
1969     else
1970     i += 2;
1971     length -= i;
1972     /* this will move pointer from start to first character after FE command */
1973     text = &(text[i]);
1974     i = 0;
1975 astrand 64 break;
1976 matty 17
1977 astrand 64 default:
1978     DO_GLYPH(text, i);
1979     i++;
1980     break;
1981 matty 29 }
1982 mmihalik 49 }
1983 jsorg71 564
1984     XSetFillStyle(g_display, g_gc, FillSolid);
1985    
1986 jsorg71 450 if (g_ownbackstore)
1987 jsorg71 278 {
1988     if (boxcx > 1)
1989 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1990 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
1991     else
1992 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1993 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
1994     }
1995 matty 9 }
1996    
1997 matty 25 void
1998     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1999 matty 9 {
2000 matty 28 Pixmap pix;
2001 matty 9 XImage *image;
2002    
2003 jsorg71 450 if (g_ownbackstore)
2004 matty 31 {
2005 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2006 matty 31 }
2007     else
2008     {
2009 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2010     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2011     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2012     XFreePixmap(g_display, pix);
2013 matty 31 }
2014 matty 28
2015 jsorg71 450 offset *= g_bpp / 8;
2016     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2017 matty 28
2018     XDestroyImage(image);
2019 matty 9 }
2020    
2021 matty 25 void
2022     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2023 matty 9 {
2024     XImage *image;
2025 matty 10 uint8 *data;
2026 matty 9
2027 jsorg71 450 offset *= g_bpp / 8;
2028     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2029 matty 10 if (data == NULL)
2030     return;
2031 matty 29
2032 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2033     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2034 matty 29
2035 jsorg71 450 if (g_ownbackstore)
2036 matty 31 {
2037 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2038     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2039 matty 31 }
2040     else
2041     {
2042 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2043 matty 31 }
2044    
2045 matty 9 XFree(image);
2046     }

  ViewVC Help
Powered by ViewVC 1.1.26