/[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 795 - (hide annotations)
Wed Nov 3 13:56:52 2004 UTC (19 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 48497 byte(s)
Big serial- and disk-redirection update from
Andreas Flick <Andreas.Flick@unicon-ka.de>

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 astrand 788 uint8 null_pointer_data[24] = { 0x00 };
950    
951 matthewc 121 XSetWindowAttributes attribs;
952 matty 28 XClassHint *classhints;
953     XSizeHints *sizehints;
954 matthewc 188 int wndwidth, wndheight;
955 matthewc 432 long input_mask, ic_input_mask;
956 jsorg71 100 XEvent xevent;
957    
958 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
959     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
960 matthewc 188
961 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
962 stargo 565 attribs.border_pixel = WhitePixelOfScreen(g_screen);
963 jsorg71 450 attribs.backing_store = g_ownbackstore ? NotUseful : Always;
964 jsorg71 447 attribs.override_redirect = g_fullscreen;
965 stargo 565 attribs.colormap = g_xcolmap;
966 matthewc 188
967 jsorg71 450 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
968 stargo 565 0, g_depth, InputOutput, g_visual,
969     CWBackPixel | CWBackingStore | CWOverrideRedirect |
970     CWColormap | CWBorderPixel, &attribs);
971 jsorg71 100
972 stargo 576 if (g_gc == NULL)
973 stargo 566 g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
974 stargo 565
975 jsorg71 725 if (g_create_bitmap_gc == NULL)
976     g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
977    
978 stargo 603 if ((g_ownbackstore) && (g_backstore == 0))
979 stargo 565 {
980 astrand 580 g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
981 stargo 565
982     /* clear to prevent rubbish being exposed at startup */
983     XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
984     XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
985     }
986    
987 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
988 jsorg71 100
989 jsorg71 450 if (g_hide_decorations)
990 astrand 262 mwm_hide_decorations();
991    
992 jsorg71 100 classhints = XAllocClassHint();
993     if (classhints != NULL)
994     {
995     classhints->res_name = classhints->res_class = "rdesktop";
996 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
997 jsorg71 100 XFree(classhints);
998     }
999    
1000     sizehints = XAllocSizeHints();
1001     if (sizehints)
1002     {
1003     sizehints->flags = PMinSize | PMaxSize;
1004 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
1005     sizehints->min_height = sizehints->max_height = g_height;
1006 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
1007 jsorg71 100 XFree(sizehints);
1008     }
1009    
1010 astrand 651 if (g_embed_wnd)
1011     {
1012     XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1013     }
1014 stargo 636
1015 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1016 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
1017 matthewc 121
1018 jsorg71 447 if (g_sendmotion)
1019 matthewc 121 input_mask |= PointerMotionMask;
1020 jsorg71 450 if (g_ownbackstore)
1021 matthewc 121 input_mask |= ExposureMask;
1022 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
1023 matthewc 250 input_mask |= EnterWindowMask;
1024 jsorg71 450 if (g_grab_keyboard)
1025 jsorg71 257 input_mask |= LeaveWindowMask;
1026 jsorg71 100
1027 jsorg71 450 if (g_IM != NULL)
1028 matthewc 188 {
1029 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1030 astrand 456 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1031 matthewc 188
1032 jsorg71 450 if ((g_IC != NULL)
1033     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1034 matthewc 188 input_mask |= ic_input_mask;
1035     }
1036    
1037 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
1038     XMapWindow(g_display, g_wnd);
1039 jsorg71 100
1040 matthewc 208 /* wait for VisibilityNotify */
1041 astrand 196 do
1042     {
1043 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1044 astrand 196 }
1045 matthewc 208 while (xevent.type != VisibilityNotify);
1046 jsorg71 688 g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1047 matthewc 123
1048 jsorg71 447 g_focused = False;
1049     g_mouse_in_wnd = False;
1050 jsorg71 257
1051 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
1052 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1053     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1054     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1055 astrand 275
1056 astrand 508 /* create invisible 1x1 cursor to be used as null cursor */
1057 stargo 576 if (g_null_cursor == NULL)
1058     g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1059 astrand 508
1060 matty 10 return True;
1061 matty 6 }
1062    
1063 matty 25 void
1064 n-ki 677 ui_resize_window()
1065     {
1066     XSizeHints *sizehints;
1067 jsorg71 708 Pixmap bs;
1068 n-ki 677
1069     sizehints = XAllocSizeHints();
1070     if (sizehints)
1071     {
1072     sizehints->flags = PMinSize | PMaxSize;
1073     sizehints->min_width = sizehints->max_width = g_width;
1074     sizehints->min_height = sizehints->max_height = g_height;
1075     XSetWMNormalHints(g_display, g_wnd, sizehints);
1076     XFree(sizehints);
1077     }
1078    
1079     if (!(g_fullscreen || g_embed_wnd))
1080     {
1081     XResizeWindow(g_display, g_wnd, g_width, g_height);
1082     }
1083 jsorg71 708
1084     /* create new backstore pixmap */
1085     if (g_backstore != 0)
1086     {
1087     bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1088     XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1089     XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1090     XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1091     XFreePixmap(g_display, g_backstore);
1092     g_backstore = bs;
1093     }
1094 n-ki 677 }
1095    
1096     void
1097 matthewc 192 ui_destroy_window(void)
1098 matty 6 {
1099 jsorg71 450 if (g_IC != NULL)
1100     XDestroyIC(g_IC);
1101 matty 31
1102 jsorg71 450 XDestroyWindow(g_display, g_wnd);
1103 matty 6 }
1104    
1105 jsorg71 100 void
1106 matthewc 192 xwin_toggle_fullscreen(void)
1107 jsorg71 100 {
1108 matthewc 188 Pixmap contents = 0;
1109 matthewc 123
1110 jsorg71 450 if (!g_ownbackstore)
1111 matthewc 188 {
1112     /* need to save contents of window */
1113 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1114     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1115 matthewc 188 }
1116    
1117     ui_destroy_window();
1118 jsorg71 447 g_fullscreen = !g_fullscreen;
1119 matthewc 188 ui_create_window();
1120 matthewc 123
1121 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
1122 matthewc 188
1123 jsorg71 450 if (!g_ownbackstore)
1124 matthewc 188 {
1125 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1126     XFreePixmap(g_display, contents);
1127 matthewc 188 }
1128 jsorg71 100 }
1129    
1130 jsorg71 447 /* Process all events in Xlib queue
1131 astrand 275 Returns 0 after user quit, 1 otherwise */
1132     static int
1133 matthewc 192 xwin_process_events(void)
1134 matty 9 {
1135 n-ki 54 XEvent xevent;
1136 matthewc 38 KeySym keysym;
1137 matthewc 50 uint16 button, flags;
1138 matty 10 uint32 ev_time;
1139 astrand 66 key_translation tr;
1140     char str[256];
1141     Status status;
1142 matty 9
1143 jsorg71 450 while (XPending(g_display) > 0)
1144 matty 9 {
1145 jsorg71 450 XNextEvent(g_display, &xevent);
1146 matthewc 123
1147 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1148 astrand 66 {
1149 astrand 84 DEBUG_KBD(("Filtering event\n"));
1150 astrand 66 continue;
1151     }
1152    
1153 matthewc 50 flags = 0;
1154 matty 10
1155 n-ki 54 switch (xevent.type)
1156 matty 9 {
1157 jsorg71 688 case VisibilityNotify:
1158     g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1159     break;
1160 astrand 275 case ClientMessage:
1161     /* the window manager told us to quit */
1162 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
1163     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1164 astrand 275 /* Quit */
1165     return 0;
1166     break;
1167    
1168 matty 9 case KeyPress:
1169 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1170     if (g_IC != NULL)
1171 astrand 66 /* Multi_key compatible version */
1172     {
1173 jsorg71 450 XmbLookupString(g_IC,
1174 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
1175     &status);
1176 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1177 astrand 66 {
1178 astrand 82 error("XmbLookupString failed with status 0x%x\n",
1179     status);
1180 astrand 66 break;
1181     }
1182     }
1183     else
1184     {
1185     /* Plain old XLookupString */
1186 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1187 astrand 66 XLookupString((XKeyEvent *) & xevent,
1188 astrand 82 str, sizeof(str), &keysym, NULL);
1189 astrand 66 }
1190    
1191 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1192     get_ksname(keysym)));
1193 astrand 66
1194 matthewc 203 ev_time = time(NULL);
1195     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1196 astrand 118 break;
1197    
1198 astrand 66 tr = xkeymap_translate_key(keysym,
1199 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1200 astrand 69
1201 astrand 66 if (tr.scancode == 0)
1202 n-ki 52 break;
1203    
1204 astrand 470 save_remote_modifiers(tr.scancode);
1205 astrand 115 ensure_remote_modifiers(ev_time, tr);
1206 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1207 astrand 470 restore_remote_modifiers(ev_time, tr.scancode);
1208 astrand 115
1209 astrand 66 break;
1210 matthewc 203
1211 astrand 66 case KeyRelease:
1212 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1213 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
1214     sizeof(str), &keysym, NULL);
1215 n-ki 52
1216 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1217 matthewc 203 get_ksname(keysym)));
1218 n-ki 52
1219 matthewc 203 ev_time = time(NULL);
1220     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1221 astrand 118 break;
1222    
1223 astrand 66 tr = xkeymap_translate_key(keysym,
1224 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1225 astrand 66
1226     if (tr.scancode == 0)
1227     break;
1228    
1229 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1230 matty 9 break;
1231    
1232     case ButtonPress:
1233 matthewc 50 flags = MOUSE_FLAG_DOWN;
1234     /* fall through */
1235 matty 9
1236     case ButtonRelease:
1237 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
1238 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
1239 matty 9 if (button == 0)
1240     break;
1241    
1242 astrand 328 /* If win_button_size is nonzero, enable single app mode */
1243 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
1244 astrand 328 {
1245 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
1246 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
1247     g_moving_wnd = False;
1248 astrand 332
1249 astrand 342 /* Check from right to left: */
1250    
1251 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
1252 astrand 328 {
1253 astrand 331 /* The close button, continue */
1254 astrand 328 ;
1255     }
1256 astrand 456 else if (xevent.xbutton.x >=
1257     g_width - g_win_button_size * 2)
1258 astrand 328 {
1259     /* The maximize/restore button. Do not send to
1260     server. It might be a good idea to change the
1261 jsorg71 447 cursor or give some other visible indication
1262 astrand 328 that rdesktop inhibited this click */
1263     break;
1264     }
1265 astrand 456 else if (xevent.xbutton.x >=
1266     g_width - g_win_button_size * 3)
1267 astrand 328 {
1268     /* The minimize button. Iconify window. */
1269 jsorg71 450 XIconifyWindow(g_display, g_wnd,
1270     DefaultScreen(g_display));
1271 astrand 328 break;
1272     }
1273 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
1274 astrand 342 {
1275     /* The system menu. Ignore. */
1276     break;
1277     }
1278 astrand 332 else
1279     {
1280 astrand 342 /* The title bar. */
1281 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
1282 jsorg71 450 && g_hide_decorations)
1283 astrand 342 {
1284 jsorg71 450 g_moving_wnd = True;
1285     g_move_x_offset = xevent.xbutton.x;
1286     g_move_y_offset = xevent.xbutton.y;
1287 astrand 342 }
1288 astrand 332 break;
1289 astrand 342
1290 astrand 332 }
1291 astrand 328 }
1292    
1293 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1294 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1295 matty 10 break;
1296    
1297     case MotionNotify:
1298 jsorg71 450 if (g_moving_wnd)
1299 astrand 342 {
1300 jsorg71 450 XMoveWindow(g_display, g_wnd,
1301     xevent.xmotion.x_root - g_move_x_offset,
1302     xevent.xmotion.y_root - g_move_y_offset);
1303 astrand 342 break;
1304     }
1305    
1306 jsorg71 447 if (g_fullscreen && !g_focused)
1307 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1308 jsorg71 288 CurrentTime);
1309 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1310 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1311 matty 28 break;
1312    
1313 matthewc 194 case FocusIn:
1314 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
1315     break;
1316 jsorg71 447 g_focused = True;
1317 astrand 543 reset_modifier_keys();
1318 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
1319     XGrabKeyboard(g_display, g_wnd, True,
1320 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
1321 matty 28 break;
1322    
1323 matthewc 194 case FocusOut:
1324 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
1325     break;
1326 jsorg71 447 g_focused = False;
1327 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1328 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1329 matty 28 break;
1330 matty 31
1331 matthewc 250 case EnterNotify:
1332     /* we only register for this event when in fullscreen mode */
1333 jsorg71 257 /* or grab_keyboard */
1334 jsorg71 447 g_mouse_in_wnd = True;
1335     if (g_fullscreen)
1336 jsorg71 257 {
1337 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1338 astrand 261 CurrentTime);
1339 jsorg71 257 break;
1340     }
1341 jsorg71 447 if (g_focused)
1342 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
1343 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
1344 matthewc 250 break;
1345    
1346 matthewc 253 case LeaveNotify:
1347 jsorg71 257 /* we only register for this event when grab_keyboard */
1348 jsorg71 447 g_mouse_in_wnd = False;
1349 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1350 matthewc 253 break;
1351    
1352 matty 31 case Expose:
1353 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1354 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
1355 astrand 64 xevent.xexpose.width,
1356     xevent.xexpose.height,
1357 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
1358 matty 31 break;
1359 astrand 119
1360     case MappingNotify:
1361     /* Refresh keyboard mapping if it has changed. This is important for
1362     Xvnc, since it allocates keycodes dynamically */
1363     if (xevent.xmapping.request == MappingKeyboard
1364     || xevent.xmapping.request == MappingModifier)
1365     XRefreshKeyboardMapping(&xevent.xmapping);
1366 matthewc 203
1367     if (xevent.xmapping.request == MappingModifier)
1368     {
1369 jsorg71 450 XFreeModifiermap(g_mod_map);
1370     g_mod_map = XGetModifierMapping(g_display);
1371 matthewc 203 }
1372 astrand 119 break;
1373 matthewc 432
1374 astrand 435 /* clipboard stuff */
1375 forsberg 415 case SelectionNotify:
1376 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1377 forsberg 415 break;
1378     case SelectionRequest:
1379 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1380 forsberg 415 break;
1381 matthewc 432 case SelectionClear:
1382     xclip_handle_SelectionClear();
1383     break;
1384 forsberg 415 case PropertyNotify:
1385 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1386 forsberg 415 break;
1387 matty 9 }
1388     }
1389 astrand 275 /* Keep going */
1390     return 1;
1391 matty 9 }
1392    
1393 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1394     int
1395 matty 33 ui_select(int rdp_socket)
1396     {
1397 stargo 606 int n;
1398 matthewc 474 fd_set rfds, wfds;
1399 n-ki 592 struct timeval tv;
1400     BOOL s_timeout = False;
1401 matty 33
1402     while (True)
1403     {
1404 stargo 606 n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1405 matthewc 121 /* Process any events already waiting */
1406 astrand 275 if (!xwin_process_events())
1407     /* User quit */
1408     return 0;
1409 astrand 119
1410 matty 33 FD_ZERO(&rfds);
1411 matthewc 474 FD_ZERO(&wfds);
1412 matty 33 FD_SET(rdp_socket, &rfds);
1413 jsorg71 450 FD_SET(g_x_socket, &rfds);
1414 matty 33
1415 matthewc 474 #ifdef WITH_RDPSND
1416     /* FIXME: there should be an API for registering fds */
1417 stargo 504 if (g_dsp_busy)
1418 matty 33 {
1419 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1420 n-ki 592 n = (g_dsp_fd > n) ? g_dsp_fd : n;
1421 astrand 499 }
1422 matthewc 474 #endif
1423 n-ki 592 /* default timeout */
1424     tv.tv_sec = 60;
1425     tv.tv_usec = 0;
1426 matthewc 474
1427 n-ki 592 /* add redirection handles */
1428     rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1429    
1430     n++;
1431    
1432     switch (select(n, &rfds, &wfds, NULL, &tv))
1433 matthewc 474 {
1434 matty 33 case -1:
1435     error("select: %s\n", strerror(errno));
1436    
1437     case 0:
1438 stargo 795 /* Abort serial read calls */
1439     if (s_timeout)
1440     rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
1441 matty 33 continue;
1442     }
1443    
1444 n-ki 592 rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
1445    
1446 stargo 754 if (FD_ISSET(rdp_socket, &rfds))
1447     return 1;
1448    
1449 matthewc 474 #ifdef WITH_RDPSND
1450 stargo 504 if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds))
1451 matthewc 474 wave_out_play();
1452     #endif
1453 matty 33 }
1454     }
1455    
1456     void
1457 matty 25 ui_move_pointer(int x, int y)
1458 matty 9 {
1459 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1460 matty 9 }
1461    
1462 matty 25 HBITMAP
1463 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1464 matty 6 {
1465     XImage *image;
1466 matty 9 Pixmap bitmap;
1467 matty 28 uint8 *tdata;
1468 stargo 521 int bitmap_pad;
1469 matty 29
1470 stargo 521 if (g_server_bpp == 8)
1471     {
1472     bitmap_pad = 8;
1473     }
1474     else
1475     {
1476     bitmap_pad = g_bpp;
1477    
1478     if (g_bpp == 24)
1479     bitmap_pad = 32;
1480     }
1481    
1482 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1483     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1484     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1485 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1486 matty 6
1487 jsorg71 725 XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
1488 matty 9
1489     XFree(image);
1490 jsorg71 644 if (tdata != data)
1491 n-ki 279 xfree(tdata);
1492 matty 24 return (HBITMAP) bitmap;
1493 matty 6 }
1494    
1495 matty 25 void
1496 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1497 matty 6 {
1498 matty 10 XImage *image;
1499 matty 29 uint8 *tdata;
1500 stargo 521 int bitmap_pad;
1501    
1502     if (g_server_bpp == 8)
1503     {
1504     bitmap_pad = 8;
1505     }
1506     else
1507     {
1508     bitmap_pad = g_bpp;
1509    
1510     if (g_bpp == 24)
1511     bitmap_pad = 32;
1512     }
1513    
1514 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1515     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1516 stargo 521 (char *) tdata, width, height, bitmap_pad, 0);
1517 matty 28
1518 jsorg71 450 if (g_ownbackstore)
1519 matty 31 {
1520 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1521     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1522 matty 31 }
1523     else
1524     {
1525 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1526 matty 31 }
1527 matty 29
1528 matty 24 XFree(image);
1529 jsorg71 644 if (tdata != data)
1530 n-ki 279 xfree(tdata);
1531 matty 6 }
1532    
1533 matty 25 void
1534     ui_destroy_bitmap(HBITMAP bmp)
1535 matty 6 {
1536 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1537 matty 10 }
1538    
1539 matty 25 HGLYPH
1540 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1541 matty 10 {
1542 matty 9 XImage *image;
1543     Pixmap bitmap;
1544     int scanline;
1545 matty 6
1546 matty 9 scanline = (width + 7) / 8;
1547 matty 6
1548 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1549 jsorg71 725 if (g_create_glyph_gc == 0)
1550     g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
1551 matty 9
1552 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1553 astrand 73 width, height, 8, scanline);
1554 matty 23 image->byte_order = MSBFirst;
1555     image->bitmap_bit_order = MSBFirst;
1556     XInitImage(image);
1557    
1558 jsorg71 725 XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
1559 matty 29
1560 matty 9 XFree(image);
1561 astrand 64 return (HGLYPH) bitmap;
1562 matty 6 }
1563 matty 7
1564 matty 25 void
1565     ui_destroy_glyph(HGLYPH glyph)
1566 matty 7 {
1567 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1568 matty 9 }
1569    
1570 matty 29 HCURSOR
1571 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1572     uint8 * andmask, uint8 * xormask)
1573 matty 9 {
1574 matty 29 HGLYPH maskglyph, cursorglyph;
1575     XColor bg, fg;
1576     Cursor xcursor;
1577     uint8 *cursor, *pcursor;
1578     uint8 *mask, *pmask;
1579     uint8 nextbit;
1580     int scanline, offset;
1581     int i, j;
1582    
1583     scanline = (width + 7) / 8;
1584     offset = scanline * height;
1585    
1586 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1587 matty 29 memset(cursor, 0, offset);
1588    
1589 forsberg 415 mask = (uint8 *) xmalloc(offset);
1590 matty 29 memset(mask, 0, offset);
1591    
1592     /* approximate AND and XOR masks with a monochrome X pointer */
1593     for (i = 0; i < height; i++)
1594 matty 7 {
1595 matty 29 offset -= scanline;
1596     pcursor = &cursor[offset];
1597     pmask = &mask[offset];
1598    
1599     for (j = 0; j < scanline; j++)
1600 matty 28 {
1601 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1602     {
1603     if (xormask[0] || xormask[1] || xormask[2])
1604     {
1605     *pcursor |= (~(*andmask) & nextbit);
1606     *pmask |= nextbit;
1607     }
1608     else
1609     {
1610     *pcursor |= ((*andmask) & nextbit);
1611     *pmask |= (~(*andmask) & nextbit);
1612     }
1613    
1614     xormask += 3;
1615     }
1616    
1617     andmask++;
1618     pcursor++;
1619     pmask++;
1620 matty 28 }
1621 matty 7 }
1622 matty 29
1623     fg.red = fg.blue = fg.green = 0xffff;
1624     bg.red = bg.blue = bg.green = 0x0000;
1625     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1626    
1627     cursorglyph = ui_create_glyph(width, height, cursor);
1628     maskglyph = ui_create_glyph(width, height, mask);
1629    
1630 astrand 66 xcursor =
1631 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1632 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1633 astrand 64
1634 matty 29 ui_destroy_glyph(maskglyph);
1635     ui_destroy_glyph(cursorglyph);
1636     xfree(mask);
1637     xfree(cursor);
1638 astrand 64 return (HCURSOR) xcursor;
1639 matty 29 }
1640    
1641     void
1642     ui_set_cursor(HCURSOR cursor)
1643     {
1644 jsorg71 450 g_current_cursor = (Cursor) cursor;
1645     XDefineCursor(g_display, g_wnd, g_current_cursor);
1646 matty 29 }
1647    
1648     void
1649     ui_destroy_cursor(HCURSOR cursor)
1650     {
1651 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1652 matty 29 }
1653    
1654 astrand 508 void
1655     ui_set_null_cursor(void)
1656     {
1657     ui_set_cursor(g_null_cursor);
1658     }
1659    
1660 matty 29 #define MAKE_XCOLOR(xc,c) \
1661     (xc)->red = ((c)->red << 8) | (c)->red; \
1662     (xc)->green = ((c)->green << 8) | (c)->green; \
1663     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1664     (xc)->flags = DoRed | DoGreen | DoBlue;
1665    
1666 n-ki 279
1667 matty 29 HCOLOURMAP
1668 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1669 matty 29 {
1670     COLOURENTRY *entry;
1671     int i, ncolours = colours->ncolours;
1672 jsorg71 450 if (!g_owncolmap)
1673 matty 28 {
1674 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1675 n-ki 279 XColor xentry;
1676     XColor xc_cache[256];
1677     uint32 colour;
1678     int colLookup = 256;
1679     for (i = 0; i < ncolours; i++)
1680 matty 28 {
1681 n-ki 279 entry = &colours->colours[i];
1682     MAKE_XCOLOR(&xentry, entry);
1683 matty 7
1684 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1685 astrand 196 {
1686 n-ki 279 /* Allocation failed, find closest match. */
1687     int j = 256;
1688     int nMinDist = 3 * 256 * 256;
1689     long nDist = nMinDist;
1690 matty 28
1691 n-ki 279 /* only get the colors once */
1692     while (colLookup--)
1693 astrand 196 {
1694 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1695     xc_cache[colLookup].red = xc_cache[colLookup].green =
1696     xc_cache[colLookup].blue = 0;
1697     xc_cache[colLookup].flags = 0;
1698 jsorg71 450 XQueryColor(g_display,
1699     DefaultColormap(g_display,
1700     DefaultScreen(g_display)),
1701 n-ki 279 &xc_cache[colLookup]);
1702 n-ki 185 }
1703 n-ki 279 colLookup = 0;
1704    
1705     /* approximate the pixel */
1706     while (j--)
1707 astrand 196 {
1708 n-ki 279 if (xc_cache[j].flags)
1709     {
1710     nDist = ((long) (xc_cache[j].red >> 8) -
1711     (long) (xentry.red >> 8)) *
1712     ((long) (xc_cache[j].red >> 8) -
1713     (long) (xentry.red >> 8)) +
1714     ((long) (xc_cache[j].green >> 8) -
1715     (long) (xentry.green >> 8)) *
1716     ((long) (xc_cache[j].green >> 8) -
1717     (long) (xentry.green >> 8)) +
1718     ((long) (xc_cache[j].blue >> 8) -
1719     (long) (xentry.blue >> 8)) *
1720     ((long) (xc_cache[j].blue >> 8) -
1721     (long) (xentry.blue >> 8));
1722     }
1723     if (nDist < nMinDist)
1724     {
1725     nMinDist = nDist;
1726     xentry.pixel = j;
1727     }
1728 n-ki 185 }
1729     }
1730 n-ki 279 colour = xentry.pixel;
1731    
1732     /* update our cache */
1733     if (xentry.pixel < 256)
1734     {
1735     xc_cache[xentry.pixel].red = xentry.red;
1736     xc_cache[xentry.pixel].green = xentry.green;
1737     xc_cache[xentry.pixel].blue = xentry.blue;
1738    
1739     }
1740    
1741 matthewc 527 map[i] = colour;
1742 n-ki 185 }
1743 n-ki 279 return map;
1744     }
1745     else
1746     {
1747     XColor *xcolours, *xentry;
1748     Colormap map;
1749 matty 29
1750 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1751 n-ki 279 for (i = 0; i < ncolours; i++)
1752 astrand 196 {
1753 n-ki 279 entry = &colours->colours[i];
1754     xentry = &xcolours[i];
1755     xentry->pixel = i;
1756     MAKE_XCOLOR(xentry, entry);
1757 matty 29 }
1758    
1759 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1760     XStoreColors(g_display, map, xcolours, ncolours);
1761 n-ki 185
1762 n-ki 279 xfree(xcolours);
1763     return (HCOLOURMAP) map;
1764 matty 29 }
1765 matty 7 }
1766    
1767 matty 25 void
1768     ui_destroy_colourmap(HCOLOURMAP map)
1769 matty 7 {
1770 jsorg71 450 if (!g_owncolmap)
1771 n-ki 279 xfree(map);
1772     else
1773 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1774 matty 7 }
1775    
1776 matty 25 void
1777     ui_set_colourmap(HCOLOURMAP map)
1778 matty 7 {
1779 jsorg71 450 if (!g_owncolmap)
1780 astrand 448 {
1781 jsorg71 450 if (g_colmap)
1782     xfree(g_colmap);
1783 astrand 448
1784 jsorg71 450 g_colmap = (uint32 *) map;
1785 astrand 448 }
1786 n-ki 279 else
1787 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1788 matty 7 }
1789    
1790 matty 25 void
1791     ui_set_clip(int x, int y, int cx, int cy)
1792 matty 7 {
1793 matty 9 XRectangle rect;
1794 matty 7
1795 matty 9 rect.x = x;
1796     rect.y = y;
1797     rect.width = cx;
1798     rect.height = cy;
1799 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1800 matty 9 }
1801 matty 7
1802 matty 25 void
1803 matthewc 192 ui_reset_clip(void)
1804 matty 9 {
1805     XRectangle rect;
1806    
1807     rect.x = 0;
1808     rect.y = 0;
1809 jsorg71 447 rect.width = g_width;
1810     rect.height = g_height;
1811 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1812 matty 7 }
1813    
1814 matty 25 void
1815 matthewc 192 ui_bell(void)
1816 matty 10 {
1817 jsorg71 450 XBell(g_display, 0);
1818 matty 10 }
1819    
1820 matty 25 void
1821     ui_destblt(uint8 opcode,
1822     /* dest */ int x, int y, int cx, int cy)
1823 matty 9 {
1824 matty 29 SET_FUNCTION(opcode);
1825 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1826 matty 29 RESET_FUNCTION(opcode);
1827 matty 9 }
1828    
1829 jsorg71 373 static uint8 hatch_patterns[] = {
1830 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1831     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1832     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1833     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1834     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1835     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1836 jsorg71 373 };
1837    
1838 matty 25 void
1839     ui_patblt(uint8 opcode,
1840     /* dest */ int x, int y, int cx, int cy,
1841 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1842 matty 9 {
1843     Pixmap fill;
1844 jsorg71 59 uint8 i, ipattern[8];
1845 matty 9
1846 matty 29 SET_FUNCTION(opcode);
1847 matty 9
1848     switch (brush->style)
1849     {
1850 matty 24 case 0: /* Solid */
1851 matty 29 SET_FOREGROUND(fgcolour);
1852 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1853 matty 9 break;
1854    
1855 jsorg71 373 case 2: /* Hatch */
1856 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1857     hatch_patterns + brush->pattern[0] * 8);
1858 astrand 487 SET_FOREGROUND(fgcolour);
1859     SET_BACKGROUND(bgcolour);
1860 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1861     XSetStipple(g_display, g_gc, fill);
1862     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1863 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1864 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1865     XSetTSOrigin(g_display, g_gc, 0, 0);
1866 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1867     break;
1868    
1869 matty 24 case 3: /* Pattern */
1870 jsorg71 59 for (i = 0; i != 8; i++)
1871     ipattern[7 - i] = brush->pattern[i];
1872     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1873 matty 29 SET_FOREGROUND(bgcolour);
1874     SET_BACKGROUND(fgcolour);
1875 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1876     XSetStipple(g_display, g_gc, fill);
1877     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1878 jsorg71 680 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1879 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1880     XSetTSOrigin(g_display, g_gc, 0, 0);
1881 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1882 matty 9 break;
1883    
1884     default:
1885 matty 30 unimpl("brush %d\n", brush->style);
1886 matty 9 }
1887 matty 29
1888     RESET_FUNCTION(opcode);
1889 jsorg71 680
1890     if (g_ownbackstore)
1891     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1892 matty 9 }
1893    
1894 matty 25 void
1895     ui_screenblt(uint8 opcode,
1896     /* dest */ int x, int y, int cx, int cy,
1897     /* src */ int srcx, int srcy)
1898 matty 9 {
1899 matty 29 SET_FUNCTION(opcode);
1900 jsorg71 450 if (g_ownbackstore)
1901 stargo 609 {
1902 jsorg71 688 if (g_Unobscured)
1903     {
1904     XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1905 astrand 691 XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
1906     y);
1907 jsorg71 688 }
1908     else
1909     {
1910     XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1911 astrand 691 XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
1912     y);
1913 jsorg71 688 }
1914 stargo 609 }
1915     else
1916     {
1917     XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1918     }
1919 matty 29 RESET_FUNCTION(opcode);
1920 matty 9 }
1921    
1922 matty 25 void
1923     ui_memblt(uint8 opcode,
1924     /* dest */ int x, int y, int cx, int cy,
1925     /* src */ HBITMAP src, int srcx, int srcy)
1926 matty 9 {
1927 matty 29 SET_FUNCTION(opcode);
1928 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1929     if (g_ownbackstore)
1930     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1931 matty 29 RESET_FUNCTION(opcode);
1932 matty 9 }
1933    
1934 matty 25 void
1935     ui_triblt(uint8 opcode,
1936     /* dest */ int x, int y, int cx, int cy,
1937     /* src */ HBITMAP src, int srcx, int srcy,
1938 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1939 matty 9 {
1940     /* This is potentially difficult to do in general. Until someone
1941 matty 10 comes up with a more efficient way of doing it I am using cases. */
1942 matty 9
1943     switch (opcode)
1944     {
1945 matty 24 case 0x69: /* PDSxxn */
1946 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1947 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1948 matty 16 break;
1949    
1950 matty 24 case 0xb8: /* PSDPxax */
1951 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1952 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1953 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1954 matty 9 break;
1955    
1956 matty 29 case 0xc0: /* PSa */
1957 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1958 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1959 matty 28 break;
1960    
1961 matty 9 default:
1962 matty 30 unimpl("triblt 0x%x\n", opcode);
1963 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1964 matty 9 }
1965     }
1966    
1967 matty 25 void
1968     ui_line(uint8 opcode,
1969     /* dest */ int startx, int starty, int endx, int endy,
1970 astrand 64 /* pen */ PEN * pen)
1971 matty 9 {
1972 matty 29 SET_FUNCTION(opcode);
1973     SET_FOREGROUND(pen->colour);
1974 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1975     if (g_ownbackstore)
1976     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1977 matty 29 RESET_FUNCTION(opcode);
1978 matty 9 }
1979    
1980 matty 25 void
1981     ui_rect(
1982     /* dest */ int x, int y, int cx, int cy,
1983     /* brush */ int colour)
1984 matty 9 {
1985 matty 29 SET_FOREGROUND(colour);
1986 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1987 matty 9 }
1988    
1989 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1990 matty 25 void
1991     ui_draw_glyph(int mixmode,
1992     /* dest */ int x, int y, int cx, int cy,
1993 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1994     int bgcolour, int fgcolour)
1995 matty 9 {
1996 matty 29 SET_FOREGROUND(fgcolour);
1997     SET_BACKGROUND(bgcolour);
1998 matty 9
1999 jsorg71 450 XSetFillStyle(g_display, g_gc,
2000 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
2001 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
2002     XSetTSOrigin(g_display, g_gc, x, y);
2003 matty 9
2004 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
2005 matty 9
2006 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
2007 matty 9 }
2008    
2009 mmihalik 49 #define DO_GLYPH(ttext,idx) \
2010     {\
2011     glyph = cache_get_font (font, ttext[idx]);\
2012     if (!(flags & TEXT2_IMPLICIT_X))\
2013 jsorg71 564 {\
2014     xyoffset = ttext[++idx];\
2015     if ((xyoffset & 0x80))\
2016 mmihalik 49 {\
2017 jsorg71 564 if (flags & TEXT2_VERTICAL)\
2018     y += ttext[idx+1] | (ttext[idx+2] << 8);\
2019 mmihalik 49 else\
2020 jsorg71 564 x += ttext[idx+1] | (ttext[idx+2] << 8);\
2021     idx += 2;\
2022 mmihalik 49 }\
2023 jsorg71 564 else\
2024 mmihalik 49 {\
2025 jsorg71 564 if (flags & TEXT2_VERTICAL)\
2026     y += xyoffset;\
2027     else\
2028     x += xyoffset;\
2029 mmihalik 49 }\
2030 jsorg71 564 }\
2031     if (glyph != NULL)\
2032     {\
2033     x1 = x + glyph->offset;\
2034     y1 = y + glyph->baseline;\
2035     XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
2036     XSetTSOrigin(g_display, g_gc, x1, y1);\
2037     FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
2038     if (flags & TEXT2_IMPLICIT_X)\
2039     x += glyph->width;\
2040     }\
2041 mmihalik 49 }
2042    
2043 matty 25 void
2044     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
2045 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
2046     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
2047 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
2048 matty 9 {
2049 matty 10 FONTGLYPH *glyph;
2050 jsorg71 564 int i, j, xyoffset, x1, y1;
2051 mmihalik 49 DATABLOB *entry;
2052 matty 9
2053 matty 29 SET_FOREGROUND(bgcolour);
2054 matty 28
2055 astrand 620 /* Sometimes, the boxcx value is something really large, like
2056     32691. This makes XCopyArea fail with Xvnc. The code below
2057     is a quick fix. */
2058     if (boxx + boxcx > g_width)
2059     boxcx = g_width - boxx;
2060    
2061 matty 9 if (boxcx > 1)
2062 matty 31 {
2063 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
2064 matty 31 }
2065 matty 17 else if (mixmode == MIX_OPAQUE)
2066 matty 31 {
2067 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
2068 matty 31 }
2069 matty 9
2070 jsorg71 564 SET_FOREGROUND(fgcolour);
2071     SET_BACKGROUND(bgcolour);
2072     XSetFillStyle(g_display, g_gc, FillStippled);
2073    
2074 matty 9 /* Paint text, character by character */
2075 astrand 64 for (i = 0; i < length;)
2076     {
2077     switch (text[i])
2078     {
2079     case 0xff:
2080     if (i + 2 < length)
2081 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
2082 astrand 64 else
2083     {
2084     error("this shouldn't be happening\n");
2085 astrand 265 exit(1);
2086 astrand 64 }
2087     /* this will move pointer from start to first character after FF command */
2088     length -= i + 3;
2089     text = &(text[i + 3]);
2090     i = 0;
2091 mmihalik 49 break;
2092 matty 9
2093 astrand 64 case 0xfe:
2094     entry = cache_get_text(text[i + 1]);
2095     if (entry != NULL)
2096     {
2097     if ((((uint8 *) (entry->data))[1] ==
2098 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
2099 astrand 64 {
2100     if (flags & TEXT2_VERTICAL)
2101     y += text[i + 2];
2102     else
2103     x += text[i + 2];
2104     }
2105     for (j = 0; j < entry->size; j++)
2106 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
2107 matthewc 44 }
2108 jsorg71 286 if (i + 2 < length)
2109     i += 3;
2110     else
2111     i += 2;
2112     length -= i;
2113     /* this will move pointer from start to first character after FE command */
2114     text = &(text[i]);
2115     i = 0;
2116 astrand 64 break;
2117 matty 17
2118 astrand 64 default:
2119     DO_GLYPH(text, i);
2120     i++;
2121     break;
2122 matty 29 }
2123 mmihalik 49 }
2124 jsorg71 564
2125     XSetFillStyle(g_display, g_gc, FillSolid);
2126    
2127 jsorg71 450 if (g_ownbackstore)
2128 jsorg71 278 {
2129     if (boxcx > 1)
2130 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
2131 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
2132     else
2133 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
2134 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
2135     }
2136 matty 9 }
2137    
2138 matty 25 void
2139     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
2140 matty 9 {
2141 matty 28 Pixmap pix;
2142 matty 9 XImage *image;
2143    
2144 jsorg71 450 if (g_ownbackstore)
2145 matty 31 {
2146 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
2147 matty 31 }
2148     else
2149     {
2150 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
2151     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
2152     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
2153     XFreePixmap(g_display, pix);
2154 matty 31 }
2155 matty 28
2156 jsorg71 450 offset *= g_bpp / 8;
2157     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
2158 matty 28
2159     XDestroyImage(image);
2160 matty 9 }
2161    
2162 matty 25 void
2163     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2164 matty 9 {
2165     XImage *image;
2166 matty 10 uint8 *data;
2167 matty 9
2168 jsorg71 450 offset *= g_bpp / 8;
2169     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
2170 matty 10 if (data == NULL)
2171     return;
2172 matty 29
2173 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
2174     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
2175 matty 29
2176 jsorg71 450 if (g_ownbackstore)
2177 matty 31 {
2178 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
2179     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
2180 matty 31 }
2181     else
2182     {
2183 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
2184 matty 31 }
2185    
2186 matty 9 XFree(image);
2187     }
2188 jsorg71 713
2189     /* these do nothing here but are used in uiports */
2190     void
2191     ui_begin_update(void)
2192     {
2193     }
2194    
2195     void
2196     ui_end_update(void)
2197     {
2198     }

  ViewVC Help
Powered by ViewVC 1.1.26