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

Annotation of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 677 - (hide annotations)
Mon Apr 26 13:48:39 2004 UTC (20 years ago) by n-ki
File MIME type: text/plain
File size: 46364 byte(s)
new: ui_resize_window() and related, which is used when resizing while shadowing. And fallback for color when connecting to a session with fewer colors than you have set in your session. Jeroen Meijer jeroen@oldambt7.com

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

  ViewVC Help
Powered by ViewVC 1.1.26