/[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 257 - (hide annotations)
Mon Nov 11 23:15:27 2002 UTC (21 years, 6 months ago) by jsorg71
File MIME type: text/plain
File size: 27207 byte(s)
can't grabkeyboard on focusin unless mouse is in window, can't grabkeyboard on enternotiy unless window is focused, cache them, other grabkeyboard fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26