/[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 636 - (hide annotations)
Sat Mar 13 12:08:18 2004 UTC (20 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 45271 byte(s)
XEmbed-patch by Arend van Beelen jr. <arend@auton.nl>

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

  ViewVC Help
Powered by ViewVC 1.1.26