/[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 713 - (hide annotations)
Wed Jun 16 03:08:55 2004 UTC (19 years, 11 months ago) by jsorg71
File MIME type: text/plain
File size: 48364 byte(s)
added ui_begin/end_update and rdp_loop for ports

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

  ViewVC Help
Powered by ViewVC 1.1.26