/[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 679 - (hide annotations)
Mon Apr 26 23:00:25 2004 UTC (20 years ago) by jsorg71
File MIME type: text/plain
File size: 46684 byte(s)
unroll the bits in translate8to16/32

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

  ViewVC Help
Powered by ViewVC 1.1.26