/[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 262 - (hide annotations)
Mon Nov 18 15:37:20 2002 UTC (21 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 28088 byte(s)
Support for hiding WM decorations

1 matty 6 /*
2     rdesktop: A Remote Desktop Protocol client.
3 matthewc 38 User interface services - X Window System
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
5 n-ki 52
6 matty 6 This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 n-ki 52
11 matty 6 This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15 n-ki 52
16 matty 6 You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21 matty 10 #include <X11/Xlib.h>
22 matty 28 #include <X11/Xutil.h>
23 matty 10 #include <time.h>
24 matty 33 #include <errno.h>
25 matty 10 #include "rdesktop.h"
26 matty 6
27 matty 10 extern int width;
28     extern int height;
29 matty 29 extern BOOL sendmotion;
30 matty 28 extern BOOL fullscreen;
31 astrand 76 extern BOOL grab_keyboard;
32 astrand 262 extern BOOL hide_decorations;
33 jsorg71 100 extern char title[];
34 matthewc 188 BOOL enable_compose = False;
35 jsorg71 257 BOOL focused;
36     BOOL mouse_in_wnd;
37 matty 10
38 matthewc 121 Display *display;
39 matty 33 static int x_socket;
40 matthewc 121 static Screen *screen;
41 matty 10 static Window wnd;
42     static GC gc;
43     static Visual *visual;
44 matty 29 static int depth;
45     static int bpp;
46 matthewc 188 static XIM IM;
47     static XIC IC;
48 matthewc 203 static XModifierKeymap *mod_map;
49 matthewc 188 static Cursor current_cursor;
50 matty 29
51 matty 33 /* endianness */
52     static BOOL host_be;
53     static BOOL xserver_be;
54    
55     /* software backing store */
56 matty 31 static BOOL ownbackstore;
57     static Pixmap backstore;
58    
59 astrand 262 /* MWM decorations */
60     #define MWM_HINTS_DECORATIONS (1L << 1)
61     #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
62     typedef struct
63     {
64     unsigned long flags;
65     unsigned long functions;
66     unsigned long decorations;
67     long inputMode;
68     unsigned long status;
69     }
70     PropMotifWmHints;
71    
72    
73 matty 31 #define FILL_RECTANGLE(x,y,cx,cy)\
74     { \
75     XFillRectangle(display, wnd, gc, x, y, cx, cy); \
76     if (ownbackstore) \
77     XFillRectangle(display, backstore, gc, x, y, cx, cy); \
78     }
79    
80 matty 33 /* colour maps */
81 matty 29 static Colormap xcolmap;
82 matty 28 static uint32 *colmap;
83 matty 10
84 n-ki 185 #define SET_FOREGROUND(col) XSetForeground(display, gc, translate_colour(colmap[col]));
85     #define SET_BACKGROUND(col) XSetBackground(display, gc, translate_colour(colmap[col]));
86 matty 28
87     static int rop2_map[] = {
88     GXclear, /* 0 */
89     GXnor, /* DPon */
90     GXandInverted, /* DPna */
91     GXcopyInverted, /* Pn */
92     GXandReverse, /* PDna */
93     GXinvert, /* Dn */
94     GXxor, /* DPx */
95     GXnand, /* DPan */
96     GXand, /* DPa */
97     GXequiv, /* DPxn */
98     GXnoop, /* D */
99     GXorInverted, /* DPno */
100     GXcopy, /* P */
101     GXorReverse, /* PDno */
102     GXor, /* DPo */
103     GXset /* 1 */
104     };
105    
106 matty 29 #define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, rop2_map[rop2]); }
107     #define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(display, gc, GXcopy); }
108    
109 astrand 262 void
110     mwm_hide_decorations(void)
111     {
112     PropMotifWmHints motif_hints;
113     Atom hintsatom;
114    
115     /* setup the property */
116     motif_hints.flags = MWM_HINTS_DECORATIONS;
117     motif_hints.decorations = 0;
118    
119     /* get the atom for the property */
120     hintsatom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
121     if (!hintsatom)
122     {
123     error("Failed to get atom _MOTIF_WM_HINTS\n");
124     return;
125     }
126    
127     XChangeProperty(display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
128     (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
129     }
130    
131 matty 28 static void
132 astrand 64 translate8(uint8 * data, uint8 * out, uint8 * end)
133 matty 28 {
134 matty 29 while (out < end)
135 astrand 64 *(out++) = (uint8) colmap[*(data++)];
136 matty 29 }
137 matty 28
138 matty 29 static void
139 astrand 64 translate16(uint8 * data, uint16 * out, uint16 * end)
140 matty 29 {
141     while (out < end)
142 astrand 64 *(out++) = (uint16) colmap[*(data++)];
143 matty 29 }
144    
145 matty 33 /* little endian - conversion happens when colourmap is built */
146 matty 29 static void
147 astrand 64 translate24(uint8 * data, uint8 * out, uint8 * end)
148 matty 29 {
149     uint32 value;
150    
151     while (out < end)
152 matty 28 {
153 matty 29 value = colmap[*(data++)];
154     *(out++) = value;
155     *(out++) = value >> 8;
156     *(out++) = value >> 16;
157 matty 28 }
158     }
159    
160     static void
161 astrand 64 translate32(uint8 * data, uint32 * out, uint32 * end)
162 matty 28 {
163 matty 29 while (out < end)
164     *(out++) = colmap[*(data++)];
165 matty 28 }
166    
167 matty 29 static uint8 *
168 astrand 64 translate_image(int width, int height, uint8 * data)
169 matty 28 {
170 astrand 64 int size = width * height * bpp / 8;
171 matty 29 uint8 *out = xmalloc(size);
172     uint8 *end = out + size;
173    
174     switch (bpp)
175     {
176     case 8:
177     translate8(data, out, end);
178     break;
179    
180     case 16:
181 astrand 64 translate16(data, (uint16 *) out, (uint16 *) end);
182 matty 29 break;
183    
184     case 24:
185     translate24(data, out, end);
186     break;
187    
188     case 32:
189 astrand 64 translate32(data, (uint32 *) out, (uint32 *) end);
190 matty 29 break;
191     }
192    
193     return out;
194 matty 28 }
195    
196 matty 35 #define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
197     #define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | ((x >> 8) & 0xff00)); }
198     #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
199     x = (x << 16) | (x >> 16); }
200 matty 29
201 matty 33 static uint32
202     translate_colour(uint32 colour)
203     {
204     switch (bpp)
205     {
206     case 16:
207     if (host_be != xserver_be)
208     BSWAP16(colour);
209     break;
210 matty 29
211 matty 33 case 24:
212     if (xserver_be)
213     BSWAP24(colour);
214     break;
215    
216     case 32:
217     if (host_be != xserver_be)
218     BSWAP32(colour);
219     break;
220     }
221    
222     return colour;
223     }
224    
225 astrand 118 BOOL
226 matthewc 209 get_key_state(unsigned int state, uint32 keysym)
227 astrand 102 {
228 matthewc 203 int modifierpos, key, keysymMask = 0;
229 astrand 102 int offset;
230    
231     KeyCode keycode = XKeysymToKeycode(display, keysym);
232    
233     if (keycode == NoSymbol)
234     return False;
235    
236     for (modifierpos = 0; modifierpos < 8; modifierpos++)
237     {
238 matthewc 203 offset = mod_map->max_keypermod * modifierpos;
239 astrand 102
240 matthewc 203 for (key = 0; key < mod_map->max_keypermod; key++)
241 astrand 102 {
242 matthewc 203 if (mod_map->modifiermap[offset + key] == keycode)
243     keysymMask |= 1 << modifierpos;
244 astrand 102 }
245     }
246    
247 matthewc 203 return (state & keysymMask) ? True : False;
248 astrand 102 }
249    
250 jsorg71 81 BOOL
251 matthewc 192 ui_init(void)
252 jsorg71 81 {
253 matthewc 121 XPixmapFormatValues *pfm;
254     uint16 test;
255     int i;
256    
257 jsorg71 81 display = XOpenDisplay(NULL);
258     if (display == NULL)
259     {
260 matthewc 210 error("Failed to open display: %s\n", XDisplayName(NULL));
261 jsorg71 81 return False;
262     }
263 matthewc 121
264     x_socket = ConnectionNumber(display);
265     screen = DefaultScreenOfDisplay(display);
266     visual = DefaultVisualOfScreen(screen);
267     depth = DefaultDepthOfScreen(screen);
268    
269     pfm = XListPixmapFormats(display, &i);
270     if (pfm != NULL)
271     {
272     /* Use maximum bpp for this depth - this is generally
273     desirable, e.g. 24 bits->32 bits. */
274     while (i--)
275     {
276     if ((pfm[i].depth == depth) && (pfm[i].bits_per_pixel > bpp))
277     {
278     bpp = pfm[i].bits_per_pixel;
279     }
280     }
281     XFree(pfm);
282     }
283    
284     if (bpp < 8)
285     {
286     error("Less than 8 bpp not currently supported.\n");
287     XCloseDisplay(display);
288     return False;
289     }
290    
291 n-ki 185 xcolmap = DefaultColormapOfScreen(screen);
292 matthewc 188 gc = XCreateGC(display, RootWindowOfScreen(screen), 0, NULL);
293 matthewc 121
294 matthewc 188 if (DoesBackingStore(screen) != Always)
295 matthewc 121 ownbackstore = True;
296    
297     test = 1;
298     host_be = !(BOOL) (*(uint8 *) (&test));
299     xserver_be = (ImageByteOrder(display) == MSBFirst);
300    
301 astrand 82 if (fullscreen)
302 jsorg71 81 {
303     width = WidthOfScreen(screen);
304     height = HeightOfScreen(screen);
305     }
306 matthewc 121
307 matthewc 160 /* make sure width is a multiple of 4 */
308     width = (width + 3) & ~3;
309    
310 matthewc 188 if (ownbackstore)
311     {
312 astrand 196 backstore =
313     XCreatePixmap(display, RootWindowOfScreen(screen), width, height, depth);
314 matthewc 188
315     /* clear to prevent rubbish being exposed at startup */
316     XSetForeground(display, gc, BlackPixelOfScreen(screen));
317     XFillRectangle(display, backstore, gc, 0, 0, width, height);
318     }
319    
320 matthewc 203 mod_map = XGetModifierMapping(display);
321    
322 matthewc 188 if (enable_compose)
323     IM = XOpenIM(display, NULL, NULL, NULL);
324    
325 matthewc 121 xkeymap_init();
326 jsorg71 81 return True;
327     }
328 astrand 66
329 matthewc 188 void
330 matthewc 192 ui_deinit(void)
331 matthewc 188 {
332     if (IM != NULL)
333     XCloseIM(IM);
334    
335 matthewc 204 XFreeModifiermap(mod_map);
336 matthewc 203
337 matthewc 188 if (ownbackstore)
338     XFreePixmap(display, backstore);
339    
340     XFreeGC(display, gc);
341     XCloseDisplay(display);
342     display = NULL;
343     }
344    
345 matthewc 121 BOOL
346 matthewc 192 ui_create_window(void)
347 matty 6 {
348 matthewc 121 XSetWindowAttributes attribs;
349 matty 28 XClassHint *classhints;
350     XSizeHints *sizehints;
351 matthewc 188 int wndwidth, wndheight;
352     long input_mask, ic_input_mask;
353 jsorg71 100 XEvent xevent;
354    
355 astrand 196 wndwidth = fullscreen ? WidthOfScreen(screen) : width;
356 matthewc 188 wndheight = fullscreen ? HeightOfScreen(screen) : height;
357    
358 matthewc 121 attribs.background_pixel = BlackPixelOfScreen(screen);
359     attribs.backing_store = ownbackstore ? NotUseful : Always;
360     attribs.override_redirect = fullscreen;
361 matthewc 188
362     wnd = XCreateWindow(display, RootWindowOfScreen(screen), 0, 0, wndwidth, wndheight,
363 matthewc 121 0, CopyFromParent, InputOutput, CopyFromParent,
364     CWBackPixel | CWBackingStore | CWOverrideRedirect, &attribs);
365 jsorg71 100
366     XStoreName(display, wnd, title);
367    
368 astrand 262 if (hide_decorations)
369     mwm_hide_decorations();
370    
371 jsorg71 100 classhints = XAllocClassHint();
372     if (classhints != NULL)
373     {
374     classhints->res_name = classhints->res_class = "rdesktop";
375     XSetClassHint(display, wnd, classhints);
376     XFree(classhints);
377     }
378    
379     sizehints = XAllocSizeHints();
380     if (sizehints)
381     {
382     sizehints->flags = PMinSize | PMaxSize;
383     sizehints->min_width = sizehints->max_width = width;
384     sizehints->min_height = sizehints->max_height = height;
385     XSetWMNormalHints(display, wnd, sizehints);
386     XFree(sizehints);
387     }
388    
389 matthewc 121 input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
390 jsorg71 257 VisibilityChangeMask | FocusChangeMask;
391 matthewc 121
392     if (sendmotion)
393     input_mask |= PointerMotionMask;
394     if (ownbackstore)
395     input_mask |= ExposureMask;
396 jsorg71 257 if (fullscreen || grab_keyboard)
397 matthewc 250 input_mask |= EnterWindowMask;
398 jsorg71 257 if (grab_keyboard)
399     input_mask |= LeaveWindowMask;
400 jsorg71 100
401 matthewc 188 if (IM != NULL)
402     {
403     IC = XCreateIC(IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
404     XNClientWindow, wnd, XNFocusWindow, wnd, NULL);
405    
406 astrand 196 if ((IC != NULL)
407     && (XGetICValues(IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
408 matthewc 188 input_mask |= ic_input_mask;
409     }
410    
411 jsorg71 100 XSelectInput(display, wnd, input_mask);
412 matthewc 188 XMapWindow(display, wnd);
413 jsorg71 100
414 matthewc 208 /* wait for VisibilityNotify */
415 astrand 196 do
416     {
417 matthewc 208 XMaskEvent(display, VisibilityChangeMask, &xevent);
418 astrand 196 }
419 matthewc 208 while (xevent.type != VisibilityNotify);
420 matthewc 123
421 jsorg71 257 focused = False;
422     mouse_in_wnd = False;
423    
424 matty 10 return True;
425 matty 6 }
426    
427 matty 25 void
428 matthewc 192 ui_destroy_window(void)
429 matty 6 {
430 matthewc 188 if (IC != NULL)
431     XDestroyIC(IC);
432 matty 31
433 matty 10 XDestroyWindow(display, wnd);
434 matty 6 }
435    
436 jsorg71 100 void
437 matthewc 192 xwin_toggle_fullscreen(void)
438 jsorg71 100 {
439 matthewc 188 Pixmap contents = 0;
440 matthewc 123
441 matthewc 188 if (!ownbackstore)
442     {
443     /* need to save contents of window */
444     contents = XCreatePixmap(display, wnd, width, height, depth);
445     XCopyArea(display, wnd, contents, gc, 0, 0, width, height, 0, 0);
446     }
447    
448     ui_destroy_window();
449 matthewc 123 fullscreen = !fullscreen;
450 matthewc 188 ui_create_window();
451 matthewc 123
452 matthewc 188 XDefineCursor(display, wnd, current_cursor);
453    
454     if (!ownbackstore)
455     {
456     XCopyArea(display, contents, wnd, gc, 0, 0, width, height, 0, 0);
457     XFreePixmap(display, contents);
458     }
459 jsorg71 100 }
460    
461 astrand 119 /* Process all events in Xlib queue */
462 matty 33 static void
463 matthewc 192 xwin_process_events(void)
464 matty 9 {
465 n-ki 54 XEvent xevent;
466 matthewc 38 KeySym keysym;
467 matthewc 50 uint16 button, flags;
468 matty 10 uint32 ev_time;
469 astrand 66 key_translation tr;
470     char str[256];
471     Status status;
472 matthewc 203 unsigned int state;
473     Window wdummy;
474     int dummy;
475 matty 9
476 matthewc 123 while (XPending(display) > 0)
477 matty 9 {
478 matthewc 123 XNextEvent(display, &xevent);
479    
480 matthewc 188 if ((IC != NULL) && (XFilterEvent(&xevent, None) == True))
481 astrand 66 {
482 astrand 84 DEBUG_KBD(("Filtering event\n"));
483 astrand 66 continue;
484     }
485    
486 matthewc 50 flags = 0;
487 matty 10
488 n-ki 54 switch (xevent.type)
489 matty 9 {
490     case KeyPress:
491 astrand 66 if (IC != NULL)
492     /* Multi_key compatible version */
493     {
494     XmbLookupString(IC,
495     (XKeyPressedEvent *) &
496 astrand 82 xevent, str, sizeof(str), &keysym, &status);
497     if (!((status == XLookupKeySym) || (status == XLookupBoth)))
498 astrand 66 {
499 astrand 82 error("XmbLookupString failed with status 0x%x\n",
500     status);
501 astrand 66 break;
502     }
503     }
504     else
505     {
506     /* Plain old XLookupString */
507 astrand 182 DEBUG_KBD(("\nNo input context, using XLookupString\n"));
508 astrand 66 XLookupString((XKeyEvent *) & xevent,
509 astrand 82 str, sizeof(str), &keysym, NULL);
510 astrand 66 }
511    
512 astrand 261 DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,
513     get_ksname(keysym)));
514 astrand 66
515 matthewc 203 ev_time = time(NULL);
516     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
517 astrand 118 break;
518    
519 astrand 66 tr = xkeymap_translate_key(keysym,
520 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
521 astrand 69
522 astrand 66 if (tr.scancode == 0)
523 n-ki 52 break;
524    
525 astrand 115 ensure_remote_modifiers(ev_time, tr);
526    
527 astrand 82 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);
528 astrand 66 break;
529 matthewc 203
530 astrand 66 case KeyRelease:
531     XLookupString((XKeyEvent *) & xevent, str,
532     sizeof(str), &keysym, NULL);
533 n-ki 52
534 astrand 84 DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,
535 matthewc 203 get_ksname(keysym)));
536 n-ki 52
537 matthewc 203 ev_time = time(NULL);
538     if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
539 astrand 118 break;
540    
541 astrand 66 tr = xkeymap_translate_key(keysym,
542 astrand 82 xevent.xkey.keycode, xevent.xkey.state);
543 astrand 66
544     if (tr.scancode == 0)
545     break;
546    
547 astrand 82 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);
548 matty 9 break;
549    
550     case ButtonPress:
551 matthewc 50 flags = MOUSE_FLAG_DOWN;
552     /* fall through */
553 matty 9
554     case ButtonRelease:
555 astrand 82 button = xkeymap_translate_button(xevent.xbutton.button);
556 matty 9 if (button == 0)
557     break;
558    
559 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
560 astrand 82 flags | button, xevent.xbutton.x, xevent.xbutton.y);
561 matty 10 break;
562    
563     case MotionNotify:
564 matthewc 203 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
565 astrand 82 MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
566 matty 28 break;
567    
568 matthewc 194 case FocusIn:
569 jsorg71 257 if (xevent.xfocus.mode == NotifyGrab)
570     break;
571     focused = True;
572 astrand 261 XQueryPointer(display, wnd, &wdummy, &wdummy, &dummy, &dummy,
573     &dummy, &dummy, &state);
574 matthewc 203 reset_modifier_keys(state);
575 jsorg71 257 if (grab_keyboard && mouse_in_wnd)
576 astrand 76 XGrabKeyboard(display, wnd, True,
577 astrand 82 GrabModeAsync, GrabModeAsync, CurrentTime);
578 matty 28 break;
579    
580 matthewc 194 case FocusOut:
581 jsorg71 257 if (xevent.xfocus.mode == NotifyUngrab)
582     break;
583     focused = False;
584 matthewc 201 if (xevent.xfocus.mode == NotifyWhileGrabbed)
585 astrand 76 XUngrabKeyboard(display, CurrentTime);
586 matty 28 break;
587 matty 31
588 matthewc 250 case EnterNotify:
589     /* we only register for this event when in fullscreen mode */
590 jsorg71 257 /* or grab_keyboard */
591     mouse_in_wnd = True;
592     if (fullscreen)
593     {
594 astrand 261 XSetInputFocus(display, wnd, RevertToPointerRoot,
595     CurrentTime);
596 jsorg71 257 break;
597     }
598     if (focused)
599     XGrabKeyboard(display, wnd, True,
600     GrabModeAsync, GrabModeAsync, CurrentTime);
601 matthewc 250 break;
602    
603 matthewc 253 case LeaveNotify:
604 jsorg71 257 /* we only register for this event when grab_keyboard */
605     mouse_in_wnd = False;
606 matthewc 253 XUngrabKeyboard(display, CurrentTime);
607     break;
608    
609 matty 31 case Expose:
610     XCopyArea(display, backstore, wnd, gc,
611 n-ki 54 xevent.xexpose.x, xevent.xexpose.y,
612 astrand 64 xevent.xexpose.width,
613     xevent.xexpose.height,
614 n-ki 54 xevent.xexpose.x, xevent.xexpose.y);
615 matty 31 break;
616 astrand 119
617     case MappingNotify:
618     /* Refresh keyboard mapping if it has changed. This is important for
619     Xvnc, since it allocates keycodes dynamically */
620     if (xevent.xmapping.request == MappingKeyboard
621     || xevent.xmapping.request == MappingModifier)
622     XRefreshKeyboardMapping(&xevent.xmapping);
623 matthewc 203
624     if (xevent.xmapping.request == MappingModifier)
625     {
626 matthewc 204 XFreeModifiermap(mod_map);
627 matthewc 203 mod_map = XGetModifierMapping(display);
628     }
629 astrand 119 break;
630    
631 matty 9 }
632     }
633     }
634    
635 matty 25 void
636 matty 33 ui_select(int rdp_socket)
637     {
638 astrand 64 int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1;
639 matty 33 fd_set rfds;
640    
641     FD_ZERO(&rfds);
642    
643     while (True)
644     {
645 matthewc 121 /* Process any events already waiting */
646 astrand 119 xwin_process_events();
647    
648 matty 33 FD_ZERO(&rfds);
649     FD_SET(rdp_socket, &rfds);
650 matthewc 121 FD_SET(x_socket, &rfds);
651 matty 33
652     switch (select(n, &rfds, NULL, NULL, NULL))
653     {
654     case -1:
655     error("select: %s\n", strerror(errno));
656    
657     case 0:
658     continue;
659     }
660    
661     if (FD_ISSET(rdp_socket, &rfds))
662     return;
663     }
664     }
665    
666     void
667 matty 25 ui_move_pointer(int x, int y)
668 matty 9 {
669 matty 10 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
670 matty 9 }
671    
672 matty 25 HBITMAP
673 astrand 64 ui_create_bitmap(int width, int height, uint8 * data)
674 matty 6 {
675     XImage *image;
676 matty 9 Pixmap bitmap;
677 matty 28 uint8 *tdata;
678 matty 29
679 n-ki 185 tdata = translate_image(width, height, data);
680 matty 28 bitmap = XCreatePixmap(display, wnd, width, height, depth);
681 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
682     (char *) tdata, width, height, 8, 0);
683 matty 6
684 matty 28 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
685 matty 9
686     XFree(image);
687 n-ki 185 xfree(tdata);
688 matty 24 return (HBITMAP) bitmap;
689 matty 6 }
690    
691 matty 25 void
692 astrand 82 ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
693 matty 6 {
694 matty 10 XImage *image;
695 matty 29 uint8 *tdata;
696 matty 10
697 n-ki 185 tdata = translate_image(width, height, data);
698 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
699     (char *) tdata, width, height, 8, 0);
700 matty 28
701 matty 31 if (ownbackstore)
702     {
703     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
704     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
705     }
706     else
707     {
708     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
709     }
710 matty 29
711 matty 24 XFree(image);
712 n-ki 185 xfree(tdata);
713 matty 6 }
714    
715 matty 25 void
716     ui_destroy_bitmap(HBITMAP bmp)
717 matty 6 {
718 astrand 64 XFreePixmap(display, (Pixmap) bmp);
719 matty 10 }
720    
721 matty 25 HGLYPH
722 astrand 64 ui_create_glyph(int width, int height, uint8 * data)
723 matty 10 {
724 matty 9 XImage *image;
725     Pixmap bitmap;
726     int scanline;
727     GC gc;
728 matty 6
729 matty 9 scanline = (width + 7) / 8;
730 matty 6
731 matty 10 bitmap = XCreatePixmap(display, wnd, width, height, 1);
732     gc = XCreateGC(display, bitmap, 0, NULL);
733 matty 9
734 astrand 77 image = XCreateImage(display, visual, 1, ZPixmap, 0, (char *) data,
735 astrand 73 width, height, 8, scanline);
736 matty 23 image->byte_order = MSBFirst;
737     image->bitmap_bit_order = MSBFirst;
738     XInitImage(image);
739    
740 matty 10 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
741 matty 29
742 matty 9 XFree(image);
743 matty 10 XFreeGC(display, gc);
744 astrand 64 return (HGLYPH) bitmap;
745 matty 6 }
746 matty 7
747 matty 25 void
748     ui_destroy_glyph(HGLYPH glyph)
749 matty 7 {
750 astrand 64 XFreePixmap(display, (Pixmap) glyph);
751 matty 9 }
752    
753 matty 29 HCURSOR
754 astrand 66 ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
755     uint8 * andmask, uint8 * xormask)
756 matty 9 {
757 matty 29 HGLYPH maskglyph, cursorglyph;
758     XColor bg, fg;
759     Cursor xcursor;
760     uint8 *cursor, *pcursor;
761     uint8 *mask, *pmask;
762     uint8 nextbit;
763     int scanline, offset;
764     int i, j;
765    
766     scanline = (width + 7) / 8;
767     offset = scanline * height;
768    
769     cursor = xmalloc(offset);
770     memset(cursor, 0, offset);
771    
772     mask = xmalloc(offset);
773     memset(mask, 0, offset);
774    
775     /* approximate AND and XOR masks with a monochrome X pointer */
776     for (i = 0; i < height; i++)
777 matty 7 {
778 matty 29 offset -= scanline;
779     pcursor = &cursor[offset];
780     pmask = &mask[offset];
781    
782     for (j = 0; j < scanline; j++)
783 matty 28 {
784 matty 29 for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
785     {
786     if (xormask[0] || xormask[1] || xormask[2])
787     {
788     *pcursor |= (~(*andmask) & nextbit);
789     *pmask |= nextbit;
790     }
791     else
792     {
793     *pcursor |= ((*andmask) & nextbit);
794     *pmask |= (~(*andmask) & nextbit);
795     }
796    
797     xormask += 3;
798     }
799    
800     andmask++;
801     pcursor++;
802     pmask++;
803 matty 28 }
804 matty 7 }
805 matty 29
806     fg.red = fg.blue = fg.green = 0xffff;
807     bg.red = bg.blue = bg.green = 0x0000;
808     fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
809    
810     cursorglyph = ui_create_glyph(width, height, cursor);
811     maskglyph = ui_create_glyph(width, height, mask);
812    
813 astrand 66 xcursor =
814     XCreatePixmapCursor(display, (Pixmap) cursorglyph,
815     (Pixmap) maskglyph, &fg, &bg, x, y);
816 astrand 64
817 matty 29 ui_destroy_glyph(maskglyph);
818     ui_destroy_glyph(cursorglyph);
819     xfree(mask);
820     xfree(cursor);
821 astrand 64 return (HCURSOR) xcursor;
822 matty 29 }
823    
824     void
825     ui_set_cursor(HCURSOR cursor)
826     {
827 matthewc 188 current_cursor = (Cursor) cursor;
828     XDefineCursor(display, wnd, current_cursor);
829 matty 29 }
830    
831     void
832     ui_destroy_cursor(HCURSOR cursor)
833     {
834 astrand 64 XFreeCursor(display, (Cursor) cursor);
835 matty 29 }
836    
837     #define MAKE_XCOLOR(xc,c) \
838     (xc)->red = ((c)->red << 8) | (c)->red; \
839     (xc)->green = ((c)->green << 8) | (c)->green; \
840     (xc)->blue = ((c)->blue << 8) | (c)->blue; \
841     (xc)->flags = DoRed | DoGreen | DoBlue;
842    
843     HCOLOURMAP
844 astrand 64 ui_create_colourmap(COLOURMAP * colours)
845 matty 29 {
846     COLOURENTRY *entry;
847     int i, ncolours = colours->ncolours;
848 n-ki 185 uint32 *map = xmalloc(sizeof(*colmap) * ncolours);
849     XColor xentry;
850     XColor xc_cache[256];
851     uint32 colour;
852     int colLookup = 256;
853     for (i = 0; i < ncolours; i++)
854 matty 28 {
855 n-ki 185 entry = &colours->colours[i];
856     MAKE_XCOLOR(&xentry, entry);
857 matty 29
858 n-ki 185 if (XAllocColor(display, xcolmap, &xentry) == 0)
859 matty 28 {
860 n-ki 185 /* Allocation failed, find closest match. */
861     int j = 256;
862     int nMinDist = 3 * 256 * 256;
863     long nDist = nMinDist;
864 matty 7
865 n-ki 185 /* only get the colors once */
866 astrand 196 while (colLookup--)
867     {
868 n-ki 185 xc_cache[colLookup].pixel = colLookup;
869 astrand 196 xc_cache[colLookup].red = xc_cache[colLookup].green =
870     xc_cache[colLookup].blue = 0;
871 n-ki 185 xc_cache[colLookup].flags = 0;
872 astrand 196 XQueryColor(display,
873     DefaultColormap(display, DefaultScreen(display)),
874     &xc_cache[colLookup]);
875 n-ki 185 }
876     colLookup = 0;
877 matty 28
878 n-ki 185 /* approximate the pixel */
879 astrand 196 while (j--)
880     {
881     if (xc_cache[j].flags)
882     {
883     nDist = ((long) (xc_cache[j].red >> 8) -
884     (long) (xentry.red >> 8)) *
885     ((long) (xc_cache[j].red >> 8) -
886     (long) (xentry.red >> 8)) +
887     ((long) (xc_cache[j].green >> 8) -
888     (long) (xentry.green >> 8)) *
889     ((long) (xc_cache[j].green >> 8) -
890     (long) (xentry.green >> 8)) +
891     ((long) (xc_cache[j].blue >> 8) -
892     (long) (xentry.blue >> 8)) *
893     ((long) (xc_cache[j].blue >> 8) -
894     (long) (xentry.blue >> 8));
895 n-ki 185 }
896 astrand 196 if (nDist < nMinDist)
897     {
898 n-ki 185 nMinDist = nDist;
899     xentry.pixel = j;
900     }
901     }
902     }
903     colour = xentry.pixel;
904 matty 29
905 n-ki 185 /* update our cache */
906 astrand 196 if (xentry.pixel < 256)
907     {
908 n-ki 185 xc_cache[xentry.pixel].red = xentry.red;
909     xc_cache[xentry.pixel].green = xentry.green;
910     xc_cache[xentry.pixel].blue = xentry.blue;
911 matty 29
912     }
913    
914 n-ki 185
915     /* byte swap here to make translate_image faster */
916     map[i] = translate_colour(colour);
917 matty 29 }
918 n-ki 185
919     return map;
920 matty 7 }
921    
922 matty 25 void
923     ui_destroy_colourmap(HCOLOURMAP map)
924 matty 7 {
925 n-ki 185 xfree(map);
926 matty 7 }
927    
928 matty 25 void
929     ui_set_colourmap(HCOLOURMAP map)
930 matty 7 {
931 n-ki 185 colmap = map;
932 matty 7 }
933    
934 matty 25 void
935     ui_set_clip(int x, int y, int cx, int cy)
936 matty 7 {
937 matty 9 XRectangle rect;
938 matty 7
939 matty 9 rect.x = x;
940     rect.y = y;
941     rect.width = cx;
942     rect.height = cy;
943 matty 10 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
944 matty 9 }
945 matty 7
946 matty 25 void
947 matthewc 192 ui_reset_clip(void)
948 matty 9 {
949     XRectangle rect;
950    
951     rect.x = 0;
952     rect.y = 0;
953 matty 10 rect.width = width;
954     rect.height = height;
955     XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
956 matty 7 }
957    
958 matty 25 void
959 matthewc 192 ui_bell(void)
960 matty 10 {
961     XBell(display, 0);
962     }
963    
964 matty 25 void
965     ui_destblt(uint8 opcode,
966     /* dest */ int x, int y, int cx, int cy)
967 matty 9 {
968 matty 29 SET_FUNCTION(opcode);
969 matty 31 FILL_RECTANGLE(x, y, cx, cy);
970 matty 29 RESET_FUNCTION(opcode);
971 matty 9 }
972    
973 matty 25 void
974     ui_patblt(uint8 opcode,
975     /* dest */ int x, int y, int cx, int cy,
976 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
977 matty 9 {
978     Pixmap fill;
979 jsorg71 59 uint8 i, ipattern[8];
980 matty 9
981 matty 29 SET_FUNCTION(opcode);
982 matty 9
983     switch (brush->style)
984     {
985 matty 24 case 0: /* Solid */
986 matty 29 SET_FOREGROUND(fgcolour);
987 matty 31 FILL_RECTANGLE(x, y, cx, cy);
988 matty 9 break;
989    
990 matty 24 case 3: /* Pattern */
991 jsorg71 59 for (i = 0; i != 8; i++)
992     ipattern[7 - i] = brush->pattern[i];
993     fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
994 matty 9
995 matty 29 SET_FOREGROUND(bgcolour);
996     SET_BACKGROUND(fgcolour);
997     XSetFillStyle(display, gc, FillOpaqueStippled);
998     XSetStipple(display, gc, fill);
999 astrand 82 XSetTSOrigin(display, gc, brush->xorigin, brush->yorigin);
1000 matty 9
1001 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1002 matty 9
1003 matty 29 XSetFillStyle(display, gc, FillSolid);
1004 jsorg71 80 XSetTSOrigin(display, gc, 0, 0);
1005 astrand 64 ui_destroy_glyph((HGLYPH) fill);
1006 matty 9 break;
1007    
1008     default:
1009 matty 30 unimpl("brush %d\n", brush->style);
1010 matty 9 }
1011 matty 29
1012     RESET_FUNCTION(opcode);
1013 matty 9 }
1014    
1015 matty 25 void
1016     ui_screenblt(uint8 opcode,
1017     /* dest */ int x, int y, int cx, int cy,
1018     /* src */ int srcx, int srcy)
1019 matty 9 {
1020 matty 29 SET_FUNCTION(opcode);
1021 matty 24 XCopyArea(display, wnd, wnd, gc, srcx, srcy, cx, cy, x, y);
1022 matty 31 if (ownbackstore)
1023 astrand 82 XCopyArea(display, backstore, backstore, gc, srcx, srcy, cx, cy, x, y);
1024 matty 29 RESET_FUNCTION(opcode);
1025 matty 9 }
1026    
1027 matty 25 void
1028     ui_memblt(uint8 opcode,
1029     /* dest */ int x, int y, int cx, int cy,
1030     /* src */ HBITMAP src, int srcx, int srcy)
1031 matty 9 {
1032 matty 29 SET_FUNCTION(opcode);
1033 astrand 64 XCopyArea(display, (Pixmap) src, wnd, gc, srcx, srcy, cx, cy, x, y);
1034 matty 31 if (ownbackstore)
1035 astrand 82 XCopyArea(display, (Pixmap) src, backstore, gc, srcx, srcy, cx, cy, x, y);
1036 matty 29 RESET_FUNCTION(opcode);
1037 matty 9 }
1038    
1039 matty 25 void
1040     ui_triblt(uint8 opcode,
1041     /* dest */ int x, int y, int cx, int cy,
1042     /* src */ HBITMAP src, int srcx, int srcy,
1043 astrand 64 /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
1044 matty 9 {
1045     /* This is potentially difficult to do in general. Until someone
1046 matty 10 comes up with a more efficient way of doing it I am using cases. */
1047 matty 9
1048     switch (opcode)
1049     {
1050 matty 24 case 0x69: /* PDSxxn */
1051 matty 16 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
1052 astrand 82 ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1053 matty 16 break;
1054    
1055 matty 24 case 0xb8: /* PSDPxax */
1056 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1057 matty 16 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
1058 astrand 82 ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
1059 matty 9 break;
1060    
1061 matty 29 case 0xc0: /* PSa */
1062 matty 28 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1063 astrand 82 ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
1064 matty 28 break;
1065    
1066 matty 9 default:
1067 matty 30 unimpl("triblt 0x%x\n", opcode);
1068 matty 16 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
1069 matty 9 }
1070     }
1071    
1072 matty 25 void
1073     ui_line(uint8 opcode,
1074     /* dest */ int startx, int starty, int endx, int endy,
1075 astrand 64 /* pen */ PEN * pen)
1076 matty 9 {
1077 matty 29 SET_FUNCTION(opcode);
1078     SET_FOREGROUND(pen->colour);
1079 matty 10 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
1080 matty 31 if (ownbackstore)
1081     XDrawLine(display, backstore, gc, startx, starty, endx, endy);
1082 matty 29 RESET_FUNCTION(opcode);
1083 matty 9 }
1084    
1085 matty 25 void
1086     ui_rect(
1087     /* dest */ int x, int y, int cx, int cy,
1088     /* brush */ int colour)
1089 matty 9 {
1090 matty 29 SET_FOREGROUND(colour);
1091 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1092 matty 9 }
1093    
1094 matty 25 void
1095     ui_draw_glyph(int mixmode,
1096     /* dest */ int x, int y, int cx, int cy,
1097 astrand 66 /* src */ HGLYPH glyph, int srcx, int srcy,
1098     int bgcolour, int fgcolour)
1099 matty 9 {
1100 matty 29 SET_FOREGROUND(fgcolour);
1101     SET_BACKGROUND(bgcolour);
1102 matty 9
1103 astrand 66 XSetFillStyle(display, gc,
1104 astrand 82 (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
1105 astrand 64 XSetStipple(display, gc, (Pixmap) glyph);
1106 matty 29 XSetTSOrigin(display, gc, x, y);
1107 matty 9
1108 matty 31 FILL_RECTANGLE(x, y, cx, cy);
1109 matty 9
1110 matty 29 XSetFillStyle(display, gc, FillSolid);
1111 matty 9 }
1112    
1113 mmihalik 49 #define DO_GLYPH(ttext,idx) \
1114     {\
1115     glyph = cache_get_font (font, ttext[idx]);\
1116     if (!(flags & TEXT2_IMPLICIT_X))\
1117     {\
1118     xyoffset = ttext[++idx];\
1119     if ((xyoffset & 0x80))\
1120     {\
1121     if (flags & TEXT2_VERTICAL) \
1122 astrand 72 y += ttext[idx+1] | (ttext[idx+2] << 8);\
1123 mmihalik 49 else\
1124 astrand 72 x += ttext[idx+1] | (ttext[idx+2] << 8);\
1125     idx += 2;\
1126 mmihalik 49 }\
1127     else\
1128     {\
1129     if (flags & TEXT2_VERTICAL) \
1130     y += xyoffset;\
1131     else\
1132     x += xyoffset;\
1133     }\
1134     }\
1135     if (glyph != NULL)\
1136     {\
1137     ui_draw_glyph (mixmode, x + (short) glyph->offset,\
1138     y + (short) glyph->baseline,\
1139     glyph->width, glyph->height,\
1140     glyph->pixmap, 0, 0, bgcolour, fgcolour);\
1141     if (flags & TEXT2_IMPLICIT_X)\
1142     x += glyph->width;\
1143     }\
1144     }
1145    
1146 matty 25 void
1147     ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
1148 astrand 66 int clipx, int clipy, int clipcx, int clipcy,
1149     int boxx, int boxy, int boxcx, int boxcy, int bgcolour,
1150 mmihalik 49 int fgcolour, uint8 * text, uint8 length)
1151 matty 9 {
1152 matty 10 FONTGLYPH *glyph;
1153 mmihalik 49 int i, j, xyoffset;
1154     DATABLOB *entry;
1155 matty 9
1156 matty 29 SET_FOREGROUND(bgcolour);
1157 matty 28
1158 matty 9 if (boxcx > 1)
1159 matty 31 {
1160     FILL_RECTANGLE(boxx, boxy, boxcx, boxcy);
1161     }
1162 matty 17 else if (mixmode == MIX_OPAQUE)
1163 matty 31 {
1164     FILL_RECTANGLE(clipx, clipy, clipcx, clipcy);
1165     }
1166 matty 9
1167     /* Paint text, character by character */
1168 astrand 64 for (i = 0; i < length;)
1169     {
1170     switch (text[i])
1171     {
1172     case 0xff:
1173     if (i + 2 < length)
1174 astrand 82 cache_put_text(text[i + 1], text, text[i + 2]);
1175 astrand 64 else
1176     {
1177     error("this shouldn't be happening\n");
1178     break;
1179     }
1180     /* this will move pointer from start to first character after FF command */
1181     length -= i + 3;
1182     text = &(text[i + 3]);
1183     i = 0;
1184 mmihalik 49 break;
1185 matty 9
1186 astrand 64 case 0xfe:
1187     entry = cache_get_text(text[i + 1]);
1188     if (entry != NULL)
1189     {
1190     if ((((uint8 *) (entry->data))[1] ==
1191 astrand 82 0) && (!(flags & TEXT2_IMPLICIT_X)))
1192 astrand 64 {
1193     if (flags & TEXT2_VERTICAL)
1194     y += text[i + 2];
1195     else
1196     x += text[i + 2];
1197     }
1198     if (i + 2 < length)
1199     i += 3;
1200 mmihalik 49 else
1201 astrand 64 i += 2;
1202     length -= i;
1203     /* this will move pointer from start to first character after FE command */
1204     text = &(text[i]);
1205     i = 0;
1206     for (j = 0; j < entry->size; j++)
1207 astrand 82 DO_GLYPH(((uint8 *) (entry->data)), j);
1208 matthewc 44 }
1209 astrand 64 break;
1210 matty 17
1211 astrand 64 default:
1212     DO_GLYPH(text, i);
1213     i++;
1214     break;
1215 matty 29 }
1216 mmihalik 49 }
1217 matty 28
1218 matty 9
1219     }
1220    
1221 matty 25 void
1222     ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1223 matty 9 {
1224 matty 28 Pixmap pix;
1225 matty 9 XImage *image;
1226    
1227 matty 31 if (ownbackstore)
1228     {
1229 astrand 82 image = XGetImage(display, backstore, x, y, cx, cy, AllPlanes, ZPixmap);
1230 matty 31 }
1231     else
1232     {
1233     pix = XCreatePixmap(display, wnd, cx, cy, depth);
1234     XCopyArea(display, wnd, pix, gc, x, y, cx, cy, 0, 0);
1235 astrand 82 image = XGetImage(display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
1236 matty 31 XFreePixmap(display, pix);
1237     }
1238 matty 28
1239 astrand 64 offset *= bpp / 8;
1240 astrand 82 cache_put_desktop(offset, cx, cy, image->bytes_per_line, bpp / 8, (uint8 *) image->data);
1241 matty 28
1242     XDestroyImage(image);
1243 matty 9 }
1244    
1245 matty 25 void
1246     ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1247 matty 9 {
1248     XImage *image;
1249 matty 10 uint8 *data;
1250 matty 9
1251 astrand 64 offset *= bpp / 8;
1252     data = cache_get_desktop(offset, cx, cy, bpp / 8);
1253 matty 10 if (data == NULL)
1254     return;
1255 matty 29
1256 astrand 77 image = XCreateImage(display, visual, depth, ZPixmap, 0,
1257 astrand 82 (char *) data, cx, cy, BitmapPad(display), cx * bpp / 8);
1258 matty 29
1259 matty 31 if (ownbackstore)
1260     {
1261     XPutImage(display, backstore, gc, image, 0, 0, x, y, cx, cy);
1262     XCopyArea(display, backstore, wnd, gc, x, y, cx, cy, x, y);
1263     }
1264     else
1265     {
1266     XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
1267     }
1268    
1269 matty 9 XFree(image);
1270     }

  ViewVC Help
Powered by ViewVC 1.1.26