/[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 342 - (hide annotations)
Fri Mar 14 12:00:17 2003 UTC (21 years, 2 months ago) by astrand
File MIME type: text/plain
File size: 37257 byte(s)
Support for moving window by dragging applications title bar. To be used
in conjunction with -s, -S and -D.

1 matty 6 /*
2     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 matty 10 #include <time.h>
24 matty 33 #include <errno.h>
25 matty 10 #include "rdesktop.h"
26 matty 6
27 matty 10 extern int width;
28     extern int height;
29 matty 29 extern BOOL sendmotion;
30 matty 28 extern BOOL fullscreen;
31 astrand 76 extern BOOL grab_keyboard;
32 astrand 262 extern BOOL hide_decorations;
33 jsorg71 100 extern char title[];
34 jsorg71 309 extern int server_bpp;
35 astrand 328 extern int win_button_size;
36 matthewc 188 BOOL enable_compose = False;
37 jsorg71 257 BOOL focused;
38     BOOL mouse_in_wnd;
39 matty 10
40 matthewc 121 Display *display;
41 matty 33 static int x_socket;
42 matthewc 121 static Screen *screen;
43 matty 10 static Window wnd;
44     static GC gc;
45     static Visual *visual;
46 matty 29 static int depth;
47     static int bpp;
48 matthewc 188 static XIM IM;
49     static XIC IC;
50 matthewc 203 static XModifierKeymap *mod_map;
51 matthewc 188 static Cursor current_cursor;
52 astrand 275 static Atom protocol_atom, kill_atom;
53 matty 29
54 matty 33 /* endianness */
55     static BOOL host_be;
56     static BOOL xserver_be;
57    
58     /* software backing store */
59 matty 31 static BOOL ownbackstore;
60     static Pixmap backstore;
61    
62 astrand 342 /* Moving in single app mode */
63     static BOOL moving_wnd;
64     static int move_x_offset = 0;
65     static int move_y_offset = 0;
66    
67 astrand 262 /* MWM decorations */
68     #define MWM_HINTS_DECORATIONS (1L << 1)
69     #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
70     typedef struct
71     {
72 matthewc 301 uint32 flags;
73     uint32 functions;
74     uint32 decorations;
75     sint32 inputMode;
76     uint32 status;
77 astrand 262 }
78     PropMotifWmHints;
79    
80 jsorg71 316 typedef struct
81     {
82     uint32 red;
83     uint32 green;
84     uint32 blue;
85     }
86     PixelColour;
87 astrand 262
88 matty 31 #define FILL_RECTANGLE(x,y,cx,cy)\
89     { \
90     XFillRectangle(display, wnd, gc, x, y, cx, cy); \
91     if (ownbackstore) \
92     XFillRectangle(display, backstore, gc, x, y, cx, cy); \
93     }
94    
95 matthewc 296 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
96 jsorg71 281 { \
97     XFillRectangle(display, ownbackstore ? backstore : wnd, gc, x, y, cx, cy); \
98     }
99    
100 matty 33 /* colour maps */
101 n-ki 279 BOOL owncolmap = False;
102 matty 29 static Colormap xcolmap;
103 matty 28 static uint32 *colmap;
104 matty 10
105 jsorg71 311 #define TRANSLATE(col) ( server_bpp != 8 ? translate_colour(col) : owncolmap ? col : translate_colour(colmap[col]) )
106 n-ki 279 #define SET_FOREGROUND(col) XSetForeground(display, gc, TRANSLATE(col));
107     #define SET_BACKGROUND(col) XSetBackground(display, gc, TRANSLATE(col));
108 matty 28
109     static int rop2_map[] = {
110     GXclear, /* 0 */
111     GXnor, /* DPon */
112     GXandInverted, /* DPna */
113     GXcopyInverted, /* Pn */
114     GXandReverse, /* PDna */
115     GXinvert, /* Dn */
116     GXxor, /* DPx */
117     GXnand, /* DPan */
118     GXand, /* DPa */
119     GXequiv, /* DPxn */
120     GXnoop, /* D */
121     GXorInverted, /* DPno */
122     GXcopy, /* P */
123     GXorReverse, /* PDno */
124     GXor, /* DPo */
125     GXset /* 1 */
126     };
127    
128 matty 29 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
129     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
130    
131 astrand 319 static void
132 astrand 262 mwm_hide_decorations(void)
133     {
134     PropMotifWmHints motif_hints;
135     Atom hintsatom;
136    
137     /* setup the property */
138     motif_hints.flags = MWM_HINTS_DECORATIONS;
139     motif_hints.decorations = 0;
140    
141     /* get the atom for the property */
142     hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
143     if (!hintsatom)
144     {
145 matthewc 297 warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
146 astrand 262 return;
147     }
148    
149     XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
150     (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
151     }
152    
153 astrand 319 static PixelColour
154 jsorg71 316 split_colour15(uint32 colour)
155 jsorg71 311 {
156 jsorg71 316 PixelColour rv;
157     rv.red = (colour & 0x7c00) >> 10;
158     rv.red = (rv.red * 0xff) / 0x1f;
159     rv.green = (colour & 0x03e0) >> 5;
160     rv.green = (rv.green * 0xff) / 0x1f;
161     rv.blue = (colour & 0x1f);
162     rv.blue = (rv.blue * 0xff) / 0x1f;
163     return rv;
164 jsorg71 311 }
165    
166 astrand 319 static PixelColour
167 jsorg71 316 split_colour16(uint32 colour)
168 jsorg71 311 {
169 jsorg71 316 PixelColour rv;
170     rv.red = (colour & 0xf800) >> 11;
171     rv.red = (rv.red * 0xff) / 0x1f;
172     rv.green = (colour & 0x07e0) >> 5;
173     rv.green = (rv.green * 0xff) / 0x3f;
174     rv.blue = (colour & 0x001f);
175     rv.blue = (rv.blue * 0xff) / 0x1f;
176     return rv;
177 jsorg71 311 }
178    
179 astrand 319 static PixelColour
180 jsorg71 316 split_colour24(uint32 colour)
181 jsorg71 311 {
182 jsorg71 316 PixelColour rv;
183     rv.blue = (colour & 0xff0000) >> 16;
184     rv.green = (colour & 0xff00) >> 8;
185     rv.red = (colour & 0xff);
186     return rv;
187 jsorg71 311 }
188    
189 astrand 319 static uint32
190 astrand 318 make_colour16(PixelColour pc)
191 jsorg71 316 {
192     pc.red = (pc.red * 0x1f) / 0xff;
193     pc.green = (pc.green * 0x3f) / 0xff;
194     pc.blue = (pc.blue * 0x1f) / 0xff;
195     return (pc.red << 11) | (pc.green << 5) | pc.blue;
196     }
197    
198 astrand 319 static uint32
199 astrand 318 make_colour24(PixelColour pc)
200 jsorg71 316 {
201     return (pc.red << 16) | (pc.green << 8) | pc.blue;
202     }
203    
204 astrand 319 static uint32
205 astrand 318 make_colour32(PixelColour pc)
206 jsorg71 316 {
207     return (pc.red << 16) | (pc.green << 8) | pc.blue;
208     }
209    
210 jsorg71 311 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
211     #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
212     #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
213     x = (x << 16) | (x >> 16); }
214    
215     static uint32
216     translate_colour(uint32 colour)
217     {
218     switch (server_bpp)
219     {
220 jsorg71 316 case 15:
221     switch (bpp)
222     {
223     case 16:
224     colour = make_colour16(split_colour15(colour));
225     break;
226     case 24:
227     colour = make_colour24(split_colour15(colour));
228     break;
229     case 32:
230     colour = make_colour32(split_colour15(colour));
231     break;
232     }
233     break;
234 jsorg71 311 case 16:
235     switch (bpp)
236     {
237     case 16:
238     break;
239     case 24:
240 jsorg71 316 colour = make_colour24(split_colour16(colour));
241 jsorg71 311 break;
242     case 32:
243 jsorg71 316 colour = make_colour32(split_colour16(colour));
244 jsorg71 311 break;
245     }
246     break;
247     case 24:
248     switch (bpp)
249     {
250 jsorg71 316 case 16:
251     colour = make_colour16(split_colour24(colour));
252     break;
253 jsorg71 311 case 24:
254     break;
255     case 32:
256 jsorg71 316 colour = make_colour32(split_colour24(colour));
257 jsorg71 311 break;
258     }
259     break;
260     }
261     switch (bpp)
262     {
263     case 16:
264     if (host_be != xserver_be)
265     BSWAP16(colour);
266     break;
267    
268     case 24:
269     if (xserver_be)
270     BSWAP24(colour);
271     break;
272    
273     case 32:
274     if (host_be != xserver_be)
275     BSWAP32(colour);
276     break;
277     }
278    
279     return colour;
280     }
281    
282 matty 28 static void
283 jsorg71 311 translate8to8(uint8 * data, uint8 * out, uint8 * end)
284 matty 28 {
285 matty 29 while (out < end)
286 astrand 64 *(out++) = (uint8) colmap[*(data++)];
287 matty 29 }
288 matty 28
289 matty 29 static void
290 jsorg71 311 translate8to16(uint8 * data, uint16 * out, uint16 * end)
291 matty 29 {
292     while (out < end)
293 astrand 64 *(out++) = (uint16) colmap[*(data++)];
294 matty 29 }
295    
296 jsorg71 316 /* little endian - conversion happens when colourmap is built */
297 jsorg71 311 static void
298 jsorg71 316 translate8to24(uint8 * data, uint8 * out, uint8 * end)
299 jsorg71 311 {
300 jsorg71 316 uint32 value;
301    
302 jsorg71 311 while (out < end)
303 jsorg71 316 {
304     value = colmap[*(data++)];
305     *(out++) = value;
306     *(out++) = value >> 8;
307     *(out++) = value >> 16;
308     }
309 jsorg71 311 }
310    
311 matty 29 static void
312 jsorg71 316 translate8to32(uint8 * data, uint32 * out, uint32 * end)
313 matty 29 {
314 jsorg71 316 while (out < end)
315     *(out++) = colmap[*(data++)];
316     }
317    
318     /* todo the remaining translate function might need some big endian check ?? */
319    
320     static void
321     translate15to16(uint16 * data, uint16 * out, uint16 * end)
322     {
323     while (out < end)
324     *(out++) = (uint16) make_colour16(split_colour15(*(data++)));
325     }
326    
327     static void
328     translate15to24(uint16 * data, uint8 * out, uint8 * end)
329     {
330 matty 29 uint32 value;
331    
332     while (out < end)
333 matty 28 {
334 jsorg71 316 value = make_colour24(split_colour15(*(data++)));
335 matty 29 *(out++) = value;
336     *(out++) = value >> 8;
337     *(out++) = value >> 16;
338 matty 28 }
339     }
340    
341     static void
342 jsorg71 316 translate15to32(uint16 * data, uint32 * out, uint32 * end)
343     {
344     while (out < end)
345     *(out++) = make_colour32(split_colour15(*(data++)));
346     }
347    
348     static void
349     translate16to16(uint16 * data, uint16 * out, uint16 * end)
350     {
351     while (out < end)
352     *(out++) = (uint16) (*(data++));
353     }
354    
355    
356     static void
357 jsorg71 311 translate16to24(uint16 * data, uint8 * out, uint8 * end)
358 matty 28 {
359 jsorg71 311 uint32 value;
360    
361 matty 29 while (out < end)
362 jsorg71 311 {
363 jsorg71 316 value = make_colour24(split_colour16(*(data++)));
364 jsorg71 311 *(out++) = value;
365     *(out++) = value >> 8;
366     *(out++) = value >> 16;
367     }
368     }
369    
370     static void
371 jsorg71 316 translate16to32(uint16 * data, uint32 * out, uint32 * end)
372 jsorg71 311 {
373     while (out < end)
374 jsorg71 316 *(out++) = make_colour32(split_colour16(*(data++)));
375 matty 28 }
376    
377 jsorg71 311 static void
378 jsorg71 316 translate24to16(uint8 * data, uint16 * out, uint16 * end)
379 jsorg71 311 {
380 jsorg71 316 uint32 pixel = 0;
381 jsorg71 311 while (out < end)
382 jsorg71 316 {
383     pixel = *(data++) << 16;
384     pixel |= *(data++) << 8;
385     pixel |= *(data++);
386     *(out++) = (uint16) make_colour16(split_colour24(pixel));
387     }
388 jsorg71 311 }
389    
390 jsorg71 316 static void
391     translate24to24(uint8 * data, uint8 * out, uint8 * end)
392     {
393     while (out < end)
394     {
395     *(out++) = (*(data++));
396     }
397     }
398    
399     static void
400     translate24to32(uint8 * data, uint32 * out, uint32 * end)
401     {
402     uint32 pixel = 0;
403     while (out < end)
404     {
405     memcpy(&pixel, data, 3);
406     data += 3;
407     *(out++) = pixel;
408     }
409     }
410    
411 matty 29 static uint8 *
412 astrand 64 translate_image(int width, int height, uint8 * data)
413 matty 28 {
414 astrand 64 int size = width * height * bpp / 8;
415 matty 29 uint8 *out = xmalloc(size);
416     uint8 *end = out + size;
417    
418 jsorg71 316 switch (server_bpp)
419 jsorg71 311 {
420 jsorg71 316 case 24:
421     switch (bpp)
422     {
423     case 32:
424     translate24to32(data, (uint32 *) out, (uint32 *) end);
425     break;
426     case 24:
427     translate24to24(data, out, end);
428     break;
429     case 16:
430     translate24to16(data, (uint16 *) out, (uint16 *) end);
431     break;
432     }
433 matty 29 break;
434     case 16:
435 jsorg71 316 switch (bpp)
436     {
437     case 32:
438 astrand 318 translate16to32((uint16 *) data, (uint32 *) out,
439     (uint32 *) end);
440 jsorg71 316 break;
441     case 24:
442     translate16to24((uint16 *) data, out, end);
443     break;
444     case 16:
445 astrand 318 translate16to16((uint16 *) data, (uint16 *) out,
446     (uint16 *) end);
447 jsorg71 316 break;
448     }
449 matty 29 break;
450 jsorg71 316 case 15:
451     switch (bpp)
452     {
453     case 32:
454 astrand 318 translate15to32((uint16 *) data, (uint32 *) out,
455     (uint32 *) end);
456 jsorg71 316 break;
457     case 24:
458     translate15to24((uint16 *) data, out, end);
459     break;
460     case 16:
461 astrand 318 translate15to16((uint16 *) data, (uint16 *) out,
462     (uint16 *) end);
463 jsorg71 316 break;
464     }
465 matty 29 break;
466 jsorg71 316 case 8:
467     switch (bpp)
468     {
469     case 8:
470     translate8to8(data, out, end);
471     break;
472     case 16:
473     translate8to16(data, (uint16 *) out, (uint16 *) end);
474     break;
475     case 24:
476     translate8to24(data, out, end);
477     break;
478     case 32:
479     translate8to32(data, (uint32 *) out, (uint32 *) end);
480     break;
481     }
482 matty 29 break;
483     }
484     return out;
485 matty 28 }
486    
487 astrand 118 BOOL
488 matthewc 209 get_key_state(unsigned int state, uint32 keysym)
489 astrand 102 {
490 matthewc 203 int modifierpos, key, keysymMask = 0;
491 astrand 102 int offset;
492    
493     KeyCode keycode = XKeysymToKeycode(display, keysym);
494    
495     if (keycode == NoSymbol)
496     return False;
497    
498     for (modifierpos = 0; modifierpos < 8; modifierpos++)
499     {
500 matthewc 203 offset = mod_map->max_keypermod * modifierpos;
501 astrand 102
502 matthewc 203 for (key = 0; key < mod_map->max_keypermod; key++)
503 astrand 102 {
504 matthewc 203 if (mod_map->modifiermap[offset + key] == keycode)
505     keysymMask |= 1 << modifierpos;
506 astrand 102 }
507     }
508    
509 matthewc 203 return (state & keysymMask) ? True : False;
510 astrand 102 }
511    
512 jsorg71 81 BOOL
513 matthewc 192 ui_init(void)
514 jsorg71 81 {
515 matthewc 121 XPixmapFormatValues *pfm;
516     uint16 test;
517     int i;
518    
519 jsorg71 81 display = XOpenDisplay(NULL);
520     if (display == NULL)
521     {
522 matthewc 210 error("Failed to open display: %s\n", XDisplayName(NULL));
523 jsorg71 81 return False;
524     }
525 matthewc 121
526     x_socket = ConnectionNumber(display);
527     screen = DefaultScreenOfDisplay(display);
528     visual = DefaultVisualOfScreen(screen);
529     depth = DefaultDepthOfScreen(screen);
530    
531     pfm = XListPixmapFormats(display, &i);
532     if (pfm != NULL)
533     {
534     /* Use maximum bpp for this depth - this is generally
535     desirable, e.g. 24 bits->32 bits. */
536     while (i--)
537     {
538     if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
539     {
540     bpp = pfm[i].bits_per_pixel;
541     }
542     }
543     XFree(pfm);
544     }
545    
546     if (bpp < 8)
547     {
548     error("Less than 8 bpp not currently supported.\n");
549     XCloseDisplay(display);
550     return False;
551     }
552    
553 n-ki 279 if (owncolmap != True)
554     {
555     xcolmap = DefaultColormapOfScreen(screen);
556     if (depth <= 8)
557 matthewc 297 warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");
558 n-ki 279 }
559    
560 matthewc 188 gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
561 matthewc 121
562 matthewc 188 if (DoesBackingStore(screen) != Always)
563 matthewc 121 ownbackstore = True;
564    
565     test = 1;
566     host_be = !(BOOL) (*(uint8 *) (&test));
567     xserver_be = (ImageByteOrder(display) == MSBFirst);
568    
569 astrand 263 if ((width == 0) || (height == 0))
570     {
571     /* Fetch geometry from _NET_WORKAREA */
572 matthewc 300 uint32 x, y, cx, cy;
573 astrand 263
574 matthewc 300 if (get_current_workarea(&x, &y, &cx, &cy) == 0)
575 astrand 263 {
576 matthewc 300 width = cx;
577     height = cy;
578     }
579     else
580     {
581 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
582 astrand 274 width = 800;
583     height = 600;
584 astrand 263 }
585     }
586    
587 astrand 82 if (fullscreen)
588 jsorg71 81 {
589     width = WidthOfScreen(screen);
590     height = HeightOfScreen(screen);
591     }
592 matthewc 121
593 matthewc 160 /* make sure width is a multiple of 4 */
594     width = (width + 3) & ~3;
595    
596 matthewc 188 if (ownbackstore)
597     {
598 astrand 196 backstore =
599     XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
600 matthewc 188
601     /* clear to prevent rubbish being exposed at startup */
602     XSetForeground(display, gc, BlackPixelOfScreen(screen));
603     XFillRectangle(display, backstore, gc, 0, 0, width, height);
604     }
605    
606 matthewc 203 mod_map = XGetModifierMapping(display);
607    
608 matthewc 188 if (enable_compose)
609     IM = XOpenIM(display, NULL, NULL, NULL);
610    
611 matthewc 121 xkeymap_init();
612 jsorg71 316
613     /* todo take this out when high colour is done */
614     printf("server bpp %d client bpp %d depth %d\n", server_bpp, bpp, depth);
615    
616 jsorg71 81 return True;
617     }
618 astrand 66
619 matthewc 188 void
620 matthewc 192 ui_deinit(void)
621 matthewc 188 {
622     if (IM != NULL)
623     XCloseIM(IM);
624    
625 matthewc 204 XFreeModifiermap(mod_map);
626 matthewc 203
627 matthewc 188 if (ownbackstore)
628     XFreePixmap(display, backstore);
629    
630     XFreeGC(display, gc);
631     XCloseDisplay(display);
632     display = NULL;
633     }
634    
635 matthewc 121 BOOL
636 matthewc 192 ui_create_window(void)
637 matty 6 {
638 matthewc 121 XSetWindowAttributes attribs;
639 matty 28 XClassHint *classhints;
640     XSizeHints *sizehints;
641 matthewc 188 int wndwidth, wndheight;
642     long input_mask, ic_input_mask;
643 jsorg71 100 XEvent xevent;
644    
645 astrand 196 wndwidth = fullscreen ? WidthOfScreen(screen) : width;
646 matthewc 188 wndheight = fullscreen ? HeightOfScreen(screen) : height;
647    
648 matthewc 121 attribs.background_pixel = BlackPixelOfScreen(screen);
649     attribs.backing_store = ownbackstore ? NotUseful : Always;
650     attribs.override_redirect = fullscreen;
651 matthewc 188
652     wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
653 matthewc 121 0, CopyFromParent, InputOutput, CopyFromParent,
654     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
655 jsorg71 100
656     XStoreName(display, wnd, title);
657    
658 astrand 262 if (hide_decorations)
659     mwm_hide_decorations();
660    
661 jsorg71 100 classhints = XAllocClassHint();
662     if (classhints != NULL)
663     {
664     classhints->res_name = classhints->res_class = "rdesktop";
665     XSetClassHint(display, wnd, classhints);
666     XFree(classhints);
667     }
668    
669     sizehints = XAllocSizeHints();
670     if (sizehints)
671     {
672     sizehints->flags = PMinSize | PMaxSize;
673     sizehints->min_width = sizehints->max_width = width;
674     sizehints->min_height = sizehints->max_height = height;
675     XSetWMNormalHints(display, wnd, sizehints);
676     XFree(sizehints);
677     }
678    
679 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
680 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
681 matthewc 121
682     if (sendmotion)
683     input_mask |= PointerMotionMask;
684     if (ownbackstore)
685     input_mask |= ExposureMask;
686 jsorg71 257 if (fullscreen || grab_keyboard)
687 matthewc 250 input_mask |= EnterWindowMask;
688 jsorg71 257 if (grab_keyboard)
689     input_mask |= LeaveWindowMask;
690 jsorg71 100
691 matthewc 188 if (IM != NULL)
692     {
693     IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
694     XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
695    
696 astrand 196 if ((IC != NULL)
697     && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
698 matthewc 188 input_mask |= ic_input_mask;
699     }
700    
701 jsorg71 100 XSelectInput(display, wnd, input_mask);
702 matthewc 188 XMapWindow(display, wnd);
703 jsorg71 100
704 matthewc 208 /* wait for VisibilityNotify */
705 astrand 196 do
706     {
707 matthewc 208 XMaskEvent(display, VisibilityChangeMask, &xevent);
708 astrand 196 }
709 matthewc 208 while (xevent.type != VisibilityNotify);
710 matthewc 123
711 jsorg71 257 focused = False;
712     mouse_in_wnd = False;
713    
714 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
715     protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True);
716     kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True);
717     XSetWMProtocols(display, wnd, &kill_atom, 1);
718    
719 matty 10 return True;
720 matty 6 }
721    
722 matty 25 void
723 matthewc 192 ui_destroy_window(void)
724 matty 6 {
725 matthewc 188 if (IC != NULL)
726     XDestroyIC(IC);
727 matty 31
728 matty 10 XDestroyWindow(display, wnd);
729 matty 6 }
730    
731 jsorg71 100 void
732 matthewc 192 xwin_toggle_fullscreen(void)
733 jsorg71 100 {
734 matthewc 188 Pixmap contents = 0;
735 matthewc 123
736 matthewc 188 if (!ownbackstore)
737     {
738     /* need to save contents of window */
739     contents = XCreatePixmap(display, wnd, width, height, depth);
740     XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
741     }
742    
743     ui_destroy_window();
744 matthewc 123 fullscreen = !fullscreen;
745 matthewc 188 ui_create_window();
746 matthewc 123
747 matthewc 188 XDefineCursor(display, wnd, current_cursor);
748    
749     if (!ownbackstore)
750     {
751     XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
752     XFreePixmap(display, contents);
753     }
754 jsorg71 100 }
755    
756 astrand 275 /* Process all events in Xlib queue
757     Returns 0 after user quit, 1 otherwise */
758     static int
759 matthewc 192 xwin_process_events(void)
760 matty 9 {
761 n-ki 54 XEvent xevent;
762 matthewc 38 KeySym keysym;
763 matthewc 50 uint16 button, flags;
764 matty 10 uint32 ev_time;
765 astrand 66 key_translation tr;
766     char str[256];
767     Status status;
768 matthewc 203 unsigned int state;
769     Window wdummy;
770     int dummy;
771 matty 9
772 matthewc 123 while (XPending(display) > 0)
773 matty 9 {
774 matthewc 123 XNextEvent(display, &xevent);
775    
776 matthewc 188 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
777 astrand 66 {
778 astrand 84 DEBUG_KBD(("Filtering event\n"));
779 astrand 66 continue;
780     }
781    
782 matthewc 50 flags = 0;
783 matty 10
784 n-ki 54 switch (xevent.type)
785 matty 9 {
786 astrand 275 case ClientMessage:
787     /* the window manager told us to quit */
788     if ((xevent.xclient.message_type == protocol_atom)
789     && (xevent.xclient.data.l[0] == kill_atom))
790     /* Quit */
791     return 0;
792     break;
793    
794 matty 9 case KeyPress:
795 astrand 66 if (IC != NULL)
796     /* Multi_key compatible version */
797     {
798     XmbLookupString(IC,
799     (XKeyPressedEvent *) &
800 astrand 82 xevent, str, sizeof(str), &keysym, &status);
801     if (!((status == XLookupKeySym) || (status == XLookupBoth)))
802 astrand 66 {
803 astrand 82 error("XmbLookupString failed with status 0x%x\n",
804     status);
805 astrand 66 break;
806     }
807     }
808     else
809     {
810     /* Plain old XLookupString */
811 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
812 astrand 66 XLookupString((XKeyEvent *) & xevent,
813 astrand 82 str, sizeof(str), &keysym, NULL);
814 astrand 66 }
815    
816 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
817     get_ksname(keysym)));
818 astrand 66
819 matthewc 203 ev_time = time(NULL);
820     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
821 astrand 118 break;
822    
823 astrand 66 tr = xkeymap_translate_key(keysym,
824 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
825 astrand 69
826 astrand 66 if (tr.scancode == 0)
827 n-ki 52 break;
828    
829 astrand 115 ensure_remote_modifiers(ev_time, tr);
830    
831 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
832 astrand 66 break;
833 matthewc 203
834 astrand 66 case KeyRelease:
835     XLookupString((XKeyEvent *) & xevent, str,
836     sizeof(str), &keysym, NULL);
837 n-ki 52
838 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
839 matthewc 203 get_ksname(keysym)));
840 n-ki 52
841 matthewc 203 ev_time = time(NULL);
842     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
843 astrand 118 break;
844    
845 astrand 66 tr = xkeymap_translate_key(keysym,
846 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
847 astrand 66
848     if (tr.scancode == 0)
849     break;
850    
851 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
852 matty 9 break;
853    
854     case ButtonPress:
855 matthewc 50 flags = MOUSE_FLAG_DOWN;
856     /* fall through */
857 matty 9
858     case ButtonRelease:
859 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
860 matty 9 if (button == 0)
861     break;
862    
863 astrand 328 /* If win_button_size is nonzero, enable single app mode */
864     if (xevent.xbutton.y < win_button_size)
865     {
866 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
867     if (moving_wnd && (xevent.type == ButtonRelease))
868     moving_wnd = False;
869 astrand 332
870 astrand 342 /* Check from right to left: */
871    
872 astrand 332 if (xevent.xbutton.x >= width - win_button_size)
873 astrand 328 {
874 astrand 331 /* The close button, continue */
875 astrand 328 ;
876     }
877     else if (xevent.xbutton.x >= width - win_button_size * 2)
878     {
879     /* The maximize/restore button. Do not send to
880     server. It might be a good idea to change the
881     cursor or give some other visible indication
882     that rdesktop inhibited this click */
883     break;
884     }
885     else if (xevent.xbutton.x >= width - win_button_size * 3)
886     {
887     /* The minimize button. Iconify window. */
888     XIconifyWindow(display, wnd,
889     DefaultScreen(display));
890     break;
891     }
892 astrand 342 else if (xevent.xbutton.x <= win_button_size)
893     {
894     /* The system menu. Ignore. */
895     break;
896     }
897 astrand 332 else
898     {
899 astrand 342 /* The title bar. */
900     if ((xevent.type == ButtonPress) && !fullscreen
901     && hide_decorations)
902     {
903     moving_wnd = True;
904     move_x_offset = xevent.xbutton.x;
905     move_y_offset = xevent.xbutton.y;
906     }
907 astrand 332 break;
908 astrand 342
909 astrand 332 }
910 astrand 328 }
911    
912 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
913 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
914 matty 10 break;
915    
916     case MotionNotify:
917 astrand 342 if (moving_wnd)
918     {
919     XMoveWindow(display, wnd,
920     xevent.xmotion.x_root - move_x_offset,
921     xevent.xmotion.y_root - move_y_offset);
922     break;
923     }
924    
925 jsorg71 288 if (fullscreen && !focused)
926     XSetInputFocus(display, wnd, RevertToPointerRoot,
927     CurrentTime);
928 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
929 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
930 matty 28 break;
931    
932 matthewc 194 case FocusIn:
933 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
934     break;
935     focused = True;
936 astrand 261 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
937     &dummy, &dummy, &state);
938 matthewc 203 reset_modifier_keys(state);
939 jsorg71 257 if (grab_keyboard && mouse_in_wnd)
940 astrand 76 XGrabKeyboard(display, wnd, True,
941 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
942 matty 28 break;
943    
944 matthewc 194 case FocusOut:
945 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
946     break;
947     focused = False;
948 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
949 astrand 76 XUngrabKeyboard(display, CurrentTime);
950 matty 28 break;
951 matty 31
952 matthewc 250 case EnterNotify:
953     /* we only register for this event when in fullscreen mode */
954 jsorg71 257 /* or grab_keyboard */
955     mouse_in_wnd = True;
956     if (fullscreen)
957     {
958 astrand 261 XSetInputFocus(display, wnd, RevertToPointerRoot,
959     CurrentTime);
960 jsorg71 257 break;
961     }
962     if (focused)
963     XGrabKeyboard(display, wnd, True,
964     GrabModeAsync, GrabModeAsync, CurrentTime);
965 matthewc 250 break;
966    
967 matthewc 253 case LeaveNotify:
968 jsorg71 257 /* we only register for this event when grab_keyboard */
969     mouse_in_wnd = False;
970 matthewc 253 XUngrabKeyboard(display, CurrentTime);
971     break;
972    
973 matty 31 case Expose:
974     XCopyArea(display, backstore, wnd, gc,
975 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
976 astrand 64 xevent.xexpose.width,
977     xevent.xexpose.height,
978 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
979 matty 31 break;
980 astrand 119
981     case MappingNotify:
982     /* Refresh keyboard mapping if it has changed. This is important for
983     Xvnc, since it allocates keycodes dynamically */
984     if (xevent.xmapping.request == MappingKeyboard
985     || xevent.xmapping.request == MappingModifier)
986     XRefreshKeyboardMapping(&xevent.xmapping);
987 matthewc 203
988     if (xevent.xmapping.request == MappingModifier)
989     {
990 matthewc 204 XFreeModifiermap(mod_map);
991 matthewc 203 mod_map = XGetModifierMapping(display);
992     }
993 astrand 119 break;
994    
995 matty 9 }
996     }
997 astrand 275 /* Keep going */
998     return 1;
999 matty 9 }
1000    
1001 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1002     int
1003 matty 33 ui_select(int rdp_socket)
1004     {
1005 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
1006 matty 33 fd_set rfds;
1007    
1008     FD_ZERO(&rfds);
1009    
1010     while (True)
1011     {
1012 matthewc 121 /* Process any events already waiting */
1013 astrand 275 if (!xwin_process_events())
1014     /* User quit */
1015     return 0;
1016 astrand 119
1017 matty 33 FD_ZERO(&rfds);
1018     FD_SET(rdp_socket, &rfds);
1019 matthewc 121 FD_SET(x_socket, &rfds);
1020 matty 33
1021     switch (select(n, &rfds, NULL, NULL, NULL))
1022     {
1023     case -1:
1024     error("select: %s\n", strerror(errno));
1025    
1026     case 0:
1027     continue;
1028     }
1029    
1030     if (FD_ISSET(rdp_socket, &rfds))
1031 astrand 275 return 1;
1032 matty 33 }
1033     }
1034    
1035     void
1036 matty 25 ui_move_pointer(int x, int y)
1037 matty 9 {
1038 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
1039 matty 9 }
1040    
1041 matty 25 HBITMAP
1042 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1043 matty 6 {
1044     XImage *image;
1045 matty 9 Pixmap bitmap;
1046 matty 28 uint8 *tdata;
1047 matty 29
1048 n-ki 279 tdata = (owncolmap ? data : translate_image(width, height, data));
1049 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
1050 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1051 jsorg71 311 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1052 matty 6
1053 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1054 matty 9
1055     XFree(image);
1056 n-ki 279 if (!owncolmap)
1057     xfree(tdata);
1058 matty 24 return (HBITMAP) bitmap;
1059 matty 6 }
1060    
1061 matty 25 void
1062 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1063 matty 6 {
1064 matty 10 XImage *image;
1065 matty 29 uint8 *tdata;
1066 n-ki 279 tdata = (owncolmap ? data : translate_image(width, height, data));
1067 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1068 jsorg71 311 (char *) tdata, width, height, server_bpp == 8 ? 8 : bpp, 0);
1069 matty 28
1070 matty 31 if (ownbackstore)
1071     {
1072     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1073     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1074     }
1075     else
1076     {
1077     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1078     }
1079 matty 29
1080 matty 24 XFree(image);
1081 n-ki 279 if (!owncolmap)
1082     xfree(tdata);
1083 matty 6 }
1084    
1085 matty 25 void
1086     ui_destroy_bitmap(HBITMAP bmp)
1087 matty 6 {
1088 astrand 64 XFreePixmap(display, (Pixmap) bmp);
1089 matty 10 }
1090    
1091 matty 25 HGLYPH
1092 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1093 matty 10 {
1094 matty 9 XImage *image;
1095     Pixmap bitmap;
1096     int scanline;
1097     GC gc;
1098 matty 6
1099 matty 9 scanline = (width + 7) / 8;
1100 matty 6
1101 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
1102     gc = XCreateGC(display, bitmap, 0, NULL);
1103 matty 9
1104 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
1105 astrand 73 width, height, 8, scanline);
1106 matty 23 image->byte_order = MSBFirst;
1107     image->bitmap_bit_order = MSBFirst;
1108     XInitImage(image);
1109    
1110 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1111 matty 29
1112 matty 9 XFree(image);
1113 matty 10 XFreeGC(display, gc);
1114 astrand 64 return (HGLYPH) bitmap;
1115 matty 6 }
1116 matty 7
1117 matty 25 void
1118     ui_destroy_glyph(HGLYPH glyph)
1119 matty 7 {
1120 astrand 64 XFreePixmap(display, (Pixmap) glyph);
1121 matty 9 }
1122    
1123 matty 29 HCURSOR
1124 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1125     uint8 * andmask, uint8 * xormask)
1126 matty 9 {
1127 matty 29 HGLYPH maskglyph, cursorglyph;
1128     XColor bg, fg;
1129     Cursor xcursor;
1130     uint8 *cursor, *pcursor;
1131     uint8 *mask, *pmask;
1132     uint8 nextbit;
1133     int scanline, offset;
1134     int i, j;
1135    
1136     scanline = (width + 7) / 8;
1137     offset = scanline * height;
1138    
1139     cursor = xmalloc(offset);
1140     memset(cursor, 0, offset);
1141    
1142     mask = xmalloc(offset);
1143     memset(mask, 0, offset);
1144    
1145     /* approximate AND and XOR masks with a monochrome X pointer */
1146     for (i = 0; i < height; i++)
1147 matty 7 {
1148 matty 29 offset -= scanline;
1149     pcursor = &cursor[offset];
1150     pmask = &mask[offset];
1151    
1152     for (j = 0; j < scanline; j++)
1153 matty 28 {
1154 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1155     {
1156     if (xormask[0] || xormask[1] || xormask[2])
1157     {
1158     *pcursor |= (~(*andmask) & nextbit);
1159     *pmask |= nextbit;
1160     }
1161     else
1162     {
1163     *pcursor |= ((*andmask) & nextbit);
1164     *pmask |= (~(*andmask) & nextbit);
1165     }
1166    
1167     xormask += 3;
1168     }
1169    
1170     andmask++;
1171     pcursor++;
1172     pmask++;
1173 matty 28 }
1174 matty 7 }
1175 matty 29
1176     fg.red = fg.blue = fg.green = 0xffff;
1177     bg.red = bg.blue = bg.green = 0x0000;
1178     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1179    
1180     cursorglyph = ui_create_glyph(width, height, cursor);
1181     maskglyph = ui_create_glyph(width, height, mask);
1182    
1183 astrand 66 xcursor =
1184     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
1185     (Pixmap) maskglyph, &fg, &bg, x, y);
1186 astrand 64
1187 matty 29 ui_destroy_glyph(maskglyph);
1188     ui_destroy_glyph(cursorglyph);
1189     xfree(mask);
1190     xfree(cursor);
1191 astrand 64 return (HCURSOR) xcursor;
1192 matty 29 }
1193    
1194     void
1195     ui_set_cursor(HCURSOR cursor)
1196     {
1197 matthewc 188 current_cursor = (Cursor) cursor;
1198     XDefineCursor(display, wnd, current_cursor);
1199 matty 29 }
1200    
1201     void
1202     ui_destroy_cursor(HCURSOR cursor)
1203     {
1204 astrand 64 XFreeCursor(display, (Cursor) cursor);
1205 matty 29 }
1206    
1207     #define MAKE_XCOLOR(xc,c) \
1208     (xc)->red = ((c)->red << 8) | (c)->red; \
1209     (xc)->green = ((c)->green << 8) | (c)->green; \
1210     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1211     (xc)->flags = DoRed | DoGreen | DoBlue;
1212    
1213 n-ki 279
1214 matty 29 HCOLOURMAP
1215 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1216 matty 29 {
1217     COLOURENTRY *entry;
1218     int i, ncolours = colours->ncolours;
1219 n-ki 279 if (!owncolmap)
1220 matty 28 {
1221 n-ki 279 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
1222     XColor xentry;
1223     XColor xc_cache[256];
1224     uint32 colour;
1225     int colLookup = 256;
1226     for (i = 0; i < ncolours; i++)
1227 matty 28 {
1228 n-ki 279 entry = &colours->colours[i];
1229     MAKE_XCOLOR(&xentry, entry);
1230 matty 7
1231 n-ki 279 if (XAllocColor(display, xcolmap, &xentry) == 0)
1232 astrand 196 {
1233 n-ki 279 /* Allocation failed, find closest match. */
1234     int j = 256;
1235     int nMinDist = 3 * 256 * 256;
1236     long nDist = nMinDist;
1237 matty 28
1238 n-ki 279 /* only get the colors once */
1239     while (colLookup--)
1240 astrand 196 {
1241 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1242     xc_cache[colLookup].red = xc_cache[colLookup].green =
1243     xc_cache[colLookup].blue = 0;
1244     xc_cache[colLookup].flags = 0;
1245     XQueryColor(display,
1246     DefaultColormap(display,
1247     DefaultScreen(display)),
1248     &xc_cache[colLookup]);
1249 n-ki 185 }
1250 n-ki 279 colLookup = 0;
1251    
1252     /* approximate the pixel */
1253     while (j--)
1254 astrand 196 {
1255 n-ki 279 if (xc_cache[j].flags)
1256     {
1257     nDist = ((long) (xc_cache[j].red >> 8) -
1258     (long) (xentry.red >> 8)) *
1259     ((long) (xc_cache[j].red >> 8) -
1260     (long) (xentry.red >> 8)) +
1261     ((long) (xc_cache[j].green >> 8) -
1262     (long) (xentry.green >> 8)) *
1263     ((long) (xc_cache[j].green >> 8) -
1264     (long) (xentry.green >> 8)) +
1265     ((long) (xc_cache[j].blue >> 8) -
1266     (long) (xentry.blue >> 8)) *
1267     ((long) (xc_cache[j].blue >> 8) -
1268     (long) (xentry.blue >> 8));
1269     }
1270     if (nDist < nMinDist)
1271     {
1272     nMinDist = nDist;
1273     xentry.pixel = j;
1274     }
1275 n-ki 185 }
1276     }
1277 n-ki 279 colour = xentry.pixel;
1278    
1279     /* update our cache */
1280     if (xentry.pixel < 256)
1281     {
1282     xc_cache[xentry.pixel].red = xentry.red;
1283     xc_cache[xentry.pixel].green = xentry.green;
1284     xc_cache[xentry.pixel].blue = xentry.blue;
1285    
1286     }
1287    
1288    
1289     /* byte swap here to make translate_image faster */
1290     map[i] = translate_colour(colour);
1291 n-ki 185 }
1292 n-ki 279 return map;
1293     }
1294     else
1295     {
1296     XColor *xcolours, *xentry;
1297     Colormap map;
1298 matty 29
1299 n-ki 279 xcolours = xmalloc(sizeof(XColor) * ncolours);
1300     for (i = 0; i < ncolours; i++)
1301 astrand 196 {
1302 n-ki 279 entry = &colours->colours[i];
1303     xentry = &xcolours[i];
1304     xentry->pixel = i;
1305     MAKE_XCOLOR(xentry, entry);
1306 matty 29 }
1307    
1308 n-ki 279 map = XCreateColormap(display, wnd, visual, AllocAll);
1309     XStoreColors(display, map, xcolours, ncolours);
1310 n-ki 185
1311 n-ki 279 xfree(xcolours);
1312     return (HCOLOURMAP) map;
1313 matty 29 }
1314 matty 7 }
1315    
1316 matty 25 void
1317     ui_destroy_colourmap(HCOLOURMAP map)
1318 matty 7 {
1319 n-ki 279 if (!owncolmap)
1320     xfree(map);
1321     else
1322     XFreeColormap(display, (Colormap) map);
1323 matty 7 }
1324    
1325 matty 25 void
1326     ui_set_colourmap(HCOLOURMAP map)
1327 matty 7 {
1328 n-ki 279 if (!owncolmap)
1329     colmap = map;
1330     else
1331     XSetWindowColormap(display, wnd, (Colormap) map);
1332 matty 7 }
1333    
1334 matty 25 void
1335     ui_set_clip(int x, int y, int cx, int cy)
1336 matty 7 {
1337 matty 9 XRectangle rect;
1338 matty 7
1339 matty 9 rect.x = x;
1340     rect.y = y;
1341     rect.width = cx;
1342     rect.height = cy;
1343 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1344 matty 9 }
1345 matty 7
1346 matty 25 void
1347 matthewc 192 ui_reset_clip(void)
1348 matty 9 {
1349     XRectangle rect;
1350    
1351     rect.x = 0;
1352     rect.y = 0;
1353 matty 10 rect.width = width;
1354     rect.height = height;
1355     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
1356 matty 7 }
1357    
1358 matty 25 void
1359 matthewc 192 ui_bell(void)
1360 matty 10 {
1361     XBell(display, 0);
1362     }
1363    
1364 matty 25 void
1365     ui_destblt(uint8 opcode,
1366     /* dest */ int x, int y, int cx, int cy)
1367 matty 9 {
1368 matty 29 SET_FUNCTION(opcode);
1369 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1370 matty 29 RESET_FUNCTION(opcode);
1371 matty 9 }
1372    
1373 matty 25 void
1374     ui_patblt(uint8 opcode,
1375     /* dest */ int x, int y, int cx, int cy,
1376 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1377 matty 9 {
1378     Pixmap fill;
1379 jsorg71 59 uint8 i, ipattern[8];
1380 matty 9
1381 matty 29 SET_FUNCTION(opcode);
1382 matty 9
1383     switch (brush->style)
1384     {
1385 matty 24 case 0: /* Solid */
1386 matty 29 SET_FOREGROUND(fgcolour);
1387 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1388 matty 9 break;
1389    
1390 matty 24 case 3: /* Pattern */
1391 jsorg71 59 for (i = 0; i != 8; i++)
1392     ipattern[7 - i] = brush->pattern[i];
1393     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1394 matty 9
1395 matty 29 SET_FOREGROUND(bgcolour);
1396     SET_BACKGROUND(fgcolour);
1397     XSetFillStyle(display, gc, FillOpaqueStippled);
1398     XSetStipple(display, gc, fill);
1399 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1400 matty 9
1401 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1402 matty 9
1403 matty 29 XSetFillStyle(display, gc, FillSolid);
1404 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
1405 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1406 matty 9 break;
1407    
1408     default:
1409 matty 30 unimpl("brush %d\n", brush->style);
1410 matty 9 }
1411 matty 29
1412     RESET_FUNCTION(opcode);
1413 matty 9 }
1414    
1415 matty 25 void
1416     ui_screenblt(uint8 opcode,
1417     /* dest */ int x, int y, int cx, int cy,
1418     /* src */ int srcx, int srcy)
1419 matty 9 {
1420 matty 29 SET_FUNCTION(opcode);
1421 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1422 matty 31 if (ownbackstore)
1423 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1424 matty 29 RESET_FUNCTION(opcode);
1425 matty 9 }
1426    
1427 matty 25 void
1428     ui_memblt(uint8 opcode,
1429     /* dest */ int x, int y, int cx, int cy,
1430     /* src */ HBITMAP src, int srcx, int srcy)
1431 matty 9 {
1432 matty 29 SET_FUNCTION(opcode);
1433 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1434 matty 31 if (ownbackstore)
1435 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1436 matty 29 RESET_FUNCTION(opcode);
1437 matty 9 }
1438    
1439 matty 25 void
1440     ui_triblt(uint8 opcode,
1441     /* dest */ int x, int y, int cx, int cy,
1442     /* src */ HBITMAP src, int srcx, int srcy,
1443 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1444 matty 9 {
1445     /* This is potentially difficult to do in general. Until someone
1446 matty 10 comes up with a more efficient way of doing it I am using cases. */
1447 matty 9
1448     switch (opcode)
1449     {
1450 matty 24 case 0x69: /* PDSxxn */
1451 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1452 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1453 matty 16 break;
1454    
1455 matty 24 case 0xb8: /* PSDPxax */
1456 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1457 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1458 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1459 matty 9 break;
1460    
1461 matty 29 case 0xc0: /* PSa */
1462 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1463 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1464 matty 28 break;
1465    
1466 matty 9 default:
1467 matty 30 unimpl("triblt 0x%x\n", opcode);
1468 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1469 matty 9 }
1470     }
1471    
1472 matty 25 void
1473     ui_line(uint8 opcode,
1474     /* dest */ int startx, int starty, int endx, int endy,
1475 astrand 64 /* pen */ PEN * pen)
1476 matty 9 {
1477 matty 29 SET_FUNCTION(opcode);
1478     SET_FOREGROUND(pen->colour);
1479 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1480 matty 31 if (ownbackstore)
1481     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1482 matty 29 RESET_FUNCTION(opcode);
1483 matty 9 }
1484    
1485 matty 25 void
1486     ui_rect(
1487     /* dest */ int x, int y, int cx, int cy,
1488     /* brush */ int colour)
1489 matty 9 {
1490 matty 29 SET_FOREGROUND(colour);
1491 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1492 matty 9 }
1493    
1494 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1495 matty 25 void
1496     ui_draw_glyph(int mixmode,
1497     /* dest */ int x, int y, int cx, int cy,
1498 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1499     int bgcolour, int fgcolour)
1500 matty 9 {
1501 matty 29 SET_FOREGROUND(fgcolour);
1502     SET_BACKGROUND(bgcolour);
1503 matty 9
1504 astrand 66 XSetFillStyle(display, gc,
1505 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1506 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1507 matty 29 XSetTSOrigin(display, gc, x, y);
1508 matty 9
1509 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1510 matty 9
1511 matty 29 XSetFillStyle(display, gc, FillSolid);
1512 matty 9 }
1513    
1514 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1515     {\
1516     glyph = cache_get_font (font, ttext[idx]);\
1517     if (!(flags & TEXT2_IMPLICIT_X))\
1518     {\
1519     xyoffset = ttext[++idx];\
1520     if ((xyoffset & 0x80))\
1521     {\
1522     if (flags & TEXT2_VERTICAL) \
1523 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1524 mmihalik 49 else\
1525 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1526     idx += 2;\
1527 mmihalik 49 }\
1528     else\
1529     {\
1530     if (flags & TEXT2_VERTICAL) \
1531     y += xyoffset;\
1532     else\
1533     x += xyoffset;\
1534     }\
1535     }\
1536     if (glyph != NULL)\
1537     {\
1538 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1539     y + glyph->baseline,\
1540 mmihalik 49 glyph->width, glyph->height,\
1541     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1542     if (flags & TEXT2_IMPLICIT_X)\
1543     x += glyph->width;\
1544     }\
1545     }
1546    
1547 matty 25 void
1548     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1549 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1550     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1551 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1552 matty 9 {
1553 matty 10 FONTGLYPH *glyph;
1554 mmihalik 49 int i, j, xyoffset;
1555     DATABLOB *entry;
1556 matty 9
1557 matty 29 SET_FOREGROUND(bgcolour);
1558 matty 28
1559 matty 9 if (boxcx > 1)
1560 matty 31 {
1561 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1562 matty 31 }
1563 matty 17 else if (mixmode == MIX_OPAQUE)
1564 matty 31 {
1565 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1566 matty 31 }
1567 matty 9
1568     /* Paint text, character by character */
1569 astrand 64 for (i = 0; i < length;)
1570     {
1571     switch (text[i])
1572     {
1573     case 0xff:
1574     if (i + 2 < length)
1575 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1576 astrand 64 else
1577     {
1578     error("this shouldn't be happening\n");
1579 astrand 265 exit(1);
1580 astrand 64 }
1581     /* this will move pointer from start to first character after FF command */
1582     length -= i + 3;
1583     text = &(text[i + 3]);
1584     i = 0;
1585 mmihalik 49 break;
1586 matty 9
1587 astrand 64 case 0xfe:
1588     entry = cache_get_text(text[i + 1]);
1589     if (entry != NULL)
1590     {
1591     if ((((uint8 *) (entry->data))[1] ==
1592 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1593 astrand 64 {
1594     if (flags & TEXT2_VERTICAL)
1595     y += text[i + 2];
1596     else
1597     x += text[i + 2];
1598     }
1599     for (j = 0; j < entry->size; j++)
1600 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1601 matthewc 44 }
1602 jsorg71 286 if (i + 2 < length)
1603     i += 3;
1604     else
1605     i += 2;
1606     length -= i;
1607     /* this will move pointer from start to first character after FE command */
1608     text = &(text[i]);
1609     i = 0;
1610 astrand 64 break;
1611 matty 17
1612 astrand 64 default:
1613     DO_GLYPH(text, i);
1614     i++;
1615     break;
1616 matty 29 }
1617 mmihalik 49 }
1618 jsorg71 278 if (ownbackstore)
1619     {
1620     if (boxcx > 1)
1621     XCopyArea(display, backstore, wnd, gc, boxx,
1622     boxy, boxcx, boxcy, boxx, boxy);
1623     else
1624     XCopyArea(display, backstore, wnd, gc, clipx,
1625     clipy, clipcx, clipcy, clipx, clipy);
1626     }
1627 matty 9 }
1628    
1629 matty 25 void
1630     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1631 matty 9 {
1632 matty 28 Pixmap pix;
1633 matty 9 XImage *image;
1634    
1635 matty 31 if (ownbackstore)
1636     {
1637 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1638 matty 31 }
1639     else
1640     {
1641     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1642     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1643 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1644 matty 31 XFreePixmap(display, pix);
1645     }
1646 matty 28
1647 astrand 64 offset *= bpp / 8;
1648 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1649 matty 28
1650     XDestroyImage(image);
1651 matty 9 }
1652    
1653 matty 25 void
1654     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1655 matty 9 {
1656     XImage *image;
1657 matty 10 uint8 *data;
1658 matty 9
1659 astrand 64 offset *= bpp / 8;
1660     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1661 matty 10 if (data == NULL)
1662     return;
1663 matty 29
1664 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1665 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1666 matty 29
1667 matty 31 if (ownbackstore)
1668     {
1669     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1670     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1671     }
1672     else
1673     {
1674     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1675     }
1676    
1677 matty 9 XFree(image);
1678     }

  ViewVC Help
Powered by ViewVC 1.1.26