/[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 801 - (hide annotations)
Tue Nov 23 13:29:12 2004 UTC (19 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 48545 byte(s)
Indent fixes

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 stargo 800 extern int g_xpos;
34     extern int g_ypos;
35 jsorg71 447 extern BOOL g_sendmotion;
36     extern BOOL g_fullscreen;
37 jsorg71 450 extern BOOL g_grab_keyboard;
38     extern BOOL g_hide_decorations;
39     extern char g_title[];
40 jsorg71 438 extern int g_server_bpp;
41 jsorg71 450 extern int g_win_button_size;
42 matty 10
43 jsorg71 450 Display *g_display;
44     Time g_last_gesturetime;
45     static int g_x_socket;
46     static Screen *g_screen;
47     Window g_wnd;
48 stargo 648 extern uint32 g_embed_wnd;
49 matthewc 481 BOOL g_enable_compose = False;
50 astrand 691 BOOL g_Unobscured; /* used for screenblt */
51 stargo 576 static GC g_gc = NULL;
52 jsorg71 725 static GC g_create_bitmap_gc = NULL;
53     static GC g_create_glyph_gc = NULL;
54 jsorg71 450 static Visual *g_visual;
55     static int g_depth;
56     static int g_bpp;
57     static XIM g_IM;
58     static XIC g_IC;
59     static XModifierKeymap *g_mod_map;
60     static Cursor g_current_cursor;
61 stargo 576 static HCURSOR g_null_cursor = NULL;
62 jsorg71 450 static Atom g_protocol_atom, g_kill_atom;
63 matthewc 481 static BOOL g_focused;
64     static BOOL g_mouse_in_wnd;
65 astrand 651 static BOOL g_arch_match = False; /* set to True if RGB XServer and little endian */
66 matty 29
67 matty 33 /* endianness */
68 jsorg71 450 static BOOL g_host_be;
69     static BOOL g_xserver_be;
70 matthewc 527 static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
71     static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
72 matty 33
73     /* software backing store */
74 stargo 648 extern BOOL g_ownbackstore;
75 stargo 603 static Pixmap g_backstore = 0;
76 matty 31
77 astrand 342 /* Moving in single app mode */
78 jsorg71 450 static BOOL g_moving_wnd;
79     static int g_move_x_offset = 0;
80     static int g_move_y_offset = 0;
81 astrand 342
82 matthewc 474 #ifdef WITH_RDPSND
83     extern int g_dsp_fd;
84     extern BOOL g_dsp_busy;
85 stargo 501 extern BOOL g_rdpsnd;
86 matthewc 474 #endif
87    
88 astrand 262 /* MWM decorations */
89     #define MWM_HINTS_DECORATIONS (1L << 1)
90     #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
91     typedef struct
92     {
93 matthewc 301 uint32 flags;
94     uint32 functions;
95     uint32 decorations;
96     sint32 inputMode;
97     uint32 status;
98 astrand 262 }
99     PropMotifWmHints;
100    
101 jsorg71 316 typedef struct
102     {
103     uint32 red;
104     uint32 green;
105     uint32 blue;
106     }
107     PixelColour;
108 astrand 262
109 forsberg 415
110 matty 31 #define FILL_RECTANGLE(x,y,cx,cy)\
111     { \
112 jsorg71 450 XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
113     if (g_ownbackstore) \
114     XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
115 matty 31 }
116    
117 matthewc 296 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
118 jsorg71 281 { \
119 jsorg71 450 XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
120 jsorg71 281 }
121    
122 matty 33 /* colour maps */
123 stargo 648 extern BOOL g_owncolmap;
124 jsorg71 450 static Colormap g_xcolmap;
125     static uint32 *g_colmap = NULL;
126 matty 10
127 matthewc 527 #define TRANSLATE(col) ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
128 jsorg71 450 #define SET_FOREGROUND(col) XSetForeground(g_display, g_gc, TRANSLATE(col));
129     #define SET_BACKGROUND(col) XSetBackground(g_display, g_gc, TRANSLATE(col));
130 matty 28
131     static int rop2_map[] = {
132     GXclear, /* 0 */
133     GXnor, /* DPon */
134     GXandInverted, /* DPna */
135     GXcopyInverted, /* Pn */
136     GXandReverse, /* PDna */
137     GXinvert, /* Dn */
138     GXxor, /* DPx */
139     GXnand, /* DPan */
140     GXand, /* DPa */
141     GXequiv, /* DPxn */
142     GXnoop, /* D */
143     GXorInverted, /* DPno */
144     GXcopy, /* P */
145     GXorReverse, /* PDno */
146     GXor, /* DPo */
147     GXset /* 1 */
148     };
149    
150 jsorg71 450 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
151     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
152 matty 29
153 astrand 319 static void
154 astrand 262 mwm_hide_decorations(void)
155     {
156     PropMotifWmHints motif_hints;
157     Atom hintsatom;
158    
159     /* setup the property */
160     motif_hints.flags = MWM_HINTS_DECORATIONS;
161     motif_hints.decorations = 0;
162    
163     /* get the atom for the property */
164 jsorg71 450 hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
165 astrand 262 if (!hintsatom)
166     {
167 matthewc 297 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
168 astrand 262 return;
169     }
170    
171 jsorg71 450 XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
172 astrand 262 (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
173     }
174    
175 astrand 319 static PixelColour
176 jsorg71 316 split_colour15(uint32 colour)
177 jsorg71 311 {
178 jsorg71 316 PixelColour rv;
179 astrand 706 rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7);
180 stargo 704 rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7);
181 astrand 706 rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);
182 jsorg71 316 return rv;
183 jsorg71 311 }
184    
185 astrand 319 static PixelColour
186 jsorg71 316 split_colour16(uint32 colour)
187 jsorg71 311 {
188 jsorg71 316 PixelColour rv;
189 astrand 706 rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7);
190 stargo 704 rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3);
191 astrand 706 rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7);
192 jsorg71 316 return rv;
193 jsorg71 311 }
194    
195 astrand 319 static PixelColour
196 jsorg71 316 split_colour24(uint32 colour)
197 jsorg71 311 {
198 jsorg71 316 PixelColour rv;
199 astrand 619 rv.blue = (colour & 0xff0000) >> 16;
200 jsorg71 617 rv.green = (colour & 0x00ff00) >> 8;
201 astrand 619 rv.red = (colour & 0x0000ff);
202 jsorg71 316 return rv;
203 jsorg71 311 }
204    
205 astrand 319 static uint32
206 matthewc 527 make_colour(PixelColour pc)
207 jsorg71 316 {
208 matthewc 527 return (((pc.red >> g_red_shift_r) << g_red_shift_l)
209     | ((pc.green >> g_green_shift_r) << g_green_shift_l)
210     | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l));
211 jsorg71 316 }
212    
213 jsorg71 311 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
214 stargo 534 #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
215 jsorg71 311 #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
216     x = (x << 16) | (x >> 16); }
217    
218     static uint32
219     translate_colour(uint32 colour)
220     {
221 matthewc 527 PixelColour pc;
222 jsorg71 438 switch (g_server_bpp)
223 jsorg71 311 {
224 jsorg71 316 case 15:
225 matthewc 527 pc = split_colour15(colour);
226 jsorg71 316 break;
227 jsorg71 311 case 16:
228 matthewc 527 pc = split_colour16(colour);
229 jsorg71 311 break;
230     case 24:
231 matthewc 527 pc = split_colour24(colour);
232 jsorg71 311 break;
233     }
234 matthewc 527 return make_colour(pc);
235 jsorg71 311 }
236    
237 jsorg71 709 /* indent is confused by UNROLL8 */
238     /* *INDENT-OFF* */
239    
240     /* repeat and unroll, similar to bitmap.c */
241     /* potentialy any of the following translate */
242     /* functions can use repeat but just doing */
243     /* the most common ones */
244    
245 jsorg71 679 #define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
246 jsorg71 709 /* 2 byte output repeat */
247     #define REPEAT2(stm) \
248 jsorg71 679 { \
249 jsorg71 709 while (out <= end - 8 * 2) \
250     UNROLL8(stm) \
251     while (out < end) \
252     { stm } \
253     }
254     /* 4 byte output repeat */
255     #define REPEAT4(stm) \
256     { \
257 jsorg71 679 while (out <= end - 8 * 4) \
258     UNROLL8(stm) \
259     while (out < end) \
260     { stm } \
261     }
262    
263 matty 28 static void
264 jsorg71 311 translate8to8(uint8 * data, uint8 * out, uint8 * end)
265 matty 28 {
266 matty 29 while (out < end)
267 jsorg71 450 *(out++) = (uint8) g_colmap[*(data++)];
268 matty 29 }
269 matty 28
270 matty 29 static void
271 stargo 521 translate8to16(uint8 * data, uint8 * out, uint8 * end)
272 matty 29 {
273 stargo 521 uint16 value;
274    
275 jsorg71 679 if (g_arch_match)
276 stargo 521 {
277 jsorg71 709 REPEAT2
278     (
279     *((uint16 *) out) = g_colmap[*(data++)];
280     out += 2;
281     )
282 jsorg71 643 }
283 jsorg71 709 else if (g_xserver_be)
284 jsorg71 643 {
285 jsorg71 709 while (out < end)
286     {
287     value = (uint16) g_colmap[*(data++)];
288     *(out++) = value >> 8;
289     *(out++) = value;
290     }
291 stargo 521 }
292 jsorg71 709 else
293     {
294     while (out < end)
295     {
296     value = (uint16) g_colmap[*(data++)];
297     *(out++) = value;
298     *(out++) = value >> 8;
299     }
300     }
301 matty 29 }
302    
303 jsorg71 316 /* little endian - conversion happens when colourmap is built */
304 jsorg71 311 static void
305 jsorg71 316 translate8to24(uint8 * data, uint8 * out, uint8 * end)
306 jsorg71 311 {
307 jsorg71 316 uint32 value;
308    
309 jsorg71 643 if (g_xserver_be)
310 jsorg71 316 {
311 jsorg71 643 while (out < end)
312 stargo 521 {
313 jsorg71 643 value = g_colmap[*(data++)];
314 stargo 521 *(out++) = value >> 16;
315     *(out++) = value >> 8;
316     *(out++) = value;
317     }
318 jsorg71 643 }
319     else
320     {
321     while (out < end)
322 stargo 521 {
323 jsorg71 643 value = g_colmap[*(data++)];
324 stargo 521 *(out++) = value;
325     *(out++) = value >> 8;
326     *(out++) = value >> 16;
327     }
328 jsorg71 316 }
329 jsorg71 311 }
330    
331 matty 29 static void
332 stargo 521 translate8to32(uint8 * data, uint8 * out, uint8 * end)
333 matty 29 {
334 stargo 521 uint32 value;
335    
336 jsorg71 679 if (g_arch_match)
337 stargo 521 {
338 jsorg71 709 REPEAT4
339     (
340     *((uint32 *) out) = g_colmap[*(data++)];
341     out += 4;
342     )
343 jsorg71 643 }
344 jsorg71 709 else if (g_xserver_be)
345 jsorg71 643 {
346 jsorg71 709 while (out < end)
347     {
348     value = g_colmap[*(data++)];
349     *(out++) = value >> 24;
350     *(out++) = value >> 16;
351     *(out++) = value >> 8;
352     *(out++) = value;
353     }
354 stargo 521 }
355 jsorg71 709 else
356     {
357     while (out < end)
358     {
359     value = g_colmap[*(data++)];
360     *(out++) = value;
361     *(out++) = value >> 8;
362     *(out++) = value >> 16;
363     *(out++) = value >> 24;
364     }
365     }
366 jsorg71 316 }
367    
368 jsorg71 709 /* *INDENT-ON* */
369    
370 jsorg71 316 static void
371 jsorg71 483 translate15to16(uint16 * data, uint8 * out, uint8 * end)
372 jsorg71 316 {
373 jsorg71 483 uint16 pixel;
374     uint16 value;
375    
376 jsorg71 316 while (out < end)
377 jsorg71 483 {
378     pixel = *(data++);
379    
380     if (g_host_be)
381     {
382 stargo 521 BSWAP16(pixel);
383     }
384 jsorg71 483
385 matthewc 527 value = make_colour(split_colour15(pixel));
386 jsorg71 483
387     if (g_xserver_be)
388     {
389     *(out++) = value >> 8;
390     *(out++) = value;
391     }
392     else
393     {
394     *(out++) = value;
395     *(out++) = value >> 8;
396     }
397     }
398 jsorg71 316 }
399    
400     static void
401     translate15to24(uint16 * data, uint8 * out, uint8 * end)
402     {
403 matty 29 uint32 value;
404 jsorg71 483 uint16 pixel;
405 matty 29
406     while (out < end)
407 matty 28 {
408 jsorg71 483 pixel = *(data++);
409    
410     if (g_host_be)
411     {
412 stargo 521 BSWAP16(pixel);
413     }
414 jsorg71 483
415 matthewc 527 value = make_colour(split_colour15(pixel));
416 jsorg71 483 if (g_xserver_be)
417     {
418     *(out++) = value >> 16;
419     *(out++) = value >> 8;
420     *(out++) = value;
421     }
422     else
423     {
424     *(out++) = value;
425     *(out++) = value >> 8;
426     *(out++) = value >> 16;
427     }
428 matty 28 }
429     }
430    
431     static void
432 jsorg71 483 translate15to32(uint16 * data, uint8 * out, uint8 * end)
433 jsorg71 316 {
434 jsorg71 472 uint16 pixel;
435 jsorg71 483 uint32 value;
436 jsorg71 472
437 jsorg71 316 while (out < end)
438 jsorg71 472 {
439 jsorg71 483 pixel = *(data++);
440    
441 jsorg71 472 if (g_host_be)
442     {
443 jsorg71 483 BSWAP16(pixel);
444 jsorg71 472 }
445 jsorg71 483
446 matthewc 527 value = make_colour(split_colour15(pixel));
447 jsorg71 483
448     if (g_xserver_be)
449     {
450     *(out++) = value >> 24;
451     *(out++) = value >> 16;
452     *(out++) = value >> 8;
453     *(out++) = value;
454     }
455 jsorg71 472 else
456     {
457 jsorg71 483 *(out++) = value;
458     *(out++) = value >> 8;
459     *(out++) = value >> 16;
460     *(out++) = value >> 24;
461 jsorg71 472 }
462     }
463 jsorg71 316 }
464    
465     static void
466 matthewc 528 translate16to16(uint16 * data, uint8 * out, uint8 * end)
467 jsorg71 316 {
468 matthewc 528 uint16 pixel;
469 jsorg71 483 uint16 value;
470    
471 matthewc 528 while (out < end)
472 jsorg71 483 {
473 matthewc 528 pixel = *(data++);
474    
475     if (g_host_be)
476 jsorg71 483 {
477 matthewc 528 BSWAP16(pixel);
478 jsorg71 483 }
479    
480 matthewc 528 value = make_colour(split_colour16(pixel));
481    
482     if (g_xserver_be)
483 jsorg71 483 {
484 matthewc 528 *(out++) = value >> 8;
485     *(out++) = value;
486 jsorg71 483 }
487 matthewc 528 else
488     {
489     *(out++) = value;
490     *(out++) = value >> 8;
491     }
492 jsorg71 483 }
493 jsorg71 316 }
494    
495     static void
496 jsorg71 311 translate16to24(uint16 * data, uint8 * out, uint8 * end)
497 matty 28 {
498 jsorg71 311 uint32 value;
499 jsorg71 483 uint16 pixel;
500 jsorg71 311
501 matty 29 while (out < end)
502 jsorg71 311 {
503 jsorg71 483 pixel = *(data++);
504    
505     if (g_host_be)
506     {
507 stargo 521 BSWAP16(pixel);
508     }
509 jsorg71 483
510 matthewc 527 value = make_colour(split_colour16(pixel));
511 jsorg71 483
512     if (g_xserver_be)
513     {
514     *(out++) = value >> 16;
515     *(out++) = value >> 8;
516     *(out++) = value;
517     }
518     else
519     {
520     *(out++) = value;
521     *(out++) = value >> 8;
522     *(out++) = value >> 16;
523     }
524 jsorg71 311 }
525     }
526    
527     static void
528 jsorg71 483 translate16to32(uint16 * data, uint8 * out, uint8 * end)
529 jsorg71 311 {
530 jsorg71 472 uint16 pixel;
531 jsorg71 483 uint32 value;
532 jsorg71 472
533 jsorg71 311 while (out < end)
534 jsorg71 472 {
535 jsorg71 483 pixel = *(data++);
536    
537 jsorg71 472 if (g_host_be)
538     {
539 stargo 534 BSWAP16(pixel);
540     }
541 jsorg71 483
542 matthewc 527 value = make_colour(split_colour16(pixel));
543 jsorg71 483
544     if (g_xserver_be)
545 jsorg71 472 {
546 jsorg71 483 *(out++) = value >> 24;
547     *(out++) = value >> 16;
548     *(out++) = value >> 8;
549     *(out++) = value;
550 astrand 499 }
551     else
552     {
553 jsorg71 483 *(out++) = value;
554     *(out++) = value >> 8;
555     *(out++) = value >> 16;
556     *(out++) = value >> 24;
557 astrand 499 }
558     }
559 matty 28 }
560    
561 jsorg71 311 static void
562 jsorg71 483 translate24to16(uint8 * data, uint8 * out, uint8 * end)
563 jsorg71 311 {
564 jsorg71 316 uint32 pixel = 0;
565 jsorg71 483 uint16 value;
566 jsorg71 311 while (out < end)
567 jsorg71 316 {
568     pixel = *(data++) << 16;
569     pixel |= *(data++) << 8;
570     pixel |= *(data++);
571 jsorg71 483
572 matthewc 527 value = (uint16) make_colour(split_colour24(pixel));
573 jsorg71 483
574     if (g_xserver_be)
575     {
576     *(out++) = value >> 8;
577     *(out++) = value;
578     }
579     else
580     {
581     *(out++) = value;
582     *(out++) = value >> 8;
583     }
584 jsorg71 316 }
585 jsorg71 311 }
586    
587 jsorg71 316 static void
588     translate24to24(uint8 * data, uint8 * out, uint8 * end)
589     {
590 stargo 534 uint32 pixel;
591     uint32 value;
592    
593 jsorg71 316 while (out < end)
594     {
595 stargo 534 pixel = *(data++) << 16;
596     pixel |= *(data++) << 8;
597     pixel |= *(data++);
598    
599     value = make_colour(split_colour24(pixel));
600 astrand 542
601 stargo 534 if (g_xserver_be)
602     {
603     *(out++) = value >> 16;
604     *(out++) = value >> 8;
605     *(out++) = value;
606     }
607     else
608     {
609     *(out++) = value;
610     *(out++) = value >> 8;
611     *(out++) = value >> 16;
612     }
613 jsorg71 316 }
614     }
615    
616     static void
617 jsorg71 483 translate24to32(uint8 * data, uint8 * out, uint8 * end)
618 jsorg71 316 {
619 stargo 534 uint32 pixel;
620     uint32 value;
621    
622 jsorg71 316 while (out < end)
623     {
624 stargo 534 pixel = *(data++) << 16;
625     pixel |= *(data++) << 8;
626     pixel |= *(data++);
627    
628     value = make_colour(split_colour24(pixel));
629    
630 jsorg71 483 if (g_xserver_be)
631 jsorg71 472 {
632 stargo 534 *(out++) = value >> 24;
633     *(out++) = value >> 16;
634     *(out++) = value >> 8;
635     *(out++) = value;
636 jsorg71 472 }
637     else
638     {
639 stargo 534 *(out++) = value;
640     *(out++) = value >> 8;
641     *(out++) = value >> 16;
642     *(out++) = value >> 24;
643 jsorg71 472 }
644 jsorg71 316 }
645     }
646    
647 matty 29 static uint8 *
648 astrand 64 translate_image(int width, int height, uint8 * data)
649 matty 28 {
650 jsorg71 644 int size;
651     uint8 *out;
652     uint8 *end;
653 matty 29
654 jsorg71 644 /* if server and xserver bpp match, */
655     /* and arch(endian) matches, no need to translate */
656     /* just return data */
657 jsorg71 645 if (g_arch_match)
658     {
659     if (g_depth == 15 && g_server_bpp == 15)
660     return data;
661     if (g_depth == 16 && g_server_bpp == 16)
662     return data;
663     }
664 jsorg71 644
665     size = width * height * (g_bpp / 8);
666     out = (uint8 *) xmalloc(size);
667     end = out + size;
668    
669 jsorg71 438 switch (g_server_bpp)
670 jsorg71 311 {
671 jsorg71 316 case 24:
672 jsorg71 450 switch (g_bpp)
673 jsorg71 316 {
674     case 32:
675 jsorg71 483 translate24to32(data, out, end);
676 jsorg71 316 break;
677     case 24:
678     translate24to24(data, out, end);
679     break;
680     case 16:
681 jsorg71 483 translate24to16(data, out, end);
682 jsorg71 316 break;
683     }
684 matty 29 break;
685     case 16:
686 jsorg71 450 switch (g_bpp)
687 jsorg71 316 {
688     case 32:
689 jsorg71 483 translate16to32((uint16 *) data, out, end);
690 jsorg71 316 break;
691     case 24:
692     translate16to24((uint16 *) data, out, end);
693     break;
694     case 16:
695 matthewc 528 translate16to16((uint16 *) data, out, end);
696 jsorg71 316 break;
697     }
698 matty 29 break;
699 jsorg71 316 case 15:
700 jsorg71 450 switch (g_bpp)
701 jsorg71 316 {
702     case 32:
703 jsorg71 483 translate15to32((uint16 *) data, out, end);
704 jsorg71 316 break;
705     case 24:
706     translate15to24((uint16 *) data, out, end);
707     break;
708     case 16:
709 jsorg71 483 translate15to16((uint16 *) data, out, end);
710 jsorg71 316 break;
711     }
712 matty 29 break;
713 jsorg71 316 case 8:
714 jsorg71 450 switch (g_bpp)
715 jsorg71 316 {
716     case 8:
717     translate8to8(data, out, end);
718     break;
719     case 16:
720 stargo 521 translate8to16(data, out, end);
721 jsorg71 316 break;
722     case 24:
723     translate8to24(data, out, end);
724     break;
725     case 32:
726 stargo 521 translate8to32(data, out, end);
727 jsorg71 316 break;
728     }
729 matty 29 break;
730     }
731     return out;
732 matty 28 }
733    
734 astrand 118 BOOL
735 matthewc 209 get_key_state(unsigned int state, uint32 keysym)
736 astrand 102 {
737 matthewc 203 int modifierpos, key, keysymMask = 0;
738 astrand 102 int offset;
739    
740 jsorg71 450 KeyCode keycode = XKeysymToKeycode(g_display, keysym);
741 astrand 102
742     if (keycode == NoSymbol)
743     return False;
744    
745     for (modifierpos = 0; modifierpos < 8; modifierpos++)
746     {
747 jsorg71 450 offset = g_mod_map->max_keypermod * modifierpos;
748 astrand 102
749 jsorg71 450 for (key = 0; key < g_mod_map->max_keypermod; key++)
750 astrand 102 {
751 jsorg71 450 if (g_mod_map->modifiermap[offset + key] == keycode)
752 matthewc 203 keysymMask |= 1 << modifierpos;
753 astrand 102 }
754     }
755    
756 matthewc 203 return (state & keysymMask) ? True : False;
757 astrand 102 }
758    
759 matthewc 527 static void
760     calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
761     {
762     *shift_l = ffs(mask) - 1;
763     mask >>= *shift_l;
764     *shift_r = 8 - ffs(mask & ~(mask >> 1));
765     }
766    
767 jsorg71 81 BOOL
768 matthewc 192 ui_init(void)
769 jsorg71 81 {
770 matthewc 527 XVisualInfo vi;
771 matthewc 121 XPixmapFormatValues *pfm;
772     uint16 test;
773 stargo 565 int i, screen_num, nvisuals;
774     XVisualInfo *vmatches = NULL;
775     XVisualInfo template;
776     Bool TrueColorVisual = False;
777 matthewc 121
778 jsorg71 450 g_display = XOpenDisplay(NULL);
779     if (g_display == NULL)
780 jsorg71 81 {
781 matthewc 210 error("Failed to open display: %s\n", XDisplayName(NULL));
782 jsorg71 81 return False;
783     }
784 matthewc 121
785 matthewc 527 screen_num = DefaultScreen(g_display);
786 jsorg71 450 g_x_socket = ConnectionNumber(g_display);
787 matthewc 527 g_screen = ScreenOfDisplay(g_display, screen_num);
788 jsorg71 450 g_depth = DefaultDepthOfScreen(g_screen);
789 matthewc 121
790 stargo 565 /* Search for best TrueColor depth */
791     template.class = TrueColor;
792     vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);
793    
794     nvisuals--;
795     while (nvisuals >= 0)
796 matthewc 527 {
797 stargo 565 if ((vmatches + nvisuals)->depth > g_depth)
798     {
799     g_depth = (vmatches + nvisuals)->depth;
800     }
801     nvisuals--;
802     TrueColorVisual = True;
803     }
804    
805 jsorg71 644 test = 1;
806     g_host_be = !(BOOL) (*(uint8 *) (&test));
807     g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
808    
809 astrand 580 if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))
810 stargo 565 {
811     /* we use a colourmap, so the default visual should do */
812 matthewc 527 g_visual = DefaultVisualOfScreen(g_screen);
813 stargo 565 g_depth = DefaultDepthOfScreen(g_screen);
814    
815     /* Do not allocate colours on a TrueColor visual */
816     if (g_visual->class == TrueColor)
817     {
818     g_owncolmap = False;
819     }
820 matthewc 527 }
821     else
822     {
823     /* need a truecolour visual */
824     if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))
825     {
826     error("The display does not support true colour - high colour support unavailable.\n");
827     return False;
828     }
829    
830     g_visual = vi.visual;
831     g_owncolmap = False;
832 astrand 532 calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);
833     calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);
834 matthewc 527 calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);
835 jsorg71 644
836     /* if RGB video and averything is little endian */
837     if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask)
838     if (!g_xserver_be && !g_host_be)
839     g_arch_match = True;
840 matthewc 527 }
841    
842 jsorg71 450 pfm = XListPixmapFormats(g_display, &i);
843 matthewc 121 if (pfm != NULL)
844     {
845     /* Use maximum bpp for this depth - this is generally
846     desirable, e.g. 24 bits->32 bits. */
847     while (i--)
848     {
849 jsorg71 450 if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
850 matthewc 121 {
851 jsorg71 450 g_bpp = pfm[i].bits_per_pixel;
852 matthewc 121 }
853     }
854     XFree(pfm);
855     }
856    
857 jsorg71 450 if (g_bpp < 8)
858 matthewc 121 {
859     error("Less than 8 bpp not currently supported.\n");
860 jsorg71 450 XCloseDisplay(g_display);
861 matthewc 121 return False;
862     }
863    
864 matthewc 517 if (!g_owncolmap)
865 n-ki 279 {
866 astrand 580 g_xcolmap =
867     XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
868     AllocNone);
869 jsorg71 450 if (g_depth <= 8)
870 matthewc 297 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
871 n-ki 279 }
872    
873 stargo 609 if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
874     {
875     warning("External BackingStore not available, using internal\n");
876 jsorg71 450 g_ownbackstore = True;
877 stargo 609 }
878 matthewc 121
879 astrand 500 /*
880     * Determine desktop size
881     */
882 astrand 547 if (g_fullscreen)
883 astrand 263 {
884 astrand 547 g_width = WidthOfScreen(g_screen);
885     g_height = HeightOfScreen(g_screen);
886     }
887     else if (g_width < 0)
888     {
889 astrand 500 /* Percent of screen */
890     g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
891     g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
892     }
893     else if (g_width == 0)
894     {
895 astrand 263 /* Fetch geometry from _NET_WORKAREA */
896 matthewc 300 uint32 x, y, cx, cy;
897 astrand 263
898 matthewc 300 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
899 astrand 263 {
900 jsorg71 447 g_width = cx;
901     g_height = cy;
902 matthewc 300 }
903     else
904     {
905 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
906 jsorg71 447 g_width = 800;
907     g_height = 600;
908 astrand 263 }
909     }
910 matthewc 121
911 matthewc 160 /* make sure width is a multiple of 4 */
912 jsorg71 447 g_width = (g_width + 3) & ~3;
913 matthewc 160
914 jsorg71 450 g_mod_map = XGetModifierMapping(g_display);
915 matthewc 203
916 astrand 498 xkeymap_init();
917    
918 jsorg71 447 if (g_enable_compose)
919 jsorg71 450 g_IM = XOpenIM(g_display, NULL, NULL, NULL);
920 matthewc 188
921 matthewc 432 xclip_init();
922 jsorg71 316
923 matthewc 519 DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));
924 jsorg71 316
925 jsorg71 81 return True;
926     }
927 astrand 66
928 matthewc 188 void
929 matthewc 192 ui_deinit(void)
930 matthewc 188 {
931 jsorg71 450 if (g_IM != NULL)
932     XCloseIM(g_IM);
933 astrand 580
934 stargo 576 if (g_null_cursor != NULL)
935     ui_destroy_cursor(g_null_cursor);
936 matthewc 188
937 jsorg71 450 XFreeModifiermap(g_mod_map);
938 matthewc 203
939 jsorg71 450 if (g_ownbackstore)
940     XFreePixmap(g_display, g_backstore);
941 matthewc 188
942 jsorg71 450 XFreeGC(g_display, g_gc);
943     XCloseDisplay(g_display);
944     g_display = NULL;
945 matthewc 188 }
946    
947 matthewc 121 BOOL
948 matthewc 192 ui_create_window(void)
949 matty 6 {
950 matthewc 536 uint8 null_pointer_mask[1] = { 0x80 };
951 astrand 788 uint8 null_pointer_data[24] = { 0x00 };
952    
953 matthewc 121 XSetWindowAttributes attribs;
954 matty 28 XClassHint *classhints;
955     XSizeHints *sizehints;
956 matthewc 188 int wndwidth, wndheight;
957 matthewc 432 long input_mask, ic_input_mask;
958 jsorg71 100 XEvent xevent;
959    
960 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
961     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
962 matthewc 188
963 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
964 stargo 565 attribs.border_pixel = WhitePixelOfScreen(g_screen);
965 jsorg71 450 attribs.backing_store = g_ownbackstore ? NotUseful : Always;
966 jsorg71 447 attribs.override_redirect = g_fullscreen;
967 stargo 565 attribs.colormap = g_xcolmap;
968 matthewc 188
969 astrand 801 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
970     wndheight, 0, g_depth, InputOutput, g_visual,
971     CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
972     CWBorderPixel, &attribs);
973 jsorg71 100
974 stargo 576 if (g_gc == NULL)
975 stargo 566 g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
976 stargo 565
977 jsorg71 725 if (g_create_bitmap_gc == NULL)
978     g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
979    
980 stargo 603 if ((g_ownbackstore) && (g_backstore == 0))
981 stargo 565 {
982 astrand 580 g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
983 stargo 565
984     /* clear to prevent rubbish being exposed at startup */
985     XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
986     XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
987     }
988    
989 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
990 jsorg71 100
991 jsorg71 450 if (g_hide_decorations)
992 astrand 262 mwm_hide_decorations();
993    
994 jsorg71 100 classhints = XAllocClassHint();
995     if (classhints != NULL)
996     {
997     classhints->res_name = classhints->res_class = "rdesktop";
998 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
999 jsorg71 100 XFree(classhints);
1000     }
1001    
1002     sizehints = XAllocSizeHints();
1003     if (sizehints)
1004     {
1005     sizehints->flags = PMinSize | PMaxSize;
1006 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
1007     sizehints->min_height = sizehints->max_height = g_height;
1008 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
1009 jsorg71 100 XFree(sizehints);
1010     }
1011    
1012 astrand 651 if (g_embed_wnd)
1013     {
1014     XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
1015     }
1016 stargo 636
1017 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1018 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
1019 matthewc 121
1020 jsorg71 447 if (g_sendmotion)
1021 matthewc 121 input_mask |= PointerMotionMask;
1022 jsorg71 450 if (g_ownbackstore)
1023 matthewc 121 input_mask |= ExposureMask;
1024 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
1025 matthewc 250 input_mask |= EnterWindowMask;
1026 jsorg71 450 if (g_grab_keyboard)
1027 jsorg71 257 input_mask |= LeaveWindowMask;
1028 jsorg71 100
1029 jsorg71 450 if (g_IM != NULL)
1030 matthewc 188 {
1031 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
1032 astrand 456 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
1033 matthewc 188
1034 jsorg71 450 if ((g_IC != NULL)
1035     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
1036 matthewc 188 input_mask |= ic_input_mask;
1037     }
1038    
1039 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
1040     XMapWindow(g_display, g_wnd);
1041 jsorg71 100
1042 matthewc 208 /* wait for VisibilityNotify */
1043 astrand 196 do
1044     {
1045 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
1046 astrand 196 }
1047 matthewc 208 while (xevent.type != VisibilityNotify);
1048 jsorg71 688 g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1049 matthewc 123
1050 jsorg71 447 g_focused = False;
1051     g_mouse_in_wnd = False;
1052 jsorg71 257
1053 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
1054 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
1055     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
1056     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
1057 astrand 275
1058 astrand 508 /* create invisible 1x1 cursor to be used as null cursor */
1059 stargo 576 if (g_null_cursor == NULL)
1060     g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data);
1061 astrand 508
1062 matty 10 return True;
1063 matty 6 }
1064    
1065 matty 25 void
1066 n-ki 677 ui_resize_window()
1067     {
1068     XSizeHints *sizehints;
1069 jsorg71 708 Pixmap bs;
1070 n-ki 677
1071     sizehints = XAllocSizeHints();
1072     if (sizehints)
1073     {
1074     sizehints->flags = PMinSize | PMaxSize;
1075     sizehints->min_width = sizehints->max_width = g_width;
1076     sizehints->min_height = sizehints->max_height = g_height;
1077     XSetWMNormalHints(g_display, g_wnd, sizehints);
1078     XFree(sizehints);
1079     }
1080    
1081     if (!(g_fullscreen || g_embed_wnd))
1082     {
1083     XResizeWindow(g_display, g_wnd, g_width, g_height);
1084     }
1085 jsorg71 708
1086     /* create new backstore pixmap */
1087     if (g_backstore != 0)
1088     {
1089     bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1090     XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
1091     XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
1092     XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
1093     XFreePixmap(g_display, g_backstore);
1094     g_backstore = bs;
1095     }
1096 n-ki 677 }
1097    
1098     void
1099 matthewc 192 ui_destroy_window(void)
1100 matty 6 {
1101 jsorg71 450 if (g_IC != NULL)
1102     XDestroyIC(g_IC);
1103 matty 31
1104 jsorg71 450 XDestroyWindow(g_display, g_wnd);
1105 matty 6 }
1106    
1107 jsorg71 100 void
1108 matthewc 192 xwin_toggle_fullscreen(void)
1109 jsorg71 100 {
1110 matthewc 188 Pixmap contents = 0;
1111 matthewc 123
1112 jsorg71 450 if (!g_ownbackstore)
1113 matthewc 188 {
1114     /* need to save contents of window */
1115 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
1116     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
1117 matthewc 188 }
1118    
1119     ui_destroy_window();
1120 jsorg71 447 g_fullscreen = !g_fullscreen;
1121 matthewc 188 ui_create_window();
1122 matthewc 123
1123 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
1124 matthewc 188
1125 jsorg71 450 if (!g_ownbackstore)
1126 matthewc 188 {
1127 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
1128     XFreePixmap(g_display, contents);
1129 matthewc 188 }
1130 jsorg71 100 }
1131    
1132 jsorg71 447 /* Process all events in Xlib queue
1133 astrand 275 Returns 0 after user quit, 1 otherwise */
1134     static int
1135 matthewc 192 xwin_process_events(void)
1136 matty 9 {
1137 n-ki 54 XEvent xevent;
1138 matthewc 38 KeySym keysym;
1139 matthewc 50 uint16 button, flags;
1140 matty 10 uint32 ev_time;
1141 astrand 66 key_translation tr;
1142     char str[256];
1143     Status status;
1144 matty 9
1145 jsorg71 450 while (XPending(g_display) > 0)
1146 matty 9 {
1147 jsorg71 450 XNextEvent(g_display, &xevent);
1148 matthewc 123
1149 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
1150 astrand 66 {
1151 astrand 84 DEBUG_KBD(("Filtering event\n"));
1152 astrand 66 continue;
1153     }
1154    
1155 matthewc 50 flags = 0;
1156 matty 10
1157 n-ki 54 switch (xevent.type)
1158 matty 9 {
1159 jsorg71 688 case VisibilityNotify:
1160     g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
1161     break;
1162 astrand 275 case ClientMessage:
1163     /* the window manager told us to quit */
1164 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
1165     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
1166 astrand 275 /* Quit */
1167     return 0;
1168     break;
1169    
1170 matty 9 case KeyPress:
1171 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1172     if (g_IC != NULL)
1173 astrand 66 /* Multi_key compatible version */
1174     {
1175 jsorg71 450 XmbLookupString(g_IC,
1176 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
1177     &status);
1178 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
1179 astrand 66 {
1180 astrand 82 error("XmbLookupString failed with status 0x%x\n",
1181     status);
1182 astrand 66 break;
1183     }
1184     }
1185     else
1186     {
1187     /* Plain old XLookupString */
1188 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
1189 astrand 66 XLookupString((XKeyEvent *) & xevent,
1190 astrand 82 str, sizeof(str), &keysym, NULL);
1191 astrand 66 }
1192    
1193 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
1194     get_ksname(keysym)));
1195 astrand 66
1196 matthewc 203 ev_time = time(NULL);
1197     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1198 astrand 118 break;
1199    
1200 astrand 66 tr = xkeymap_translate_key(keysym,
1201 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1202 astrand 69
1203 astrand 66 if (tr.scancode == 0)
1204 n-ki 52 break;
1205    
1206 astrand 470 save_remote_modifiers(tr.scancode);
1207 astrand 115 ensure_remote_modifiers(ev_time, tr);
1208 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
1209 astrand 470 restore_remote_modifiers(ev_time, tr.scancode);
1210 astrand 115
1211 astrand 66 break;
1212 matthewc 203
1213 astrand 66 case KeyRelease:
1214 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
1215 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
1216     sizeof(str), &keysym, NULL);
1217 n-ki 52
1218 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
1219 matthewc 203 get_ksname(keysym)));
1220 n-ki 52
1221 matthewc 203 ev_time = time(NULL);
1222     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1223 astrand 118 break;
1224    
1225 astrand 66 tr = xkeymap_translate_key(keysym,
1226 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
1227 astrand 66
1228     if (tr.scancode == 0)
1229     break;
1230    
1231 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
1232 matty 9 break;
1233    
1234     case ButtonPress:
1235 matthewc 50 flags = MOUSE_FLAG_DOWN;
1236     /* fall through */
1237 matty 9
1238     case ButtonRelease:
1239 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
1240 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
1241 matty 9 if (button == 0)
1242     break;
1243    
1244 astrand 328 /* If win_button_size is nonzero, enable single app mode */
1245 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
1246 astrand 328 {
1247 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
1248 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
1249     g_moving_wnd = False;
1250 astrand 332
1251 astrand 342 /* Check from right to left: */
1252    
1253 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
1254 astrand 328 {
1255 astrand 331 /* The close button, continue */
1256 astrand 328 ;
1257     }
1258 astrand 456 else if (xevent.xbutton.x >=
1259     g_width - g_win_button_size * 2)
1260 astrand 328 {
1261     /* The maximize/restore button. Do not send to
1262     server. It might be a good idea to change the
1263 jsorg71 447 cursor or give some other visible indication
1264 astrand 328 that rdesktop inhibited this click */
1265     break;
1266     }
1267 astrand 456 else if (xevent.xbutton.x >=
1268     g_width - g_win_button_size * 3)
1269 astrand 328 {
1270     /* The minimize button. Iconify window. */
1271 jsorg71 450 XIconifyWindow(g_display, g_wnd,
1272     DefaultScreen(g_display));
1273 astrand 328 break;
1274     }
1275 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
1276 astrand 342 {
1277     /* The system menu. Ignore. */
1278     break;
1279     }
1280 astrand 332 else
1281     {
1282 astrand 342 /* The title bar. */
1283 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
1284 jsorg71 450 && g_hide_decorations)
1285 astrand 342 {
1286 jsorg71 450 g_moving_wnd = True;
1287     g_move_x_offset = xevent.xbutton.x;
1288     g_move_y_offset = xevent.xbutton.y;
1289 astrand 342 }
1290 astrand 332 break;
1291 astrand 342
1292 astrand 332 }
1293 astrand 328 }
1294    
1295 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1296 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
1297 matty 10 break;
1298    
1299     case MotionNotify:
1300 jsorg71 450 if (g_moving_wnd)
1301 astrand 342 {
1302 jsorg71 450 XMoveWindow(g_display, g_wnd,
1303     xevent.xmotion.x_root - g_move_x_offset,
1304     xevent.xmotion.y_root - g_move_y_offset);
1305 astrand 342 break;
1306     }
1307    
1308 jsorg71 447 if (g_fullscreen && !g_focused)
1309 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1310 jsorg71 288 CurrentTime);
1311 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1312 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
1313 matty 28 break;
1314    
1315 matthewc 194 case FocusIn:
1316 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
1317     break;
1318 jsorg71 447 g_focused = True;
1319 astrand 543 reset_modifier_keys();
1320 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
1321     XGrabKeyboard(g_display, g_wnd, True,
1322 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
1323 matty 28 break;
1324    
1325 matthewc 194 case FocusOut:
1326 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
1327     break;
1328 jsorg71 447 g_focused = False;
1329 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
1330 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1331 matty 28 break;
1332 matty 31
1333 matthewc 250 case EnterNotify:
1334     /* we only register for this event when in fullscreen mode */
1335 jsorg71 257 /* or grab_keyboard */
1336 jsorg71 447 g_mouse_in_wnd = True;
1337     if (g_fullscreen)
1338 jsorg71 257 {
1339 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
1340 astrand 261 CurrentTime);
1341 jsorg71 257 break;
1342     }
1343 jsorg71 447 if (g_focused)
1344 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
1345 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
1346 matthewc 250 break;
1347    
1348 matthewc 253 case LeaveNotify:
1349 jsorg71 257 /* we only register for this event when grab_keyboard */
1350 jsorg71 447 g_mouse_in_wnd = False;
1351 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
1352 matthewc 253 break;
1353    
1354 matty 31 case Expose:
1355 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
1356 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
1357 astrand 64 xevent.xexpose.width,
1358     xevent.xexpose.height,
1359 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
1360 matty 31 break;
1361 astrand 119
1362     case MappingNotify:
1363     /* Refresh keyboard mapping if it has changed. This is important for
1364     Xvnc, since it allocates keycodes dynamically */
1365     if (xevent.xmapping.request == MappingKeyboard
1366     || xevent.xmapping.request == MappingModifier)
1367     XRefreshKeyboardMapping(&xevent.xmapping);
1368 matthewc 203
1369     if (xevent.xmapping.request == MappingModifier)
1370     {
1371 jsorg71 450 XFreeModifiermap(g_mod_map);
1372     g_mod_map = XGetModifierMapping(g_display);
1373 matthewc 203 }
1374 astrand 119 break;
1375 matthewc 432
1376 astrand 435 /* clipboard stuff */
1377 forsberg 415 case SelectionNotify:
1378 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1379 forsberg 415 break;
1380     case SelectionRequest:
1381 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1382 forsberg 415 break;
1383 matthewc 432 case SelectionClear:
1384     xclip_handle_SelectionClear();
1385     break;
1386 forsberg 415 case PropertyNotify:
1387 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1388 forsberg 415 break;
1389 matty 9 }
1390     }
1391 astrand 275 /* Keep going */
1392     return 1;
1393 matty 9 }
1394    
1395 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1396     int
1397 matty 33 ui_select(int rdp_socket)
1398     {
1399 stargo 606 int n;
1400 matthewc 474 fd_set rfds, wfds;
1401 n-ki 592 struct timeval tv;
1402     BOOL s_timeout = False;
1403 matty 33
1404     while (True)
1405     {
1406 stargo 606 n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
1407 matthewc 121 /* Process any events already waiting */
1408 astrand 275 if (!xwin_process_events())
1409     /* User quit */
1410     return 0;
1411 astrand 119
1412 matty 33 FD_ZERO(&rfds);
1413 matthewc 474 FD_ZERO(&wfds);
1414 matty 33 FD_SET(rdp_socket, &rfds);
1415 jsorg71 450 FD_SET(g_x_socket, &rfds);
1416 matty 33
1417 matthewc 474 #ifdef WITH_RDPSND
1418     /* FIXME: there should be an API for registering fds */
1419 stargo 504 if (g_dsp_busy)
1420 matty 33 {
1421 matthewc 474 FD_SET(g_dsp_fd, &wfds);
1422 n-ki 592 n = (g_dsp_fd > n) ? g_dsp_fd : n;
1423 astrand 499 }
1424 matthewc 474 #endif
1425 n-ki 592 /* default timeout */
1426     tv.tv_sec = 60;
1427     tv.tv_usec = 0;
1428 matthewc 474
1429 n-ki 592 /* add redirection handles */
1430     rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
1431    
1432     n++;
1433    
1434     switch (select(n, &rfds, &wfds, NULL, &tv))
1435 matthewc 474 {
1436 matty 33 case -1:
1437     error("select: %s\n", strerror(errno));
1438    
1439     case 0:
1440 stargo 795 /* Abort serial read calls */
1441     if (s_timeout)
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 stargo 754 if (FD_ISSET(rdp_socket, &rfds))
1449     return 1;
1450    
1451 matthewc 474 #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