/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 708 - (hide annotations)
Fri Jun 4 15:01:36 2004 UTC (19 years, 11 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/xwin.c
File MIME type: text/plain
File size: 47784 byte(s)
warnings when screen size of depth change and backstore resizeing when screen size changes

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

  ViewVC Help
Powered by ViewVC 1.1.26