/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 725 - (hide annotations)
Sun Jun 27 17:51:54 2004 UTC (19 years, 10 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 48573 byte(s)
added persistant bitmap chaching from Jeroen Meijer, slightly modified

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

  ViewVC Help
Powered by ViewVC 1.1.26