/[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 54 - (hide annotations)
Fri Jun 7 07:49:59 2002 UTC (21 years, 11 months ago) by n-ki
File MIME type: text/plain
File size: 28541 byte(s)
using XEvent instead of XkbEvent. better tracking of modifiers. ( TODO: 1. sync at start up, 2. fallback for missing or improperly configured xkb module. )

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

  ViewVC Help
Powered by ViewVC 1.1.26