/[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 644 - (hide annotations)
Thu Mar 25 22:58:45 2004 UTC (20 years, 1 month ago) by jsorg71
File MIME type: text/plain
File size: 45948 byte(s)
if rdp server and client bpp match and architectures match, don't translate image

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

  ViewVC Help
Powered by ViewVC 1.1.26