/[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 432 - (hide annotations)
Tue Jul 1 09:31:25 2003 UTC (20 years, 10 months ago) by matthewc
File MIME type: text/plain
File size: 38849 byte(s)
Commit of work in progress on channels (so that other people can hack on
RDPSND), in particular:
* channel layer takes care of virtual channel header
* split X dependent parts out of CLIPRDR, simplified IPC implementation
* initial RDPDR implementation

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

  ViewVC Help
Powered by ViewVC 1.1.26