/[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 691 - (hide annotations)
Thu May 6 08:17:47 2004 UTC (20 years ago) by astrand
File MIME type: text/plain
File size: 47241 byte(s)
Indent fixes.

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

  ViewVC Help
Powered by ViewVC 1.1.26