/[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 450 - (hide annotations)
Wed Aug 27 22:51:33 2003 UTC (20 years, 8 months ago) by jsorg71
File MIME type: text/plain
File size: 39903 byte(s)
more g_ prefix for global vars

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 jsorg71 447 extern int g_width;
29     extern int g_height;
30     extern BOOL g_sendmotion;
31     extern BOOL g_fullscreen;
32 jsorg71 450 extern BOOL g_grab_keyboard;
33     extern BOOL g_hide_decorations;
34     extern char g_title[];
35 jsorg71 438 extern int g_server_bpp;
36 jsorg71 450 extern int g_win_button_size;
37 jsorg71 447 BOOL g_enable_compose = False;
38     BOOL g_focused;
39     BOOL g_mouse_in_wnd;
40 matty 10
41 jsorg71 450 Display *g_display;
42     Time g_last_gesturetime;
43     static int g_x_socket;
44     static Screen *g_screen;
45     Window g_wnd;
46     static GC g_gc;
47     static Visual *g_visual;
48     static int g_depth;
49     static int g_bpp;
50     static XIM g_IM;
51     static XIC g_IC;
52     static XModifierKeymap *g_mod_map;
53     static Cursor g_current_cursor;
54     static Atom g_protocol_atom, g_kill_atom;
55 matty 29
56 matty 33 /* endianness */
57 jsorg71 450 static BOOL g_host_be;
58     static BOOL g_xserver_be;
59 matty 33
60     /* software backing store */
61 jsorg71 450 static BOOL g_ownbackstore;
62     static Pixmap g_backstore;
63 matty 31
64 astrand 342 /* Moving in single app mode */
65 jsorg71 450 static BOOL g_moving_wnd;
66     static int g_move_x_offset = 0;
67     static int g_move_y_offset = 0;
68 astrand 342
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 jsorg71 450 XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
94     if (g_ownbackstore) \
95     XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
96 matty 31 }
97    
98 matthewc 296 #define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
99 jsorg71 281 { \
100 jsorg71 450 XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
101 jsorg71 281 }
102    
103 matty 33 /* colour maps */
104 jsorg71 450 BOOL g_owncolmap = False;
105     static Colormap g_xcolmap;
106     static uint32 *g_colmap = NULL;
107 matty 10
108 jsorg71 450 #define TRANSLATE(col) ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : translate_colour(g_colmap[col]) )
109     #define SET_FOREGROUND(col) XSetForeground(g_display, g_gc, TRANSLATE(col));
110     #define SET_BACKGROUND(col) XSetBackground(g_display, g_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 jsorg71 450 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
132     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
133 matty 29
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 jsorg71 450 hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
146 astrand 262 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 jsorg71 450 XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
153 astrand 262 (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 jsorg71 438 switch (g_server_bpp)
222 jsorg71 311 {
223 jsorg71 316 case 15:
224 jsorg71 450 switch (g_bpp)
225 jsorg71 316 {
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 jsorg71 450 switch (g_bpp)
239 jsorg71 311 {
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 jsorg71 450 switch (g_bpp)
252 jsorg71 311 {
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 jsorg71 450 switch (g_bpp)
265 jsorg71 311 {
266     case 16:
267 jsorg71 450 if (g_host_be != g_xserver_be)
268 jsorg71 311 BSWAP16(colour);
269     break;
270    
271     case 24:
272 jsorg71 450 if (g_xserver_be)
273 jsorg71 311 BSWAP24(colour);
274     break;
275    
276     case 32:
277 jsorg71 450 if (g_host_be != g_xserver_be)
278 jsorg71 311 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 jsorg71 450 *(out++) = (uint8) g_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 jsorg71 450 *(out++) = (uint16) g_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 jsorg71 450 value = g_colmap[*(data++)];
308 jsorg71 316 *(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 jsorg71 450 *(out++) = g_colmap[*(data++)];
319 jsorg71 316 }
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 jsorg71 450 int size = width * height * g_bpp / 8;
419 forsberg 415 uint8 *out = (uint8 *) xmalloc(size);
420 matty 29 uint8 *end = out + size;
421    
422 jsorg71 438 switch (g_server_bpp)
423 jsorg71 311 {
424 jsorg71 316 case 24:
425 jsorg71 450 switch (g_bpp)
426 jsorg71 316 {
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 450 switch (g_bpp)
440 jsorg71 316 {
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 jsorg71 450 switch (g_bpp)
456 jsorg71 316 {
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 jsorg71 450 switch (g_bpp)
472 jsorg71 316 {
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 jsorg71 450 KeyCode keycode = XKeysymToKeycode(g_display, keysym);
498 astrand 102
499     if (keycode == NoSymbol)
500     return False;
501    
502     for (modifierpos = 0; modifierpos < 8; modifierpos++)
503     {
504 jsorg71 450 offset = g_mod_map->max_keypermod * modifierpos;
505 astrand 102
506 jsorg71 450 for (key = 0; key < g_mod_map->max_keypermod; key++)
507 astrand 102 {
508 jsorg71 450 if (g_mod_map->modifiermap[offset + key] == keycode)
509 matthewc 203 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 450 g_display = XOpenDisplay(NULL);
524     if (g_display == NULL)
525 jsorg71 81 {
526 matthewc 210 error("Failed to open display: %s\n", XDisplayName(NULL));
527 jsorg71 81 return False;
528     }
529 matthewc 121
530 jsorg71 450 g_x_socket = ConnectionNumber(g_display);
531     g_screen = DefaultScreenOfDisplay(g_display);
532     g_visual = DefaultVisualOfScreen(g_screen);
533     g_depth = DefaultDepthOfScreen(g_screen);
534 matthewc 121
535 jsorg71 450 pfm = XListPixmapFormats(g_display, &i);
536 matthewc 121 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 jsorg71 450 if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))
543 matthewc 121 {
544 jsorg71 450 g_bpp = pfm[i].bits_per_pixel;
545 matthewc 121 }
546     }
547     XFree(pfm);
548     }
549    
550 jsorg71 450 if (g_bpp < 8)
551 matthewc 121 {
552     error("Less than 8 bpp not currently supported.\n");
553 jsorg71 450 XCloseDisplay(g_display);
554 matthewc 121 return False;
555     }
556    
557 jsorg71 450 if (g_owncolmap != True)
558 n-ki 279 {
559 jsorg71 450 g_xcolmap = DefaultColormapOfScreen(g_screen);
560     if (g_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 jsorg71 450 g_gc = XCreateGC(g_display, RootWindowOfScreen(g_screen), 0, NULL);
565 matthewc 121
566 jsorg71 450 if (DoesBackingStore(g_screen) != Always)
567     g_ownbackstore = True;
568 matthewc 121
569     test = 1;
570 jsorg71 450 g_host_be = !(BOOL) (*(uint8 *) (&test));
571     g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
572 matthewc 121
573 jsorg71 447 if ((g_width == 0) || (g_height == 0))
574 astrand 263 {
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 jsorg71 447 g_width = cx;
581     g_height = cy;
582 matthewc 300 }
583     else
584     {
585 matthewc 297 warning("Failed to get workarea: probably your window manager does not support extended hints\n");
586 jsorg71 447 g_width = 800;
587     g_height = 600;
588 astrand 263 }
589     }
590    
591 jsorg71 447 if (g_fullscreen)
592 jsorg71 81 {
593 jsorg71 450 g_width = WidthOfScreen(g_screen);
594     g_height = HeightOfScreen(g_screen);
595 jsorg71 81 }
596 matthewc 121
597 matthewc 160 /* make sure width is a multiple of 4 */
598 jsorg71 447 g_width = (g_width + 3) & ~3;
599 matthewc 160
600 jsorg71 450 if (g_ownbackstore)
601 matthewc 188 {
602 jsorg71 450 g_backstore =
603     XCreatePixmap(g_display, RootWindowOfScreen(g_screen), g_width, g_height,
604     g_depth);
605 matthewc 188
606     /* clear to prevent rubbish being exposed at startup */
607 jsorg71 450 XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
608     XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
609 matthewc 188 }
610    
611 jsorg71 450 g_mod_map = XGetModifierMapping(g_display);
612 matthewc 203
613 jsorg71 447 if (g_enable_compose)
614 jsorg71 450 g_IM = XOpenIM(g_display, NULL, NULL, NULL);
615 matthewc 188
616 matthewc 121 xkeymap_init();
617 matthewc 432 xclip_init();
618 jsorg71 316
619     /* todo take this out when high colour is done */
620 jsorg71 450 printf("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth);
621 jsorg71 316
622 jsorg71 81 return True;
623     }
624 astrand 66
625 matthewc 188 void
626 matthewc 192 ui_deinit(void)
627 matthewc 188 {
628 jsorg71 450 if (g_IM != NULL)
629     XCloseIM(g_IM);
630 matthewc 188
631 jsorg71 450 XFreeModifiermap(g_mod_map);
632 matthewc 203
633 jsorg71 450 if (g_ownbackstore)
634     XFreePixmap(g_display, g_backstore);
635 matthewc 188
636 jsorg71 450 XFreeGC(g_display, g_gc);
637     XCloseDisplay(g_display);
638     g_display = NULL;
639 matthewc 188 }
640    
641 matthewc 121 BOOL
642 matthewc 192 ui_create_window(void)
643 matty 6 {
644 matthewc 121 XSetWindowAttributes attribs;
645 matty 28 XClassHint *classhints;
646     XSizeHints *sizehints;
647 matthewc 188 int wndwidth, wndheight;
648 matthewc 432 long input_mask, ic_input_mask;
649 jsorg71 100 XEvent xevent;
650    
651 jsorg71 450 wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
652     wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
653 matthewc 188
654 jsorg71 450 attribs.background_pixel = BlackPixelOfScreen(g_screen);
655     attribs.backing_store = g_ownbackstore ? NotUseful : Always;
656 jsorg71 447 attribs.override_redirect = g_fullscreen;
657 matthewc 188
658 jsorg71 450 g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, wndwidth, wndheight,
659 matthewc 121 0, CopyFromParent, InputOutput, CopyFromParent,
660     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
661 jsorg71 100
662 jsorg71 450 XStoreName(g_display, g_wnd, g_title);
663 jsorg71 100
664 jsorg71 450 if (g_hide_decorations)
665 astrand 262 mwm_hide_decorations();
666    
667 jsorg71 100 classhints = XAllocClassHint();
668     if (classhints != NULL)
669     {
670     classhints->res_name = classhints->res_class = "rdesktop";
671 jsorg71 450 XSetClassHint(g_display, g_wnd, classhints);
672 jsorg71 100 XFree(classhints);
673     }
674    
675     sizehints = XAllocSizeHints();
676     if (sizehints)
677     {
678     sizehints->flags = PMinSize | PMaxSize;
679 jsorg71 447 sizehints->min_width = sizehints->max_width = g_width;
680     sizehints->min_height = sizehints->max_height = g_height;
681 jsorg71 450 XSetWMNormalHints(g_display, g_wnd, sizehints);
682 jsorg71 100 XFree(sizehints);
683     }
684    
685 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
686 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
687 matthewc 121
688 jsorg71 447 if (g_sendmotion)
689 matthewc 121 input_mask |= PointerMotionMask;
690 jsorg71 450 if (g_ownbackstore)
691 matthewc 121 input_mask |= ExposureMask;
692 jsorg71 450 if (g_fullscreen || g_grab_keyboard)
693 matthewc 250 input_mask |= EnterWindowMask;
694 jsorg71 450 if (g_grab_keyboard)
695 jsorg71 257 input_mask |= LeaveWindowMask;
696 jsorg71 100
697 jsorg71 450 if (g_IM != NULL)
698 matthewc 188 {
699 jsorg71 450 g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
700     XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
701 matthewc 188
702 jsorg71 450 if ((g_IC != NULL)
703     && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
704 matthewc 188 input_mask |= ic_input_mask;
705     }
706    
707 jsorg71 450 XSelectInput(g_display, g_wnd, input_mask);
708     XMapWindow(g_display, g_wnd);
709 jsorg71 100
710 matthewc 208 /* wait for VisibilityNotify */
711 astrand 196 do
712     {
713 jsorg71 450 XMaskEvent(g_display, VisibilityChangeMask, &xevent);
714 astrand 196 }
715 matthewc 208 while (xevent.type != VisibilityNotify);
716 matthewc 123
717 jsorg71 447 g_focused = False;
718     g_mouse_in_wnd = False;
719 jsorg71 257
720 astrand 275 /* handle the WM_DELETE_WINDOW protocol */
721 jsorg71 450 g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
722     g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
723     XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
724 astrand 275
725 matty 10 return True;
726 matty 6 }
727    
728 matty 25 void
729 matthewc 192 ui_destroy_window(void)
730 matty 6 {
731 jsorg71 450 if (g_IC != NULL)
732     XDestroyIC(g_IC);
733 matty 31
734 jsorg71 450 XDestroyWindow(g_display, g_wnd);
735 matty 6 }
736    
737 jsorg71 100 void
738 matthewc 192 xwin_toggle_fullscreen(void)
739 jsorg71 100 {
740 matthewc 188 Pixmap contents = 0;
741 matthewc 123
742 jsorg71 450 if (!g_ownbackstore)
743 matthewc 188 {
744     /* need to save contents of window */
745 jsorg71 450 contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
746     XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
747 matthewc 188 }
748    
749     ui_destroy_window();
750 jsorg71 447 g_fullscreen = !g_fullscreen;
751 matthewc 188 ui_create_window();
752 matthewc 123
753 jsorg71 450 XDefineCursor(g_display, g_wnd, g_current_cursor);
754 matthewc 188
755 jsorg71 450 if (!g_ownbackstore)
756 matthewc 188 {
757 jsorg71 450 XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
758     XFreePixmap(g_display, contents);
759 matthewc 188 }
760 jsorg71 100 }
761    
762 jsorg71 447 /* Process all events in Xlib queue
763 astrand 275 Returns 0 after user quit, 1 otherwise */
764     static int
765 matthewc 192 xwin_process_events(void)
766 matty 9 {
767 n-ki 54 XEvent xevent;
768 matthewc 38 KeySym keysym;
769 matthewc 50 uint16 button, flags;
770 matty 10 uint32 ev_time;
771 astrand 66 key_translation tr;
772     char str[256];
773     Status status;
774 matthewc 203 unsigned int state;
775     Window wdummy;
776     int dummy;
777 matty 9
778 jsorg71 450 while (XPending(g_display) > 0)
779 matty 9 {
780 jsorg71 450 XNextEvent(g_display, &xevent);
781 matthewc 123
782 jsorg71 450 if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
783 astrand 66 {
784 astrand 84 DEBUG_KBD(("Filtering event\n"));
785 astrand 66 continue;
786     }
787    
788 matthewc 50 flags = 0;
789 matty 10
790 n-ki 54 switch (xevent.type)
791 matty 9 {
792 astrand 275 case ClientMessage:
793     /* the window manager told us to quit */
794 jsorg71 450 if ((xevent.xclient.message_type == g_protocol_atom)
795     && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
796 astrand 275 /* Quit */
797     return 0;
798     break;
799    
800 matty 9 case KeyPress:
801 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
802     if (g_IC != NULL)
803 astrand 66 /* Multi_key compatible version */
804     {
805 jsorg71 450 XmbLookupString(g_IC,
806 astrand 435 &xevent.xkey, str, sizeof(str), &keysym,
807     &status);
808 astrand 82 if (!((status == XLookupKeySym) || (status == XLookupBoth)))
809 astrand 66 {
810 astrand 82 error("XmbLookupString failed with status 0x%x\n",
811     status);
812 astrand 66 break;
813     }
814     }
815     else
816     {
817     /* Plain old XLookupString */
818 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
819 astrand 66 XLookupString((XKeyEvent *) & xevent,
820 astrand 82 str, sizeof(str), &keysym, NULL);
821 astrand 66 }
822    
823 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
824     get_ksname(keysym)));
825 astrand 66
826 matthewc 203 ev_time = time(NULL);
827     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
828 astrand 118 break;
829    
830 astrand 66 tr = xkeymap_translate_key(keysym,
831 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
832 astrand 69
833 astrand 66 if (tr.scancode == 0)
834 n-ki 52 break;
835    
836 astrand 449 save_remote_modifiers();
837 astrand 115 ensure_remote_modifiers(ev_time, tr);
838 astrand 449 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
839     restore_remote_modifiers();
840 astrand 115
841 astrand 66 break;
842 matthewc 203
843 astrand 66 case KeyRelease:
844 jsorg71 450 g_last_gesturetime = xevent.xkey.time;
845 astrand 66 XLookupString((XKeyEvent *) & xevent, str,
846     sizeof(str), &keysym, NULL);
847 n-ki 52
848 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
849 matthewc 203 get_ksname(keysym)));
850 n-ki 52
851 matthewc 203 ev_time = time(NULL);
852     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
853 astrand 118 break;
854    
855 astrand 66 tr = xkeymap_translate_key(keysym,
856 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
857 astrand 66
858     if (tr.scancode == 0)
859     break;
860    
861 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
862 matty 9 break;
863    
864     case ButtonPress:
865 matthewc 50 flags = MOUSE_FLAG_DOWN;
866     /* fall through */
867 matty 9
868     case ButtonRelease:
869 jsorg71 450 g_last_gesturetime = xevent.xbutton.time;
870 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
871 matty 9 if (button == 0)
872     break;
873    
874 astrand 328 /* If win_button_size is nonzero, enable single app mode */
875 jsorg71 450 if (xevent.xbutton.y < g_win_button_size)
876 astrand 328 {
877 astrand 342 /* Stop moving window when button is released, regardless of cursor position */
878 jsorg71 450 if (g_moving_wnd && (xevent.type == ButtonRelease))
879     g_moving_wnd = False;
880 astrand 332
881 astrand 342 /* Check from right to left: */
882    
883 jsorg71 450 if (xevent.xbutton.x >= g_width - g_win_button_size)
884 astrand 328 {
885 astrand 331 /* The close button, continue */
886 astrand 328 ;
887     }
888 jsorg71 450 else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
889 astrand 328 {
890     /* The maximize/restore button. Do not send to
891     server. It might be a good idea to change the
892 jsorg71 447 cursor or give some other visible indication
893 astrand 328 that rdesktop inhibited this click */
894     break;
895     }
896 jsorg71 450 else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
897 astrand 328 {
898     /* The minimize button. Iconify window. */
899 jsorg71 450 XIconifyWindow(g_display, g_wnd,
900     DefaultScreen(g_display));
901 astrand 328 break;
902     }
903 jsorg71 450 else if (xevent.xbutton.x <= g_win_button_size)
904 astrand 342 {
905     /* The system menu. Ignore. */
906     break;
907     }
908 astrand 332 else
909     {
910 astrand 342 /* The title bar. */
911 jsorg71 447 if ((xevent.type == ButtonPress) && !g_fullscreen
912 jsorg71 450 && g_hide_decorations)
913 astrand 342 {
914 jsorg71 450 g_moving_wnd = True;
915     g_move_x_offset = xevent.xbutton.x;
916     g_move_y_offset = xevent.xbutton.y;
917 astrand 342 }
918 astrand 332 break;
919 astrand 342
920 astrand 332 }
921 astrand 328 }
922    
923 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
924 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
925 matty 10 break;
926    
927     case MotionNotify:
928 jsorg71 450 if (g_moving_wnd)
929 astrand 342 {
930 jsorg71 450 XMoveWindow(g_display, g_wnd,
931     xevent.xmotion.x_root - g_move_x_offset,
932     xevent.xmotion.y_root - g_move_y_offset);
933 astrand 342 break;
934     }
935    
936 jsorg71 447 if (g_fullscreen && !g_focused)
937 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
938 jsorg71 288 CurrentTime);
939 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
940 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
941 matty 28 break;
942    
943 matthewc 194 case FocusIn:
944 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
945     break;
946 jsorg71 447 g_focused = True;
947 jsorg71 450 XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy,
948 astrand 261 &dummy, &dummy, &state);
949 matthewc 203 reset_modifier_keys(state);
950 jsorg71 450 if (g_grab_keyboard && g_mouse_in_wnd)
951     XGrabKeyboard(g_display, g_wnd, True,
952 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
953 matty 28 break;
954    
955 matthewc 194 case FocusOut:
956 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
957     break;
958 jsorg71 447 g_focused = False;
959 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
960 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
961 matty 28 break;
962 matty 31
963 matthewc 250 case EnterNotify:
964     /* we only register for this event when in fullscreen mode */
965 jsorg71 257 /* or grab_keyboard */
966 jsorg71 447 g_mouse_in_wnd = True;
967     if (g_fullscreen)
968 jsorg71 257 {
969 jsorg71 450 XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
970 astrand 261 CurrentTime);
971 jsorg71 257 break;
972     }
973 jsorg71 447 if (g_focused)
974 jsorg71 450 XGrabKeyboard(g_display, g_wnd, True,
975 jsorg71 257 GrabModeAsync, GrabModeAsync, CurrentTime);
976 matthewc 250 break;
977    
978 matthewc 253 case LeaveNotify:
979 jsorg71 257 /* we only register for this event when grab_keyboard */
980 jsorg71 447 g_mouse_in_wnd = False;
981 jsorg71 450 XUngrabKeyboard(g_display, CurrentTime);
982 matthewc 253 break;
983    
984 matty 31 case Expose:
985 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc,
986 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
987 astrand 64 xevent.xexpose.width,
988     xevent.xexpose.height,
989 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
990 matty 31 break;
991 astrand 119
992     case MappingNotify:
993     /* Refresh keyboard mapping if it has changed. This is important for
994     Xvnc, since it allocates keycodes dynamically */
995     if (xevent.xmapping.request == MappingKeyboard
996     || xevent.xmapping.request == MappingModifier)
997     XRefreshKeyboardMapping(&xevent.xmapping);
998 matthewc 203
999     if (xevent.xmapping.request == MappingModifier)
1000     {
1001 jsorg71 450 XFreeModifiermap(g_mod_map);
1002     g_mod_map = XGetModifierMapping(g_display);
1003 matthewc 203 }
1004 astrand 119 break;
1005 matthewc 432
1006 astrand 435 /* clipboard stuff */
1007 forsberg 415 case SelectionNotify:
1008 matthewc 432 xclip_handle_SelectionNotify(&xevent.xselection);
1009 forsberg 415 break;
1010     case SelectionRequest:
1011 matthewc 432 xclip_handle_SelectionRequest(&xevent.xselectionrequest);
1012 forsberg 415 break;
1013 matthewc 432 case SelectionClear:
1014     xclip_handle_SelectionClear();
1015     break;
1016 forsberg 415 case PropertyNotify:
1017 matthewc 432 xclip_handle_PropertyNotify(&xevent.xproperty);
1018 forsberg 415 break;
1019 matty 9 }
1020     }
1021 astrand 275 /* Keep going */
1022     return 1;
1023 matty 9 }
1024    
1025 astrand 275 /* Returns 0 after user quit, 1 otherwise */
1026     int
1027 matty 33 ui_select(int rdp_socket)
1028     {
1029 jsorg71 450 int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
1030 matty 33 fd_set rfds;
1031    
1032     FD_ZERO(&rfds);
1033    
1034     while (True)
1035     {
1036 matthewc 121 /* Process any events already waiting */
1037 astrand 275 if (!xwin_process_events())
1038     /* User quit */
1039     return 0;
1040 astrand 119
1041 matty 33 FD_ZERO(&rfds);
1042     FD_SET(rdp_socket, &rfds);
1043 jsorg71 450 FD_SET(g_x_socket, &rfds);
1044 matty 33
1045     switch (select(n, &rfds, NULL, NULL, NULL))
1046     {
1047     case -1:
1048     error("select: %s\n", strerror(errno));
1049    
1050     case 0:
1051     continue;
1052     }
1053    
1054     if (FD_ISSET(rdp_socket, &rfds))
1055 astrand 275 return 1;
1056 matty 33 }
1057     }
1058    
1059     void
1060 matty 25 ui_move_pointer(int x, int y)
1061 matty 9 {
1062 jsorg71 450 XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
1063 matty 9 }
1064    
1065 matty 25 HBITMAP
1066 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
1067 matty 6 {
1068     XImage *image;
1069 matty 9 Pixmap bitmap;
1070 matty 28 uint8 *tdata;
1071 matty 29
1072 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1073     bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
1074     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1075     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1076 matty 6
1077 jsorg71 450 XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
1078 matty 9
1079     XFree(image);
1080 jsorg71 450 if (!g_owncolmap)
1081 n-ki 279 xfree(tdata);
1082 matty 24 return (HBITMAP) bitmap;
1083 matty 6 }
1084    
1085 matty 25 void
1086 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
1087 matty 6 {
1088 matty 10 XImage *image;
1089 matty 29 uint8 *tdata;
1090 jsorg71 450 tdata = (g_owncolmap ? data : translate_image(width, height, data));
1091     image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1092     (char *) tdata, width, height, g_server_bpp == 8 ? 8 : g_bpp, 0);
1093 matty 28
1094 jsorg71 450 if (g_ownbackstore)
1095 matty 31 {
1096 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1097     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1098 matty 31 }
1099     else
1100     {
1101 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1102 matty 31 }
1103 matty 29
1104 matty 24 XFree(image);
1105 jsorg71 450 if (!g_owncolmap)
1106 n-ki 279 xfree(tdata);
1107 matty 6 }
1108    
1109 matty 25 void
1110     ui_destroy_bitmap(HBITMAP bmp)
1111 matty 6 {
1112 jsorg71 450 XFreePixmap(g_display, (Pixmap) bmp);
1113 matty 10 }
1114    
1115 matty 25 HGLYPH
1116 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
1117 matty 10 {
1118 matty 9 XImage *image;
1119     Pixmap bitmap;
1120     int scanline;
1121     GC gc;
1122 matty 6
1123 matty 9 scanline = (width + 7) / 8;
1124 matty 6
1125 jsorg71 450 bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
1126     gc = XCreateGC(g_display, bitmap, 0, NULL);
1127 matty 9
1128 jsorg71 450 image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
1129 astrand 73 width, height, 8, scanline);
1130 matty 23 image->byte_order = MSBFirst;
1131     image->bitmap_bit_order = MSBFirst;
1132     XInitImage(image);
1133    
1134 jsorg71 450 XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
1135 matty 29
1136 matty 9 XFree(image);
1137 jsorg71 450 XFreeGC(g_display, gc);
1138 astrand 64 return (HGLYPH) bitmap;
1139 matty 6 }
1140 matty 7
1141 matty 25 void
1142     ui_destroy_glyph(HGLYPH glyph)
1143 matty 7 {
1144 jsorg71 450 XFreePixmap(g_display, (Pixmap) glyph);
1145 matty 9 }
1146    
1147 matty 29 HCURSOR
1148 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
1149     uint8 * andmask, uint8 * xormask)
1150 matty 9 {
1151 matty 29 HGLYPH maskglyph, cursorglyph;
1152     XColor bg, fg;
1153     Cursor xcursor;
1154     uint8 *cursor, *pcursor;
1155     uint8 *mask, *pmask;
1156     uint8 nextbit;
1157     int scanline, offset;
1158     int i, j;
1159    
1160     scanline = (width + 7) / 8;
1161     offset = scanline * height;
1162    
1163 forsberg 415 cursor = (uint8 *) xmalloc(offset);
1164 matty 29 memset(cursor, 0, offset);
1165    
1166 forsberg 415 mask = (uint8 *) xmalloc(offset);
1167 matty 29 memset(mask, 0, offset);
1168    
1169     /* approximate AND and XOR masks with a monochrome X pointer */
1170     for (i = 0; i < height; i++)
1171 matty 7 {
1172 matty 29 offset -= scanline;
1173     pcursor = &cursor[offset];
1174     pmask = &mask[offset];
1175    
1176     for (j = 0; j < scanline; j++)
1177 matty 28 {
1178 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
1179     {
1180     if (xormask[0] || xormask[1] || xormask[2])
1181     {
1182     *pcursor |= (~(*andmask) & nextbit);
1183     *pmask |= nextbit;
1184     }
1185     else
1186     {
1187     *pcursor |= ((*andmask) & nextbit);
1188     *pmask |= (~(*andmask) & nextbit);
1189     }
1190    
1191     xormask += 3;
1192     }
1193    
1194     andmask++;
1195     pcursor++;
1196     pmask++;
1197 matty 28 }
1198 matty 7 }
1199 matty 29
1200     fg.red = fg.blue = fg.green = 0xffff;
1201     bg.red = bg.blue = bg.green = 0x0000;
1202     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
1203    
1204     cursorglyph = ui_create_glyph(width, height, cursor);
1205     maskglyph = ui_create_glyph(width, height, mask);
1206    
1207 astrand 66 xcursor =
1208 jsorg71 450 XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
1209 astrand 66 (Pixmap) maskglyph, &fg, &bg, x, y);
1210 astrand 64
1211 matty 29 ui_destroy_glyph(maskglyph);
1212     ui_destroy_glyph(cursorglyph);
1213     xfree(mask);
1214     xfree(cursor);
1215 astrand 64 return (HCURSOR) xcursor;
1216 matty 29 }
1217    
1218     void
1219     ui_set_cursor(HCURSOR cursor)
1220     {
1221 jsorg71 450 g_current_cursor = (Cursor) cursor;
1222     XDefineCursor(g_display, g_wnd, g_current_cursor);
1223 matty 29 }
1224    
1225     void
1226     ui_destroy_cursor(HCURSOR cursor)
1227     {
1228 jsorg71 450 XFreeCursor(g_display, (Cursor) cursor);
1229 matty 29 }
1230    
1231     #define MAKE_XCOLOR(xc,c) \
1232     (xc)->red = ((c)->red << 8) | (c)->red; \
1233     (xc)->green = ((c)->green << 8) | (c)->green; \
1234     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
1235     (xc)->flags = DoRed | DoGreen | DoBlue;
1236    
1237 n-ki 279
1238 matty 29 HCOLOURMAP
1239 astrand 64 ui_create_colourmap(COLOURMAP * colours)
1240 matty 29 {
1241     COLOURENTRY *entry;
1242     int i, ncolours = colours->ncolours;
1243 jsorg71 450 if (!g_owncolmap)
1244 matty 28 {
1245 jsorg71 450 uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
1246 n-ki 279 XColor xentry;
1247     XColor xc_cache[256];
1248     uint32 colour;
1249     int colLookup = 256;
1250     for (i = 0; i < ncolours; i++)
1251 matty 28 {
1252 n-ki 279 entry = &colours->colours[i];
1253     MAKE_XCOLOR(&xentry, entry);
1254 matty 7
1255 jsorg71 450 if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
1256 astrand 196 {
1257 n-ki 279 /* Allocation failed, find closest match. */
1258     int j = 256;
1259     int nMinDist = 3 * 256 * 256;
1260     long nDist = nMinDist;
1261 matty 28
1262 n-ki 279 /* only get the colors once */
1263     while (colLookup--)
1264 astrand 196 {
1265 n-ki 279 xc_cache[colLookup].pixel = colLookup;
1266     xc_cache[colLookup].red = xc_cache[colLookup].green =
1267     xc_cache[colLookup].blue = 0;
1268     xc_cache[colLookup].flags = 0;
1269 jsorg71 450 XQueryColor(g_display,
1270     DefaultColormap(g_display,
1271     DefaultScreen(g_display)),
1272 n-ki 279 &xc_cache[colLookup]);
1273 n-ki 185 }
1274 n-ki 279 colLookup = 0;
1275    
1276     /* approximate the pixel */
1277     while (j--)
1278 astrand 196 {
1279 n-ki 279 if (xc_cache[j].flags)
1280     {
1281     nDist = ((long) (xc_cache[j].red >> 8) -
1282     (long) (xentry.red >> 8)) *
1283     ((long) (xc_cache[j].red >> 8) -
1284     (long) (xentry.red >> 8)) +
1285     ((long) (xc_cache[j].green >> 8) -
1286     (long) (xentry.green >> 8)) *
1287     ((long) (xc_cache[j].green >> 8) -
1288     (long) (xentry.green >> 8)) +
1289     ((long) (xc_cache[j].blue >> 8) -
1290     (long) (xentry.blue >> 8)) *
1291     ((long) (xc_cache[j].blue >> 8) -
1292     (long) (xentry.blue >> 8));
1293     }
1294     if (nDist < nMinDist)
1295     {
1296     nMinDist = nDist;
1297     xentry.pixel = j;
1298     }
1299 n-ki 185 }
1300     }
1301 n-ki 279 colour = xentry.pixel;
1302    
1303     /* update our cache */
1304     if (xentry.pixel < 256)
1305     {
1306     xc_cache[xentry.pixel].red = xentry.red;
1307     xc_cache[xentry.pixel].green = xentry.green;
1308     xc_cache[xentry.pixel].blue = xentry.blue;
1309    
1310     }
1311    
1312    
1313     /* byte swap here to make translate_image faster */
1314     map[i] = translate_colour(colour);
1315 n-ki 185 }
1316 n-ki 279 return map;
1317     }
1318     else
1319     {
1320     XColor *xcolours, *xentry;
1321     Colormap map;
1322 matty 29
1323 forsberg 415 xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
1324 n-ki 279 for (i = 0; i < ncolours; i++)
1325 astrand 196 {
1326 n-ki 279 entry = &colours->colours[i];
1327     xentry = &xcolours[i];
1328     xentry->pixel = i;
1329     MAKE_XCOLOR(xentry, entry);
1330 matty 29 }
1331    
1332 jsorg71 450 map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
1333     XStoreColors(g_display, map, xcolours, ncolours);
1334 n-ki 185
1335 n-ki 279 xfree(xcolours);
1336     return (HCOLOURMAP) map;
1337 matty 29 }
1338 matty 7 }
1339    
1340 matty 25 void
1341     ui_destroy_colourmap(HCOLOURMAP map)
1342 matty 7 {
1343 jsorg71 450 if (!g_owncolmap)
1344 n-ki 279 xfree(map);
1345     else
1346 jsorg71 450 XFreeColormap(g_display, (Colormap) map);
1347 matty 7 }
1348    
1349 matty 25 void
1350     ui_set_colourmap(HCOLOURMAP map)
1351 matty 7 {
1352 jsorg71 450 if (!g_owncolmap)
1353 astrand 448 {
1354 jsorg71 450 if (g_colmap)
1355     xfree(g_colmap);
1356 astrand 448
1357 jsorg71 450 g_colmap = (uint32 *) map;
1358 astrand 448 }
1359 n-ki 279 else
1360 jsorg71 450 XSetWindowColormap(g_display, g_wnd, (Colormap) map);
1361 matty 7 }
1362    
1363 matty 25 void
1364     ui_set_clip(int x, int y, int cx, int cy)
1365 matty 7 {
1366 matty 9 XRectangle rect;
1367 matty 7
1368 matty 9 rect.x = x;
1369     rect.y = y;
1370     rect.width = cx;
1371     rect.height = cy;
1372 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1373 matty 9 }
1374 matty 7
1375 matty 25 void
1376 matthewc 192 ui_reset_clip(void)
1377 matty 9 {
1378     XRectangle rect;
1379    
1380     rect.x = 0;
1381     rect.y = 0;
1382 jsorg71 447 rect.width = g_width;
1383     rect.height = g_height;
1384 jsorg71 450 XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
1385 matty 7 }
1386    
1387 matty 25 void
1388 matthewc 192 ui_bell(void)
1389 matty 10 {
1390 jsorg71 450 XBell(g_display, 0);
1391 matty 10 }
1392    
1393 matty 25 void
1394     ui_destblt(uint8 opcode,
1395     /* dest */ int x, int y, int cx, int cy)
1396 matty 9 {
1397 matty 29 SET_FUNCTION(opcode);
1398 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1399 matty 29 RESET_FUNCTION(opcode);
1400 matty 9 }
1401    
1402 jsorg71 373 static uint8 hatch_patterns[] = {
1403 forsberg 415 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
1404     0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
1405     0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
1406     0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
1407     0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
1408     0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
1409 jsorg71 373 };
1410    
1411 matty 25 void
1412     ui_patblt(uint8 opcode,
1413     /* dest */ int x, int y, int cx, int cy,
1414 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1415 matty 9 {
1416     Pixmap fill;
1417 jsorg71 59 uint8 i, ipattern[8];
1418 matty 9
1419 matty 29 SET_FUNCTION(opcode);
1420 matty 9
1421     switch (brush->style)
1422     {
1423 matty 24 case 0: /* Solid */
1424 matty 29 SET_FOREGROUND(fgcolour);
1425 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1426 matty 9 break;
1427    
1428 jsorg71 373 case 2: /* Hatch */
1429 forsberg 415 fill = (Pixmap) ui_create_glyph(8, 8,
1430     hatch_patterns + brush->pattern[0] * 8);
1431 jsorg71 373 SET_FOREGROUND(bgcolour);
1432     SET_BACKGROUND(fgcolour);
1433 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1434     XSetStipple(g_display, g_gc, fill);
1435     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1436 jsorg71 373 FILL_RECTANGLE(x, y, cx, cy);
1437 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1438     XSetTSOrigin(g_display, g_gc, 0, 0);
1439 jsorg71 373 ui_destroy_glyph((HGLYPH) fill);
1440     break;
1441    
1442 matty 24 case 3: /* Pattern */
1443 jsorg71 59 for (i = 0; i != 8; i++)
1444     ipattern[7 - i] = brush->pattern[i];
1445     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
1446 matty 9
1447 matty 29 SET_FOREGROUND(bgcolour);
1448     SET_BACKGROUND(fgcolour);
1449 jsorg71 450 XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
1450     XSetStipple(g_display, g_gc, fill);
1451     XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
1452 matty 9
1453 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1454 matty 9
1455 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1456     XSetTSOrigin(g_display, g_gc, 0, 0);
1457 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1458 matty 9 break;
1459    
1460     default:
1461 matty 30 unimpl("brush %d\n", brush->style);
1462 matty 9 }
1463 matty 29
1464     RESET_FUNCTION(opcode);
1465 matty 9 }
1466    
1467 matty 25 void
1468     ui_screenblt(uint8 opcode,
1469     /* dest */ int x, int y, int cx, int cy,
1470     /* src */ int srcx, int srcy)
1471 matty 9 {
1472 matty 29 SET_FUNCTION(opcode);
1473 jsorg71 450 XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1474     if (g_ownbackstore)
1475     XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1476 matty 29 RESET_FUNCTION(opcode);
1477 matty 9 }
1478    
1479 matty 25 void
1480     ui_memblt(uint8 opcode,
1481     /* dest */ int x, int y, int cx, int cy,
1482     /* src */ HBITMAP src, int srcx, int srcy)
1483 matty 9 {
1484 matty 29 SET_FUNCTION(opcode);
1485 jsorg71 450 XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
1486     if (g_ownbackstore)
1487     XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
1488 matty 29 RESET_FUNCTION(opcode);
1489 matty 9 }
1490    
1491 matty 25 void
1492     ui_triblt(uint8 opcode,
1493     /* dest */ int x, int y, int cx, int cy,
1494     /* src */ HBITMAP src, int srcx, int srcy,
1495 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1496 matty 9 {
1497     /* This is potentially difficult to do in general. Until someone
1498 matty 10 comes up with a more efficient way of doing it I am using cases. */
1499 matty 9
1500     switch (opcode)
1501     {
1502 matty 24 case 0x69: /* PDSxxn */
1503 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1504 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1505 matty 16 break;
1506    
1507 matty 24 case 0xb8: /* PSDPxax */
1508 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1509 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1510 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1511 matty 9 break;
1512    
1513 matty 29 case 0xc0: /* PSa */
1514 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1515 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1516 matty 28 break;
1517    
1518 matty 9 default:
1519 matty 30 unimpl("triblt 0x%x\n", opcode);
1520 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1521 matty 9 }
1522     }
1523    
1524 matty 25 void
1525     ui_line(uint8 opcode,
1526     /* dest */ int startx, int starty, int endx, int endy,
1527 astrand 64 /* pen */ PEN * pen)
1528 matty 9 {
1529 matty 29 SET_FUNCTION(opcode);
1530     SET_FOREGROUND(pen->colour);
1531 jsorg71 450 XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
1532     if (g_ownbackstore)
1533     XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
1534 matty 29 RESET_FUNCTION(opcode);
1535 matty 9 }
1536    
1537 matty 25 void
1538     ui_rect(
1539     /* dest */ int x, int y, int cx, int cy,
1540     /* brush */ int colour)
1541 matty 9 {
1542 matty 29 SET_FOREGROUND(colour);
1543 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1544 matty 9 }
1545    
1546 jsorg71 278 /* warning, this function only draws on wnd or backstore, not both */
1547 matty 25 void
1548     ui_draw_glyph(int mixmode,
1549     /* dest */ int x, int y, int cx, int cy,
1550 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1551     int bgcolour, int fgcolour)
1552 matty 9 {
1553 matty 29 SET_FOREGROUND(fgcolour);
1554     SET_BACKGROUND(bgcolour);
1555 matty 9
1556 jsorg71 450 XSetFillStyle(g_display, g_gc,
1557 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1558 jsorg71 450 XSetStipple(g_display, g_gc, (Pixmap) glyph);
1559     XSetTSOrigin(g_display, g_gc, x, y);
1560 matty 9
1561 matthewc 296 FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
1562 matty 9
1563 jsorg71 450 XSetFillStyle(g_display, g_gc, FillSolid);
1564 matty 9 }
1565    
1566 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1567     {\
1568     glyph = cache_get_font (font, ttext[idx]);\
1569     if (!(flags & TEXT2_IMPLICIT_X))\
1570     {\
1571     xyoffset = ttext[++idx];\
1572     if ((xyoffset & 0x80))\
1573     {\
1574     if (flags & TEXT2_VERTICAL) \
1575 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1576 mmihalik 49 else\
1577 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1578     idx += 2;\
1579 mmihalik 49 }\
1580     else\
1581     {\
1582     if (flags & TEXT2_VERTICAL) \
1583     y += xyoffset;\
1584     else\
1585     x += xyoffset;\
1586     }\
1587     }\
1588     if (glyph != NULL)\
1589     {\
1590 matthewc 299 ui_draw_glyph (mixmode, x + glyph->offset,\
1591     y + glyph->baseline,\
1592 mmihalik 49 glyph->width, glyph->height,\
1593     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1594     if (flags & TEXT2_IMPLICIT_X)\
1595     x += glyph->width;\
1596     }\
1597     }
1598    
1599 matty 25 void
1600     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1601 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1602     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1603 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1604 matty 9 {
1605 matty 10 FONTGLYPH *glyph;
1606 mmihalik 49 int i, j, xyoffset;
1607     DATABLOB *entry;
1608 matty 9
1609 matty 29 SET_FOREGROUND(bgcolour);
1610 matty 28
1611 matty 9 if (boxcx > 1)
1612 matty 31 {
1613 matthewc 296 FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
1614 matty 31 }
1615 matty 17 else if (mixmode == MIX_OPAQUE)
1616 matty 31 {
1617 matthewc 296 FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
1618 matty 31 }
1619 matty 9
1620     /* Paint text, character by character */
1621 astrand 64 for (i = 0; i < length;)
1622     {
1623     switch (text[i])
1624     {
1625     case 0xff:
1626     if (i + 2 < length)
1627 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1628 astrand 64 else
1629     {
1630     error("this shouldn't be happening\n");
1631 astrand 265 exit(1);
1632 astrand 64 }
1633     /* this will move pointer from start to first character after FF command */
1634     length -= i + 3;
1635     text = &(text[i + 3]);
1636     i = 0;
1637 mmihalik 49 break;
1638 matty 9
1639 astrand 64 case 0xfe:
1640     entry = cache_get_text(text[i + 1]);
1641     if (entry != NULL)
1642     {
1643     if ((((uint8 *) (entry->data))[1] ==
1644 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1645 astrand 64 {
1646     if (flags & TEXT2_VERTICAL)
1647     y += text[i + 2];
1648     else
1649     x += text[i + 2];
1650     }
1651     for (j = 0; j < entry->size; j++)
1652 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1653 matthewc 44 }
1654 jsorg71 286 if (i + 2 < length)
1655     i += 3;
1656     else
1657     i += 2;
1658     length -= i;
1659     /* this will move pointer from start to first character after FE command */
1660     text = &(text[i]);
1661     i = 0;
1662 astrand 64 break;
1663 matty 17
1664 astrand 64 default:
1665     DO_GLYPH(text, i);
1666     i++;
1667     break;
1668 matty 29 }
1669 mmihalik 49 }
1670 jsorg71 450 if (g_ownbackstore)
1671 jsorg71 278 {
1672     if (boxcx > 1)
1673 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
1674 jsorg71 278 boxy, boxcx, boxcy, boxx, boxy);
1675     else
1676 jsorg71 450 XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
1677 jsorg71 278 clipy, clipcx, clipcy, clipx, clipy);
1678     }
1679 matty 9 }
1680    
1681 matty 25 void
1682     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1683 matty 9 {
1684 matty 28 Pixmap pix;
1685 matty 9 XImage *image;
1686    
1687 jsorg71 450 if (g_ownbackstore)
1688 matty 31 {
1689 jsorg71 450 image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1690 matty 31 }
1691     else
1692     {
1693 jsorg71 450 pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
1694     XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
1695     image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1696     XFreePixmap(g_display, pix);
1697 matty 31 }
1698 matty 28
1699 jsorg71 450 offset *= g_bpp / 8;
1700     cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
1701 matty 28
1702     XDestroyImage(image);
1703 matty 9 }
1704    
1705 matty 25 void
1706     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1707 matty 9 {
1708     XImage *image;
1709 matty 10 uint8 *data;
1710 matty 9
1711 jsorg71 450 offset *= g_bpp / 8;
1712     data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
1713 matty 10 if (data == NULL)
1714     return;
1715 matty 29
1716 jsorg71 450 image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
1717     (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);
1718 matty 29
1719 jsorg71 450 if (g_ownbackstore)
1720 matty 31 {
1721 jsorg71 450 XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
1722     XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
1723 matty 31 }
1724     else
1725     {
1726 jsorg71 450 XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
1727 matty 31 }
1728    
1729 matty 9 XFree(image);
1730     }

  ViewVC Help
Powered by ViewVC 1.1.26