/[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 688 - (hide annotations)
Fri Apr 30 19:14:15 2004 UTC (20 years ago) by jsorg71
File MIME type: text/plain
File size: 47218 byte(s)
speed up screenblt if screen is unobscured

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

  ViewVC Help
Powered by ViewVC 1.1.26