/[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 643 - (hide annotations)
Wed Mar 24 18:16:58 2004 UTC (20 years, 1 month ago) by jsorg71
File MIME type: text/plain
File size: 45451 byte(s)
only check g_xserver_be once in translate8toXX

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

  ViewVC Help
Powered by ViewVC 1.1.26