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

  ViewVC Help
Powered by ViewVC 1.1.26