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

  ViewVC Help
Powered by ViewVC 1.1.26