/[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 565 - (hide annotations)
Mon Jan 19 21:58:58 2004 UTC (20 years, 4 months ago) by stargo
File MIME type: text/plain
File size: 44403 byte(s)
Try to use a TrueColor visual, even if the default-visual is
PseudoColor. This enables high-colour modes on displays with
a PseudoColor default visual and eliminates colourmap-flashing
at 8 bpp there.

1 forsberg 415 /* -*- c-basic-offset: 8 -*-
2 matty 6 rdesktop: A Remote Desktop Protocol client.
3 matthewc 38 User interface services - X Window System
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
5 n-ki 52
6 matty 6 This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 n-ki 52
11 matty 6 This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15 n-ki 52
16 matty 6 You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21 matty 10 #include <X11/Xlib.h>
22 matty 28 #include <X11/Xutil.h>
23 matthewc 537 #include <unistd.h>
24 matty 10 #include <time.h>
25 matty 33 #include <errno.h>
26 matty 10 #include "rdesktop.h"
27 forsberg 415 #include "xproto.h"
28 matty 6
29 jsorg71 447 extern int g_width;
30     extern int g_height;
31     extern BOOL g_sendmotion;
32     extern BOOL g_fullscreen;
33 jsorg71 450 extern BOOL g_grab_keyboard;
34     extern BOOL g_hide_decorations;
35     extern char g_title[];
36 jsorg71 438 extern int g_server_bpp;
37 jsorg71 450 extern int g_win_button_size;
38 matty 10
39 jsorg71 450 Display *g_display;
40     Time g_last_gesturetime;
41     static int g_x_socket;
42     static Screen *g_screen;
43     Window g_wnd;
44 matthewc 481 BOOL g_enable_compose = False;
45 jsorg71 450 static GC g_gc;
46     static Visual *g_visual;
47     static int g_depth;
48     static int g_bpp;
49     static XIM g_IM;
50     static XIC g_IC;
51     static XModifierKeymap *g_mod_map;
52     static Cursor g_current_cursor;
53 astrand 508 static HCURSOR g_null_cursor;
54 jsorg71 450 static Atom g_protocol_atom, g_kill_atom;
55 matthewc 481 static BOOL g_focused;
56     static BOOL g_mouse_in_wnd;
57 matty 29
58 matty 33 /* endianness */
59 jsorg71 450 static BOOL g_host_be;
60     static BOOL g_xserver_be;
61 matthewc 527 static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
62     static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
63 matty 33
64     /* software backing store */
65 jsorg71 450 static BOOL g_ownbackstore;
66     static Pixmap g_backstore;
67 stargo 565 static BOOL g_backstore_initialized = False;
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     if ((g_server_bpp == 8) && ((! TrueColorVisual) || (g_depth <= 8)))
736     {
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 stargo 565 g_xcolmap = XCreateColormap(g_display,RootWindowOfScreen(g_screen),g_visual,AllocNone);
788 jsorg71 450 if (g_depth <= 8)
789 matthewc 297 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
790 n-ki 279 }
791    
792 jsorg71 450 if (DoesBackingStore(g_screen) != Always)
793     g_ownbackstore = True;
794 matthewc 121
795     test = 1;
796 jsorg71 450 g_host_be = !(BOOL) (*(uint8 *) (&test));
797     g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
798 matthewc 121
799 astrand 500 /*
800     * Determine desktop size
801     */
802 astrand 547 if (g_fullscreen)
803 astrand 263 {
804 astrand 547 g_width = WidthOfScreen(g_screen);
805     g_height = HeightOfScreen(g_screen);
806     }
807     else if (g_width < 0)
808     {
809 astrand 500 /* Percent of screen */
810     g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
811     g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
812     }
813     else if (g_width == 0)
814     {
815 astrand 263 /* Fetch geometry from _NET_WORKAREA */
816 matthewc 300 uint32 x, y, cx, cy;
817 astrand 263
818 matthewc 300 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
819 astrand 263 {
820 jsorg71 447 g_width = cx;
821     g_height = cy;
822 matthewc 300 }
823     else
824     {
825 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
826 jsorg71 447 g_width = 800;
827     g_height = 600;
828 astrand 263 }
829     }
830 matthewc 121
831 matthewc 160 /* make sure width is a multiple of 4 */
832 jsorg71 447 g_width = (g_width + 3) & ~3;
833 matthewc 160
834 jsorg71 450 g_mod_map = XGetModifierMapping(g_display);
835 matthewc 203
836 astrand 498 xkeymap_init();
837    
838 jsorg71 447 if (g_enable_compose)
839 jsorg71 450 g_IM = XOpenIM(g_display, NULL, NULL, NULL);
840 matthewc 188
841 matthewc 432 xclip_init();
842 jsorg71 316
843 matthewc 519 DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
844 jsorg71 316
845 jsorg71 81 return True;
846     }
847 astrand 66
848 matthewc 188 void
849 matthewc 192 ui_deinit(void)
850 matthewc 188 {
851 jsorg71 450 if (g_IM != NULL)
852     XCloseIM(g_IM);
853 matthewc 188
854 jsorg71 450 XFreeModifiermap(g_mod_map);
855 matthewc 203
856 jsorg71 450 if (g_ownbackstore)
857     XFreePixmap(g_display, g_backstore);
858 matthewc 188
859 jsorg71 450 XFreeGC(g_display, g_gc);
860     XCloseDisplay(g_display);
861     g_display = NULL;
862 matthewc 188 }
863    
864 matthewc 121 BOOL
865 matthewc 192 ui_create_window(void)
866 matty 6 {
867 matthewc 536 uint8 null_pointer_mask[1] = { 0x80 };
868     uint8 null_pointer_data[4] = { 0x00, 0x00, 0x00, 0x00 };
869 matthewc 121 XSetWindowAttributes attribs;
870 matty 28 XClassHint *classhints;
871     XSizeHints *sizehints;
872 matthewc 188 int wndwidth, wndheight;
873 matthewc 432 long input_mask, ic_input_mask;
874 jsorg71 100 XEvent xevent;
875    
876 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
877     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
878 matthewc 188
879 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
880 stargo 565 attribs.border_pixel = WhitePixelOfScreen(g_screen);
881 jsorg71 450 attribs.backing_store = g_ownbackstore ? NotUseful : Always;
882 jsorg71 447 attribs.override_redirect = g_fullscreen;
883 stargo 565 attribs.colormap = g_xcolmap;
884 matthewc 188
885 jsorg71 450 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
886 stargo 565 0, g_depth, InputOutput, g_visual,
887     CWBackPixel | CWBackingStore | CWOverrideRedirect |
888     CWColormap | CWBorderPixel, &attribs);
889 jsorg71 100
890 stargo 565 g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
891    
892     if ((g_ownbackstore) && (! g_backstore_initialized))
893     {
894     g_backstore =
895     XCreatePixmap(g_display, g_wnd, g_width, g_height,
896     g_depth);
897    
898     /* clear to prevent rubbish being exposed at startup */
899     XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
900     XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
901     g_backstore_initialized = True;
902     }
903    
904 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
905 jsorg71 100
906 jsorg71 450 if (g_hide_decorations)
907 astrand 262 mwm_hide_decorations();
908    
909 jsorg71 100 classhints = XAllocClassHint();
910     if (classhints != NULL)
911     {
912     classhints->res_name = classhints->res_class = "rdesktop";
913 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
914 jsorg71 100 XFree(classhints);
915     }
916    
917     sizehints = XAllocSizeHints();
918     if (sizehints)
919     {
920     sizehints->flags = PMinSize | PMaxSize;
921 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
922     sizehints->min_height = sizehints->max_height = g_height;
923 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
924 jsorg71 100 XFree(sizehints);
925     }
926    
927 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
928 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
929 matthewc 121
930 jsorg71 447 if (g_sendmotion)
931 matthewc 121 input_mask |= PointerMotionMask;
932 jsorg71 450 if (g_ownbackstore)
933 matthewc 121 input_mask |= ExposureMask;
934 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
935 matthewc 250 input_mask |= EnterWindowMask;
936 jsorg71 450 if (g_grab_keyboard)
937 jsorg71 257 input_mask |= LeaveWindowMask;
938 jsorg71 100
939 jsorg71 450 if (g_IM != NULL)
940 matthewc 188 {
941 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
942 astrand 456 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
943 matthewc 188
944 jsorg71 450 if ((g_IC != NULL)
945     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
946 matthewc 188 input_mask |= ic_input_mask;
947     }
948    
949 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
950     XMapWindow(g_display, g_wnd);
951 jsorg71 100
952 matthewc 208 /* wait for VisibilityNotify */
953 astrand 196 do
954     {
955 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
956 astrand 196 }
957 matthewc 208 while (xevent.type != VisibilityNotify);
958 matthewc 123
959 jsorg71 447 g_focused = False;
960     g_mouse_in_wnd = False;
961 jsorg71 257
962 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
963 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
964     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
965     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
966 astrand 275
967 astrand 508 /* create invisible 1x1 cursor to be used as null cursor */
968 matthewc 536 g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
969 astrand 508
970 matty 10 return True;
971 matty 6 }
972    
973 matty 25 void
974 matthewc 192 ui_destroy_window(void)
975 matty 6 {
976 jsorg71 450 if (g_IC != NULL)
977     XDestroyIC(g_IC);
978 matty 31
979 jsorg71 450 XDestroyWindow(g_display, g_wnd);
980 matty 6 }
981    
982 jsorg71 100 void
983 matthewc 192 xwin_toggle_fullscreen(void)
984 jsorg71 100 {
985 matthewc 188 Pixmap contents = 0;
986 matthewc 123
987 jsorg71 450 if (!g_ownbackstore)
988 matthewc 188 {
989     /* need to save contents of window */
990 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
991     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
992 matthewc 188 }
993    
994     ui_destroy_window();
995 jsorg71 447 g_fullscreen = !g_fullscreen;
996 matthewc 188 ui_create_window();
997 matthewc 123
998 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
999 matthewc 188
1000 jsorg71 450 if (!g_ownbackstore)
1001 matthewc 188 {
1002 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1003     XFreePixmap(g_display, contents);
1004 matthewc 188 }
1005 jsorg71 100 }
1006    
1007 jsorg71 447 /* Process all events in Xlib queue
1008 astrand 275 Returns 0 after user quit, 1 otherwise */
1009     static int
1010 matthewc 192 xwin_process_events(void)
1011 matty 9 {
1012 n-ki 54 XEvent xevent;
1013 matthewc 38 KeySym keysym;
1014 matthewc 50 uint16 button, flags;
1015 matty 10 uint32 ev_time;
1016 astrand 66 key_translation tr;
1017     char str[256];
1018     Status status;
1019 matty 9
1020 jsorg71 450 while (XPending(g_display) > 0)
1021 matty 9 {
1022 jsorg71 450 XNextEvent(g_display, &xevent);
1023 matthewc 123
1024 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1025 astrand 66 {
1026 astrand 84 DEBUG_KBD(("Filtering event\n"));
1027 astrand 66 continue;
1028     }
1029    
1030 matthewc 50 flags = 0;
1031 matty 10
1032 n-ki 54 switch (xevent.type)
1033 matty 9 {
1034 astrand 275 case ClientMessage:
1035     /* the window manager told us to quit */
1036 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
1037     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1038 astrand 275 /* Quit */
1039     return 0;
1040     break;
1041    
1042 matty 9 case KeyPress:
1043 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1044     if (g_IC != NULL)
1045 astrand 66 /* Multi_key compatible version */
1046     {
1047 jsorg71 450 XmbLookupString(g_IC,
1048 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
1049     &status);
1050 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1051 astrand 66 {
1052 astrand 82 error("XmbLookupString failed with status 0x%x\n",
1053     status);
1054 astrand 66 break;
1055     }
1056     }
1057     else
1058     {
1059     /* Plain old XLookupString */
1060 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1061 astrand 66 XLookupString((XKeyEvent *) & xevent,
1062 astrand 82 str, sizeof(str), &keysym, NULL);
1063 astrand 66 }
1064    
1065 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1066     get_ksname(keysym)));
1067 astrand 66
1068 matthewc 203 ev_time = time(NULL);
1069     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1070 astrand 118 break;
1071    
1072 astrand 66 tr = xkeymap_translate_key(keysym,
1073 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1074 astrand 69
1075 astrand 66 if (tr.scancode == 0)
1076 n-ki 52 break;
1077    
1078 astrand 470 save_remote_modifiers(tr.scancode);
1079 astrand 115 ensure_remote_modifiers(ev_time, tr);
1080 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1081 astrand 470 restore_remote_modifiers(ev_time, tr.scancode);
1082 astrand 115
1083 astrand 66 break;
1084 matthewc 203
1085 astrand 66 case KeyRelease:
1086 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1087 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
1088     sizeof(str), &keysym, NULL);
1089 n-ki 52
1090 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1091 matthewc 203 get_ksname(keysym)));
1092 n-ki 52
1093 matthewc 203 ev_time = time(NULL);
1094     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1095 astrand 118 break;
1096    
1097 astrand 66 tr = xkeymap_translate_key(keysym,
1098 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1099 astrand 66
1100     if (tr.scancode == 0)
1101     break;
1102    
1103 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1104 matty 9 break;
1105    
1106     case ButtonPress:
1107 matthewc 50 flags = MOUSE_FLAG_DOWN;
1108     /* fall through */
1109 matty 9
1110     case ButtonRelease:
1111 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
1112 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
1113 matty 9 if (button == 0)
1114     break;
1115    
1116 astrand 328 /* If win_button_size is nonzero, enable single app mode */
1117 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
1118 astrand 328 {
1119 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
1120 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
1121     g_moving_wnd = False;
1122 astrand 332
1123 astrand 342 /* Check from right to left: */
1124    
1125 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
1126 astrand 328 {
1127 astrand 331 /* The close button, continue */
1128 astrand 328 ;
1129     }
1130 astrand 456 else if (xevent.xbutton.x >=
1131     g_width - g_win_button_size * 2)
1132 astrand 328 {
1133     /* The maximize/restore button. Do not send to
1134     server. It might be a good idea to change the
1135 jsorg71 447 cursor or give some other visible indication
1136 astrand 328 that rdesktop inhibited this click */
1137     break;
1138     }
1139 astrand 456 else if (xevent.xbutton.x >=
1140     g_width - g_win_button_size * 3)
1141 astrand 328 {
1142     /* The minimize button. Iconify window. */
1143 jsorg71 450 XIconifyWindow(g_display, g_wnd,
1144     DefaultScreen(g_display));
1145 astrand 328 break;
1146     }
1147 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
1148 astrand 342 {
1149     /* The system menu. Ignore. */
1150     break;
1151     }
1152 astrand 332 else
1153     {
1154 astrand 342 /* The title bar. */
1155 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
1156 jsorg71 450 && g_hide_decorations)
1157 astrand 342 {
1158 jsorg71 450 g_moving_wnd = True;
1159     g_move_x_offset = xevent.xbutton.x;
1160     g_move_y_offset = xevent.xbutton.y;
1161 astrand 342 }
1162 astrand 332 break;
1163 astrand 342
1164 astrand 332 }
1165 astrand 328 }
1166    
1167 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1168 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1169 matty 10 break;
1170    
1171     case MotionNotify:
1172 jsorg71 450 if (g_moving_wnd)
1173 astrand 342 {
1174 jsorg71 450 XMoveWindow(g_display, g_wnd,
1175     xevent.xmotion.x_root - g_move_x_offset,
1176     xevent.xmotion.y_root - g_move_y_offset);
1177 astrand 342 break;
1178     }
1179    
1180 jsorg71 447 if (g_fullscreen && !g_focused)
1181 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1182 jsorg71 288 CurrentTime);
1183 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1184 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1185 matty 28 break;
1186    
1187 matthewc 194 case FocusIn:
1188 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
1189     break;
1190 jsorg71 447 g_focused = True;
1191 astrand 543 reset_modifier_keys();
1192 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
1193     XGrabKeyboard(g_display, g_wnd, True,
1194 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
1195 matty 28 break;
1196    
1197 matthewc 194 case FocusOut:
1198 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
1199     break;
1200 jsorg71 447 g_focused = False;
1201 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1202 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1203 matty 28 break;
1204 matty 31
1205 matthewc 250 case EnterNotify:
1206     /* we only register for this event when in fullscreen mode */
1207 jsorg71 257 /* or grab_keyboard */
1208 jsorg71 447 g_mouse_in_wnd = True;
1209     if (g_fullscreen)
1210 jsorg71 257 {
1211 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1212 astrand 261 CurrentTime);
1213 jsorg71 257 break;
1214     }
1215 jsorg71 447 if (g_focused)
1216 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
1217 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
1218 matthewc 250 break;
1219    
1220 matthewc 253 case LeaveNotify:
1221 jsorg71 257 /* we only register for this event when grab_keyboard */
1222 jsorg71 447 g_mouse_in_wnd = False;
1223 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1224 matthewc 253 break;
1225    
1226 matty 31 case Expose:
1227 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1228 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
1229 astrand 64 xevent.xexpose.width,
1230     xevent.xexpose.height,
1231 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
1232 matty 31 break;
1233 astrand 119
1234     case MappingNotify:
1235     /* Refresh keyboard mapping if it has changed. This is important for
1236     Xvnc, since it allocates keycodes dynamically */
1237     if (xevent.xmapping.request == MappingKeyboard
1238     || xevent.xmapping.request == MappingModifier)
1239     XRefreshKeyboardMapping(&xevent.xmapping);
1240 matthewc 203
1241     if (xevent.xmapping.request == MappingModifier)
1242     {
1243 jsorg71 450 XFreeModifiermap(g_mod_map);
1244     g_mod_map = XGetModifierMapping(g_display);
1245 matthewc 203 }
1246 astrand 119 break;
1247 matthewc 432
1248 astrand 435 /* clipboard stuff */
1249 forsberg 415 case SelectionNotify:
1250 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1251 forsberg 415 break;
1252     case SelectionRequest:
1253 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1254 forsberg 415 break;
1255 matthewc 432 case SelectionClear:
1256     xclip_handle_SelectionClear();
1257     break;
1258 forsberg 415 case PropertyNotify:
1259 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1260 forsberg 415 break;
1261 matty 9 }
1262     }
1263 astrand 275 /* Keep going */
1264     return 1;
1265 matty 9 }
1266    
1267 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1268     int
1269 matty 33 ui_select(int rdp_socket)
1270     {
1271 jsorg71 450 int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
1272 matthewc 474 fd_set rfds, wfds;
1273 matty 33
1274     while (True)
1275     {
1276 matthewc 121 /* Process any events already waiting */
1277 astrand 275 if (!xwin_process_events())
1278     /* User quit */
1279     return 0;
1280 astrand 119
1281 matty 33 FD_ZERO(&rfds);
1282 matthewc 474 FD_ZERO(&wfds);
1283 matty 33 FD_SET(rdp_socket, &rfds);
1284 jsorg71 450 FD_SET(g_x_socket, &rfds);
1285 matty 33
1286 matthewc 474 #ifdef WITH_RDPSND
1287     /* FIXME: there should be an API for registering fds */
1288 stargo 504 if (g_dsp_busy)
1289 matty 33 {
1290 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1291     n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
1292 astrand 499 }
1293 matthewc 474 #endif
1294    
1295     switch (select(n, &rfds, &wfds, NULL, NULL))
1296     {
1297 matty 33 case -1:
1298     error("select: %s\n", strerror(errno));
1299    
1300     case 0:
1301     continue;
1302     }
1303    
1304     if (FD_ISSET(rdp_socket, &rfds))
1305 astrand 275 return 1;
1306 matthewc 474
1307     #ifdef WITH_RDPSND
1308 stargo 504 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1309 matthewc 474 wave_out_play();
1310     #endif
1311 matty 33 }
1312     }
1313    
1314     void
1315 matty 25 ui_move_pointer(int x, int y)
1316 matty 9 {
1317 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1318 matty 9 }
1319    
1320 matty 25 HBITMAP
1321 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1322 matty 6 {
1323     XImage *image;
1324 matty 9 Pixmap bitmap;
1325 matty 28 uint8 *tdata;
1326 stargo 521 int bitmap_pad;
1327 matty 29
1328 stargo 521 if (g_server_bpp == 8)
1329     {
1330     bitmap_pad = 8;
1331     }
1332     else
1333     {
1334     bitmap_pad = g_bpp;
1335    
1336     if (g_bpp == 24)
1337     bitmap_pad = 32;
1338     }
1339    
1340 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1341     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1342     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1343 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1344 matty 6
1345 jsorg71 450 XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1346 matty 9
1347     XFree(image);
1348 jsorg71 450 if (!g_owncolmap)
1349 n-ki 279 xfree(tdata);
1350 matty 24 return (HBITMAP) bitmap;
1351 matty 6 }
1352    
1353 matty 25 void
1354 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1355 matty 6 {
1356 matty 10 XImage *image;
1357 matty 29 uint8 *tdata;
1358 stargo 521 int bitmap_pad;
1359    
1360     if (g_server_bpp == 8)
1361     {
1362     bitmap_pad = 8;
1363     }
1364     else
1365     {
1366     bitmap_pad = g_bpp;
1367    
1368     if (g_bpp == 24)
1369     bitmap_pad = 32;
1370     }
1371    
1372 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1373     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1374 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1375 matty 28
1376 jsorg71 450 if (g_ownbackstore)
1377 matty 31 {
1378 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1379     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1380 matty 31 }
1381     else
1382     {
1383 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1384 matty 31 }
1385 matty 29
1386 matty 24 XFree(image);
1387 jsorg71 450 if (!g_owncolmap)
1388 n-ki 279 xfree(tdata);
1389 matty 6 }
1390    
1391 matty 25 void
1392     ui_destroy_bitmap(HBITMAP bmp)
1393 matty 6 {
1394 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1395 matty 10 }
1396    
1397 matty 25 HGLYPH
1398 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1399 matty 10 {
1400 matty 9 XImage *image;
1401     Pixmap bitmap;
1402     int scanline;
1403     GC gc;
1404 matty 6
1405 matty 9 scanline = (width + 7) / 8;
1406 matty 6
1407 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1408     gc = XCreateGC(g_display, bitmap, 0, NULL);
1409 matty 9
1410 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1411 astrand 73 width, height, 8, scanline);
1412 matty 23 image->byte_order = MSBFirst;
1413     image->bitmap_bit_order = MSBFirst;
1414     XInitImage(image);
1415    
1416 jsorg71 450 XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1417 matty 29
1418 matty 9 XFree(image);
1419 jsorg71 450 XFreeGC(g_display, gc);
1420 astrand 64 return (HGLYPH) bitmap;
1421 matty 6 }
1422 matty 7
1423 matty 25 void
1424     ui_destroy_glyph(HGLYPH glyph)
1425 matty 7 {
1426 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1427 matty 9 }
1428    
1429 matty 29 HCURSOR
1430 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1431     uint8 * andmask, uint8 * xormask)
1432 matty 9 {
1433 matty 29 HGLYPH maskglyph, cursorglyph;
1434     XColor bg, fg;
1435     Cursor xcursor;
1436     uint8 *cursor, *pcursor;
1437     uint8 *mask, *pmask;
1438     uint8 nextbit;
1439     int scanline, offset;
1440     int i, j;
1441    
1442     scanline = (width + 7) / 8;
1443     offset = scanline * height;
1444    
1445 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1446 matty 29 memset(cursor, 0, offset);
1447    
1448 forsberg 415 mask = (uint8 *) xmalloc(offset);
1449 matty 29 memset(mask, 0, offset);
1450    
1451     /* approximate AND and XOR masks with a monochrome X pointer */
1452     for (i = 0; i < height; i++)
1453 matty 7 {
1454 matty 29 offset -= scanline;
1455     pcursor = &cursor[offset];
1456     pmask = &mask[offset];
1457    
1458     for (j = 0; j < scanline; j++)
1459 matty 28 {
1460 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1461     {
1462     if (xormask[0] || xormask[1] || xormask[2])
1463     {
1464     *pcursor |= (~(*andmask) & nextbit);
1465     *pmask |= nextbit;
1466     }
1467     else
1468     {
1469     *pcursor |= ((*andmask) & nextbit);
1470     *pmask |= (~(*andmask) & nextbit);
1471     }
1472    
1473     xormask += 3;
1474     }
1475    
1476     andmask++;
1477     pcursor++;
1478     pmask++;
1479 matty 28 }
1480 matty 7 }
1481 matty 29
1482     fg.red = fg.blue = fg.green = 0xffff;
1483     bg.red = bg.blue = bg.green = 0x0000;
1484     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1485    
1486     cursorglyph = ui_create_glyph(width, height, cursor);
1487     maskglyph = ui_create_glyph(width, height, mask);
1488    
1489 astrand 66 xcursor =
1490 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1491 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1492 astrand 64
1493 matty 29 ui_destroy_glyph(maskglyph);
1494     ui_destroy_glyph(cursorglyph);
1495     xfree(mask);
1496     xfree(cursor);
1497 astrand 64 return (HCURSOR) xcursor;
1498 matty 29 }
1499    
1500     void
1501     ui_set_cursor(HCURSOR cursor)
1502     {
1503 jsorg71 450 g_current_cursor = (Cursor) cursor;
1504     XDefineCursor(g_display, g_wnd, g_current_cursor);
1505 matty 29 }
1506    
1507     void
1508     ui_destroy_cursor(HCURSOR cursor)
1509     {
1510 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1511 matty 29 }
1512    
1513 astrand 508 void
1514     ui_set_null_cursor(void)
1515     {
1516     ui_set_cursor(g_null_cursor);
1517     }
1518    
1519 matty 29 #define MAKE_XCOLOR(xc,c) \
1520     (xc)->red = ((c)->red << 8) | (c)->red; \
1521     (xc)->green = ((c)->green << 8) | (c)->green; \
1522     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1523     (xc)->flags = DoRed | DoGreen | DoBlue;
1524    
1525 n-ki 279
1526 matty 29 HCOLOURMAP
1527 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1528 matty 29 {
1529     COLOURENTRY *entry;
1530     int i, ncolours = colours->ncolours;
1531 jsorg71 450 if (!g_owncolmap)
1532 matty 28 {
1533 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1534 n-ki 279 XColor xentry;
1535     XColor xc_cache[256];
1536     uint32 colour;
1537     int colLookup = 256;
1538     for (i = 0; i < ncolours; i++)
1539 matty 28 {
1540 n-ki 279 entry = &colours->colours[i];
1541     MAKE_XCOLOR(&xentry, entry);
1542 matty 7
1543 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1544 astrand 196 {
1545 n-ki 279 /* Allocation failed, find closest match. */
1546     int j = 256;
1547     int nMinDist = 3 * 256 * 256;
1548     long nDist = nMinDist;
1549 matty 28
1550 n-ki 279 /* only get the colors once */
1551     while (colLookup--)
1552 astrand 196 {
1553 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1554     xc_cache[colLookup].red = xc_cache[colLookup].green =
1555     xc_cache[colLookup].blue = 0;
1556     xc_cache[colLookup].flags = 0;
1557 jsorg71 450 XQueryColor(g_display,
1558     DefaultColormap(g_display,
1559     DefaultScreen(g_display)),
1560 n-ki 279 &xc_cache[colLookup]);
1561 n-ki 185 }
1562 n-ki 279 colLookup = 0;
1563    
1564     /* approximate the pixel */
1565     while (j--)
1566 astrand 196 {
1567 n-ki 279 if (xc_cache[j].flags)
1568     {
1569     nDist = ((long) (xc_cache[j].red >> 8) -
1570     (long) (xentry.red >> 8)) *
1571     ((long) (xc_cache[j].red >> 8) -
1572     (long) (xentry.red >> 8)) +
1573     ((long) (xc_cache[j].green >> 8) -
1574     (long) (xentry.green >> 8)) *
1575     ((long) (xc_cache[j].green >> 8) -
1576     (long) (xentry.green >> 8)) +
1577     ((long) (xc_cache[j].blue >> 8) -
1578     (long) (xentry.blue >> 8)) *
1579     ((long) (xc_cache[j].blue >> 8) -
1580     (long) (xentry.blue >> 8));
1581     }
1582     if (nDist < nMinDist)
1583     {
1584     nMinDist = nDist;
1585     xentry.pixel = j;
1586     }
1587 n-ki 185 }
1588     }
1589 n-ki 279 colour = xentry.pixel;
1590    
1591     /* update our cache */
1592     if (xentry.pixel < 256)
1593     {
1594     xc_cache[xentry.pixel].red = xentry.red;
1595     xc_cache[xentry.pixel].green = xentry.green;
1596     xc_cache[xentry.pixel].blue = xentry.blue;
1597    
1598     }
1599    
1600 matthewc 527 map[i] = colour;
1601 n-ki 185 }
1602 n-ki 279 return map;
1603     }
1604     else
1605     {
1606     XColor *xcolours, *xentry;
1607     Colormap map;
1608 matty 29
1609 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1610 n-ki 279 for (i = 0; i < ncolours; i++)
1611 astrand 196 {
1612 n-ki 279 entry = &colours->colours[i];
1613     xentry = &xcolours[i];
1614     xentry->pixel = i;
1615     MAKE_XCOLOR(xentry, entry);
1616 matty 29 }
1617    
1618 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1619     XStoreColors(g_display, map, xcolours, ncolours);
1620 n-ki 185
1621 n-ki 279 xfree(xcolours);
1622     return (HCOLOURMAP) map;
1623 matty 29 }
1624 matty 7 }
1625    
1626 matty 25 void
1627     ui_destroy_colourmap(HCOLOURMAP map)
1628 matty 7 {
1629 jsorg71 450 if (!g_owncolmap)
1630 n-ki 279 xfree(map);
1631     else
1632 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1633 matty 7 }
1634    
1635 matty 25 void
1636     ui_set_colourmap(HCOLOURMAP map)
1637 matty 7 {
1638 jsorg71 450 if (!g_owncolmap)
1639 astrand 448 {
1640 jsorg71 450 if (g_colmap)
1641     xfree(g_colmap);
1642 astrand 448
1643 jsorg71 450 g_colmap = (uint32 *) map;
1644 astrand 448 }
1645 n-ki 279 else
1646 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1647 matty 7 }
1648    
1649 matty 25 void
1650     ui_set_clip(int x, int y, int cx, int cy)
1651 matty 7 {
1652 matty 9 XRectangle rect;
1653 matty 7
1654 matty 9 rect.x = x;
1655     rect.y = y;
1656     rect.width = cx;
1657     rect.height = cy;
1658 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1659 matty 9 }
1660 matty 7
1661 matty 25 void
1662 matthewc 192 ui_reset_clip(void)
1663 matty 9 {
1664     XRectangle rect;
1665    
1666     rect.x = 0;
1667     rect.y = 0;
1668 jsorg71 447 rect.width = g_width;
1669     rect.height = g_height;
1670 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1671 matty 7 }
1672    
1673 matty 25 void
1674 matthewc 192 ui_bell(void)
1675 matty 10 {
1676 jsorg71 450 XBell(g_display, 0);
1677 matty 10 }
1678    
1679 matty 25 void
1680     ui_destblt(uint8 opcode,
1681     /* dest */ int x, int y, int cx, int cy)
1682 matty 9 {
1683 matty 29 SET_FUNCTION(opcode);
1684 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1685 matty 29 RESET_FUNCTION(opcode);
1686 matty 9 }
1687    
1688 jsorg71 373 static uint8 hatch_patterns[] = {
1689 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1690     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1691     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1692     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1693     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1694     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1695 jsorg71 373 };
1696    
1697 matty 25 void
1698     ui_patblt(uint8 opcode,
1699     /* dest */ int x, int y, int cx, int cy,
1700 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1701 matty 9 {
1702     Pixmap fill;
1703 jsorg71 59 uint8 i, ipattern[8];
1704 matty 9
1705 matty 29 SET_FUNCTION(opcode);
1706 matty 9
1707     switch (brush->style)
1708     {
1709 matty 24 case 0: /* Solid */
1710 matty 29 SET_FOREGROUND(fgcolour);
1711 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1712 matty 9 break;
1713    
1714 jsorg71 373 case 2: /* Hatch */
1715 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1716     hatch_patterns + brush->pattern[0] * 8);
1717 astrand 487 SET_FOREGROUND(fgcolour);
1718     SET_BACKGROUND(bgcolour);
1719 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1720     XSetStipple(g_display, g_gc, fill);
1721     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1722 jsorg71 373 FILL_RECTANGLE(x, y, cx, cy);
1723 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1724     XSetTSOrigin(g_display, g_gc, 0, 0);
1725 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1726     break;
1727    
1728 matty 24 case 3: /* Pattern */
1729 jsorg71 59 for (i = 0; i != 8; i++)
1730     ipattern[7 - i] = brush->pattern[i];
1731     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1732 matty 9
1733 matty 29 SET_FOREGROUND(bgcolour);
1734     SET_BACKGROUND(fgcolour);
1735 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1736     XSetStipple(g_display, g_gc, fill);
1737     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1738 matty 9
1739 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1740 matty 9
1741 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1742     XSetTSOrigin(g_display, g_gc, 0, 0);
1743 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1744 matty 9 break;
1745    
1746     default:
1747 matty 30 unimpl("brush %d\n", brush->style);
1748 matty 9 }
1749 matty 29
1750     RESET_FUNCTION(opcode);
1751 matty 9 }
1752    
1753 matty 25 void
1754     ui_screenblt(uint8 opcode,
1755     /* dest */ int x, int y, int cx, int cy,
1756     /* src */ int srcx, int srcy)
1757 matty 9 {
1758 matty 29 SET_FUNCTION(opcode);
1759 jsorg71 450 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1760     if (g_ownbackstore)
1761     XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1762 matty 29 RESET_FUNCTION(opcode);
1763 matty 9 }
1764    
1765 matty 25 void
1766     ui_memblt(uint8 opcode,
1767     /* dest */ int x, int y, int cx, int cy,
1768     /* src */ HBITMAP src, int srcx, int srcy)
1769 matty 9 {
1770 matty 29 SET_FUNCTION(opcode);
1771 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1772     if (g_ownbackstore)
1773     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1774 matty 29 RESET_FUNCTION(opcode);
1775 matty 9 }
1776    
1777 matty 25 void
1778     ui_triblt(uint8 opcode,
1779     /* dest */ int x, int y, int cx, int cy,
1780     /* src */ HBITMAP src, int srcx, int srcy,
1781 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1782 matty 9 {
1783     /* This is potentially difficult to do in general. Until someone
1784 matty 10 comes up with a more efficient way of doing it I am using cases. */
1785 matty 9
1786     switch (opcode)
1787     {
1788 matty 24 case 0x69: /* PDSxxn */
1789 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1790 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1791 matty 16 break;
1792    
1793 matty 24 case 0xb8: /* PSDPxax */
1794 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1795 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1796 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1797 matty 9 break;
1798    
1799 matty 29 case 0xc0: /* PSa */
1800 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1801 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1802 matty 28 break;
1803    
1804 matty 9 default:
1805 matty 30 unimpl("triblt 0x%x\n", opcode);
1806 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1807 matty 9 }
1808     }
1809    
1810 matty 25 void
1811     ui_line(uint8 opcode,
1812     /* dest */ int startx, int starty, int endx, int endy,
1813 astrand 64 /* pen */ PEN * pen)
1814 matty 9 {
1815 matty 29 SET_FUNCTION(opcode);
1816     SET_FOREGROUND(pen->colour);
1817 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1818     if (g_ownbackstore)
1819     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1820 matty 29 RESET_FUNCTION(opcode);
1821 matty 9 }
1822    
1823 matty 25 void
1824     ui_rect(
1825     /* dest */ int x, int y, int cx, int cy,
1826     /* brush */ int colour)
1827 matty 9 {
1828 matty 29 SET_FOREGROUND(colour);
1829 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1830 matty 9 }
1831    
1832 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1833 matty 25 void
1834     ui_draw_glyph(int mixmode,
1835     /* dest */ int x, int y, int cx, int cy,
1836 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1837     int bgcolour, int fgcolour)
1838 matty 9 {
1839 matty 29 SET_FOREGROUND(fgcolour);
1840     SET_BACKGROUND(bgcolour);
1841 matty 9
1842 jsorg71 450 XSetFillStyle(g_display, g_gc,
1843 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1844 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
1845     XSetTSOrigin(g_display, g_gc, x, y);
1846 matty 9
1847 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1848 matty 9
1849 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1850 matty 9 }
1851    
1852 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1853     {\
1854     glyph = cache_get_font (font, ttext[idx]);\
1855     if (!(flags & TEXT2_IMPLICIT_X))\
1856 jsorg71 564 {\
1857     xyoffset = ttext[++idx];\
1858     if ((xyoffset & 0x80))\
1859 mmihalik 49 {\
1860 jsorg71 564 if (flags & TEXT2_VERTICAL)\
1861     y += ttext[idx+1] | (ttext[idx+2] << 8);\
1862 mmihalik 49 else\
1863 jsorg71 564 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1864     idx += 2;\
1865 mmihalik 49 }\
1866 jsorg71 564 else\
1867 mmihalik 49 {\
1868 jsorg71 564 if (flags & TEXT2_VERTICAL)\
1869     y += xyoffset;\
1870     else\
1871     x += xyoffset;\
1872 mmihalik 49 }\
1873 jsorg71 564 }\
1874     if (glyph != NULL)\
1875     {\
1876     x1 = x + glyph->offset;\
1877     y1 = y + glyph->baseline;\
1878     XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
1879     XSetTSOrigin(g_display, g_gc, x1, y1);\
1880     FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
1881     if (flags & TEXT2_IMPLICIT_X)\
1882     x += glyph->width;\
1883     }\
1884 mmihalik 49 }
1885    
1886 matty 25 void
1887     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1888 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1889     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1890 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1891 matty 9 {
1892 matty 10 FONTGLYPH *glyph;
1893 jsorg71 564 int i, j, xyoffset, x1, y1;
1894 mmihalik 49 DATABLOB *entry;
1895 matty 9
1896 matty 29 SET_FOREGROUND(bgcolour);
1897 matty 28
1898 matty 9 if (boxcx > 1)
1899 matty 31 {
1900 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1901 matty 31 }
1902 matty 17 else if (mixmode == MIX_OPAQUE)
1903 matty 31 {
1904 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1905 matty 31 }
1906 matty 9
1907 jsorg71 564 SET_FOREGROUND(fgcolour);
1908     SET_BACKGROUND(bgcolour);
1909     XSetFillStyle(g_display, g_gc, FillStippled);
1910    
1911 matty 9 /* Paint text, character by character */
1912 astrand 64 for (i = 0; i < length;)
1913     {
1914     switch (text[i])
1915     {
1916     case 0xff:
1917     if (i + 2 < length)
1918 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1919 astrand 64 else
1920     {
1921     error("this shouldn't be happening\n");
1922 astrand 265 exit(1);
1923 astrand 64 }
1924     /* this will move pointer from start to first character after FF command */
1925     length -= i + 3;
1926     text = &(text[i + 3]);
1927     i = 0;
1928 mmihalik 49 break;
1929 matty 9
1930 astrand 64 case 0xfe:
1931     entry = cache_get_text(text[i + 1]);
1932     if (entry != NULL)
1933     {
1934     if ((((uint8 *) (entry->data))[1] ==
1935 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1936 astrand 64 {
1937     if (flags & TEXT2_VERTICAL)
1938     y += text[i + 2];
1939     else
1940     x += text[i + 2];
1941     }
1942     for (j = 0; j < entry->size; j++)
1943 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1944 matthewc 44 }
1945 jsorg71 286 if (i + 2 < length)
1946     i += 3;
1947     else
1948     i += 2;
1949     length -= i;
1950     /* this will move pointer from start to first character after FE command */
1951     text = &(text[i]);
1952     i = 0;
1953 astrand 64 break;
1954 matty 17
1955 astrand 64 default:
1956     DO_GLYPH(text, i);
1957     i++;
1958     break;
1959 matty 29 }
1960 mmihalik 49 }
1961 jsorg71 564
1962     XSetFillStyle(g_display, g_gc, FillSolid);
1963    
1964 jsorg71 450 if (g_ownbackstore)
1965 jsorg71 278 {
1966     if (boxcx > 1)
1967 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1968 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
1969     else
1970 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1971 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
1972     }
1973 matty 9 }
1974    
1975 matty 25 void
1976     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1977 matty 9 {
1978 matty 28 Pixmap pix;
1979 matty 9 XImage *image;
1980    
1981 jsorg71 450 if (g_ownbackstore)
1982 matty 31 {
1983 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1984 matty 31 }
1985     else
1986     {
1987 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1988     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1989     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1990     XFreePixmap(g_display, pix);
1991 matty 31 }
1992 matty 28
1993 jsorg71 450 offset *= g_bpp / 8;
1994     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
1995 matty 28
1996     XDestroyImage(image);
1997 matty 9 }
1998    
1999 matty 25 void
2000     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2001 matty 9 {
2002     XImage *image;
2003 matty 10 uint8 *data;
2004 matty 9
2005 jsorg71 450 offset *= g_bpp / 8;
2006     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2007 matty 10 if (data == NULL)
2008     return;
2009 matty 29
2010 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2011     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2012 matty 29
2013 jsorg71 450 if (g_ownbackstore)
2014 matty 31 {
2015 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2016     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2017 matty 31 }
2018     else
2019     {
2020 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2021 matty 31 }
2022    
2023 matty 9 XFree(image);
2024     }

  ViewVC Help
Powered by ViewVC 1.1.26