/[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

Contents of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Tue Oct 17 08:24:09 2000 UTC (23 years, 7 months ago) by matty
File MIME type: text/plain
File size: 12428 byte(s)
Fix for big-endian X-servers: rely on server to handle byte/bit order.

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - X-Windows
4 Copyright (C) Matthew Chapman 1999-2000
5
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
11 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
16 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 #include <X11/Xlib.h>
22 #include <time.h>
23 #include "rdesktop.h"
24
25 extern int width;
26 extern int height;
27 extern BOOL motion;
28
29 static Display *display;
30 static Window wnd;
31 static GC gc;
32 static Visual *visual;
33 static XIM IM;
34
35 BOOL ui_create_window(char *title)
36 {
37 Screen *screen;
38 XSetWindowAttributes attribs;
39 unsigned long input_mask;
40 int i;
41
42 display = XOpenDisplay(NULL);
43 if (display == NULL)
44 {
45 ERROR("Failed to open display\n");
46 return False;
47 }
48
49 /* Check the screen supports 8-bit depth. */
50 screen = DefaultScreenOfDisplay(display);
51 for (i = 0; i < screen->ndepths; i++)
52 if (screen->depths[i].depth == 8)
53 break;
54
55 if (i >= screen->ndepths)
56 {
57 ERROR("8-bit depth required (in this version).\n");
58 XCloseDisplay(display);
59 return False;
60 }
61
62 visual = DefaultVisual(display, DefaultScreen(display));
63
64 attribs.background_pixel = BlackPixel(display, DefaultScreen(display));
65 attribs.backing_store = Always;
66 wnd = XCreateWindow(display, DefaultRootWindow(display),
67 0, 0, width, height, 0, 8, InputOutput, visual,
68 CWBackingStore | CWBackPixel, &attribs);
69
70 XStoreName(display, wnd, title);
71 XMapWindow(display, wnd);
72
73 input_mask = KeyPressMask | KeyReleaseMask;
74 input_mask |= ButtonPressMask | ButtonReleaseMask;
75 if (motion)
76 input_mask |= PointerMotionMask;
77
78 XSelectInput(display, wnd, input_mask);
79 gc = XCreateGC(display, wnd, 0, NULL);
80
81 IM = XOpenIM(display, NULL, NULL, NULL);
82 return True;
83 }
84
85 void ui_destroy_window()
86 {
87 XCloseIM(IM);
88 XFreeGC(display, gc);
89 XDestroyWindow(display, wnd);
90 XCloseDisplay(display);
91 }
92
93 static uint8 xwin_translate_key(unsigned long key)
94 {
95 DEBUG("KEY(code=0x%lx)\n", key);
96
97 if ((key > 8) && (key <= 0x60))
98 return (key - 8);
99
100 switch (key)
101 {
102 case 0x62: /* left arrow */
103 return 0x48;
104 case 0x64: /* up arrow */
105 return 0x4b;
106 case 0x66: /* down arrow */
107 return 0x4d;
108 case 0x68: /* right arrow */
109 return 0x50;
110 case 0x73: /* Windows key */
111 DEBUG("CHECKPOINT\n");
112 }
113
114 return 0;
115 }
116
117 static uint16 xwin_translate_mouse(unsigned long button)
118 {
119 switch (button)
120 {
121 case Button1: /* left */
122 return MOUSE_FLAG_BUTTON1;
123 case Button2: /* middle */
124 return MOUSE_FLAG_BUTTON3;
125 case Button3: /* right */
126 return MOUSE_FLAG_BUTTON2;
127 }
128
129 return 0;
130 }
131
132 void ui_process_events()
133 {
134 XEvent event;
135 uint8 scancode;
136 uint16 button;
137 uint32 ev_time;
138
139 if (display == NULL)
140 return;
141
142 while (XCheckWindowEvent(display, wnd, 0xffffffff, &event))
143 {
144 ev_time = time(NULL);
145
146 switch (event.type)
147 {
148 case KeyPress:
149 scancode = xwin_translate_key(event.xkey.keycode);
150 if (scancode == 0)
151 break;
152
153 rdp_send_input(ev_time, RDP_INPUT_SCANCODE, 0,
154 scancode, 0);
155 break;
156
157 case KeyRelease:
158 scancode = xwin_translate_key(event.xkey.keycode);
159 if (scancode == 0)
160 break;
161
162 rdp_send_input(ev_time, RDP_INPUT_SCANCODE,
163 KBD_FLAG_DOWN | KBD_FLAG_UP,
164 scancode, 0);
165 break;
166
167 case ButtonPress:
168 button = xwin_translate_mouse(event.xbutton.button);
169
170 if (button == 0)
171 break;
172
173 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
174 button | MOUSE_FLAG_DOWN,
175 event.xbutton.x,
176 event.xbutton.y);
177 break;
178
179 case ButtonRelease:
180 button = xwin_translate_mouse(event.xbutton.button);
181 if (button == 0)
182 break;
183
184 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
185 button,
186 event.xbutton.x,
187 event.xbutton.y);
188 break;
189
190 case MotionNotify:
191 rdp_send_input(ev_time, RDP_INPUT_MOUSE,
192 MOUSE_FLAG_MOVE,
193 event.xmotion.x,
194 event.xmotion.y);
195 }
196 }
197 }
198
199 void ui_move_pointer(int x, int y)
200 {
201 XWarpPointer(display, wnd, wnd, 0, 0, 0, 0, x, y);
202 }
203
204 HBITMAP ui_create_bitmap(int width, int height, uint8 *data)
205 {
206 XImage *image;
207 Pixmap bitmap;
208
209 bitmap = XCreatePixmap(display, wnd, width, height, 8);
210
211 image = XCreateImage(display, visual, 8, ZPixmap, 0,
212 data, width, height, 8, width);
213 XSetFunction(display, gc, GXcopy);
214 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
215 XFree(image);
216
217 return (HBITMAP)bitmap;
218 }
219
220 void ui_paint_bitmap(int x, int y, int cx, int cy,
221 int width, int height, uint8 *data)
222 {
223 XImage *image;
224
225 image = XCreateImage(display, visual, 8, ZPixmap, 0,
226 data, width, height, 8, width);
227 XSetFunction(display, gc, GXcopy);
228 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
229 XFree(image);
230 }
231
232 void ui_destroy_bitmap(HBITMAP bmp)
233 {
234 XFreePixmap(display, (Pixmap)bmp);
235 }
236
237 HGLYPH ui_create_glyph(int width, int height, uint8 *data)
238 {
239 XImage *image;
240 Pixmap bitmap;
241 int scanline;
242 GC gc;
243
244 scanline = (width + 7) / 8;
245
246 bitmap = XCreatePixmap(display, wnd, width, height, 1);
247 gc = XCreateGC(display, bitmap, 0, NULL);
248
249 image = XCreateImage(display, visual, 1, ZPixmap, 0,
250 data, width, height, 8, scanline);
251 image->byte_order = MSBFirst;
252 image->bitmap_bit_order = MSBFirst;
253 XInitImage(image);
254
255 XSetFunction(display, gc, GXcopy);
256 XPutImage(display, bitmap, gc, image, 0, 0, 0, 0, width, height);
257 XFree(image);
258 XFreeGC(display, gc);
259
260 return (HGLYPH)bitmap;
261 }
262
263 void ui_destroy_glyph(HGLYPH glyph)
264 {
265 XFreePixmap(display, (Pixmap)glyph);
266 }
267
268 HCOLOURMAP ui_create_colourmap(COLOURMAP *colours)
269 {
270 COLOURENTRY *entry;
271 XColor *xcolours, *xentry;
272 Colormap map;
273 int i, ncolours = colours->ncolours;
274
275 xcolours = xmalloc(sizeof(XColor) * ncolours);
276 for (i = 0; i < ncolours; i++)
277 {
278 entry = &colours->colours[i];
279 xentry = &xcolours[i];
280
281 xentry->pixel = i;
282 xentry->red = entry->red << 8;
283 xentry->blue = entry->blue << 8;
284 xentry->green = entry->green << 8;
285 xentry->flags = DoRed | DoBlue | DoGreen;
286 }
287
288 map = XCreateColormap(display, wnd, visual, AllocAll);
289 XStoreColors(display, map, xcolours, ncolours);
290
291 xfree(xcolours);
292 return (HCOLOURMAP)map;
293 }
294
295 void ui_destroy_colourmap(HCOLOURMAP map)
296 {
297 XFreeColormap(display, (Colormap)map);
298 }
299
300 void ui_set_colourmap(HCOLOURMAP map)
301 {
302 XSetWindowColormap(display, wnd, (Colormap)map);
303 }
304
305 void ui_set_clip(int x, int y, int cx, int cy)
306 {
307 XRectangle rect;
308
309 rect.x = x;
310 rect.y = y;
311 rect.width = cx;
312 rect.height = cy;
313 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
314 }
315
316 void ui_reset_clip()
317 {
318 XRectangle rect;
319
320 rect.x = 0;
321 rect.y = 0;
322 rect.width = width;
323 rect.height = height;
324 XSetClipRectangles(display, gc, 0, 0, &rect, 1, YXBanded);
325 }
326
327 void ui_bell()
328 {
329 XBell(display, 0);
330 }
331
332 static int rop2_map[] = {
333 GXclear, /* 0 */
334 GXnor, /* DPon */
335 GXandInverted, /* DPna */
336 GXcopyInverted, /* Pn */
337 GXandReverse, /* PDna */
338 GXinvert, /* Dn */
339 GXxor, /* DPx */
340 GXnand, /* DPan */
341 GXand, /* DPa */
342 GXequiv, /* DPxn */
343 GXnoop, /* D */
344 GXorInverted, /* DPno */
345 GXcopy, /* P */
346 GXorReverse, /* PDno */
347 GXor, /* DPo */
348 GXset /* 1 */
349 };
350
351 static void xwin_set_function(uint8 rop2)
352 {
353 XSetFunction(display, gc, rop2_map[rop2]);
354 }
355
356 void ui_destblt(uint8 opcode,
357 /* dest */ int x, int y, int cx, int cy)
358 {
359 xwin_set_function(opcode);
360
361 XFillRectangle(display, wnd, gc, x, y, cx, cy);
362 }
363
364 void ui_patblt(uint8 opcode,
365 /* dest */ int x, int y, int cx, int cy,
366 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
367 {
368 Display *dpy = display;
369 Pixmap fill;
370
371 xwin_set_function(opcode);
372
373 switch (brush->style)
374 {
375 case 0: /* Solid */
376 XSetForeground(dpy, gc, fgcolour);
377 XFillRectangle(dpy, wnd, gc, x, y, cx, cy);
378 break;
379
380 case 3: /* Pattern */
381 fill = (Pixmap)ui_create_glyph(8, 8, brush->pattern);
382
383 XSetForeground(dpy, gc, fgcolour);
384 XSetBackground(dpy, gc, bgcolour);
385 XSetFillStyle(dpy, gc, FillOpaqueStippled);
386 XSetStipple(dpy, gc, fill);
387
388 XFillRectangle(dpy, wnd, gc, x, y, cx, cy);
389
390 XSetFillStyle(dpy, gc, FillSolid);
391 ui_destroy_glyph((HGLYPH)fill);
392 break;
393
394 default:
395 NOTIMP("brush %d\n", brush->style);
396 }
397 }
398
399 void ui_screenblt(uint8 opcode,
400 /* dest */ int x, int y, int cx, int cy,
401 /* src */ int srcx, int srcy)
402 {
403 xwin_set_function(opcode);
404
405 XCopyArea(display, wnd, wnd, gc, srcx, srcy,
406 cx, cy, x, y);
407 }
408
409 void ui_memblt(uint8 opcode,
410 /* dest */ int x, int y, int cx, int cy,
411 /* src */ HBITMAP src, int srcx, int srcy)
412 {
413 xwin_set_function(opcode);
414
415 XCopyArea(display, (Pixmap)src, wnd, gc, srcx, srcy,
416 cx, cy, x, y);
417 }
418
419 void ui_triblt(uint8 opcode,
420 /* dest */ int x, int y, int cx, int cy,
421 /* src */ HBITMAP src, int srcx, int srcy,
422 /* brush */ BRUSH *brush, int bgcolour, int fgcolour)
423 {
424 /* This is potentially difficult to do in general. Until someone
425 comes up with a more efficient way of doing it I am using cases. */
426
427 switch (opcode)
428 {
429 case 0x69: /* PDSxxn */
430 ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
431 ui_patblt(ROP2_NXOR, x, y, cx, cy,
432 brush, bgcolour, fgcolour);
433 break;
434
435 case 0xb8: /* PSDPxax */
436 ui_patblt(ROP2_XOR, x, y, cx, cy,
437 brush, bgcolour, fgcolour);
438 ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
439 ui_patblt(ROP2_XOR, x, y, cx, cy,
440 brush, bgcolour, fgcolour);
441 break;
442
443 default:
444 NOTIMP("triblt 0x%x\n", opcode);
445 ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
446 }
447 }
448
449 void ui_line(uint8 opcode,
450 /* dest */ int startx, int starty, int endx, int endy,
451 /* pen */ PEN *pen)
452 {
453 xwin_set_function(opcode);
454
455 XSetForeground(display, gc, pen->colour);
456 XDrawLine(display, wnd, gc, startx, starty, endx, endy);
457 }
458
459 void ui_rect(
460 /* dest */ int x, int y, int cx, int cy,
461 /* brush */ int colour)
462 {
463 xwin_set_function(ROP2_COPY);
464
465 XSetForeground(display, gc, colour);
466 XFillRectangle(display, wnd, gc, x, y, cx, cy);
467 }
468
469 void ui_draw_glyph(int mixmode,
470 /* dest */ int x, int y, int cx, int cy,
471 /* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)
472 {
473 Pixmap pixmap = (Pixmap)glyph;
474
475 xwin_set_function(ROP2_COPY);
476
477 XSetForeground(display, gc, fgcolour);
478
479 switch (mixmode)
480 {
481 case MIX_TRANSPARENT:
482 XSetStipple(display, gc, pixmap);
483 XSetFillStyle(display, gc, FillStippled);
484 XSetTSOrigin(display, gc, x, y);
485 XFillRectangle(display, wnd, gc,
486 x, y, cx, cy);
487 XSetFillStyle(display, gc, FillSolid);
488 break;
489
490 case MIX_OPAQUE:
491 XSetBackground(display, gc, bgcolour);
492 XCopyPlane(display, pixmap, wnd, gc,
493 srcx, srcy, cx, cy, x, y, 1);
494 break;
495
496 default:
497 NOTIMP("mix %d\n", mixmode);
498 }
499 }
500
501 void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,
502 int clipx, int clipy, int clipcx, int clipcy,
503 int boxx, int boxy, int boxcx, int boxcy,
504 int bgcolour, int fgcolour, uint8 *text, uint8 length)
505 {
506 FONTGLYPH *glyph;
507 int i;
508
509 if (boxcx > 1)
510 {
511 ui_rect(boxx, boxy, boxcx, boxcy, bgcolour);
512 }
513 else if (mixmode == MIX_OPAQUE)
514 {
515 ui_rect(clipx, clipy, clipcx, clipcy, bgcolour);
516 }
517
518 /* Paint text, character by character */
519 for (i = 0; i < length; i++)
520 {
521 glyph = cache_get_font(font, text[i]);
522
523 if (!(flags & TEXT2_IMPLICIT_X))
524 x += text[++i];
525
526 if (glyph != NULL)
527 {
528 ui_draw_glyph(mixmode, x + (short)glyph->offset,
529 y + (short)glyph->baseline,
530 glyph->width, glyph->height,
531 glyph->pixmap, 0, 0,
532 bgcolour, fgcolour);
533
534 if (flags & TEXT2_IMPLICIT_X)
535 x += glyph->width;
536 }
537 }
538 }
539
540 void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
541 {
542 XImage *image;
543
544 image = XGetImage(display, wnd, x, y, cx, cy, 0xffffffff, ZPixmap);
545 cache_put_desktop(offset, cx, cy, image->bytes_per_line, image->data);
546 XFree(image->data);
547 XFree(image);
548 }
549
550 void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
551 {
552 XImage *image;
553 uint8 *data;
554
555 data = cache_get_desktop(offset, cx, cy);
556 if (data == NULL)
557 return;
558
559 image = XCreateImage(display, visual, 8, ZPixmap, 0,
560 data, cx, cy, 32, cx);
561 XSetFunction(display, gc, GXcopy);
562 XPutImage(display, wnd, gc, image, 0, 0, x, y, cx, cy);
563 XFree(image);
564 }

  ViewVC Help
Powered by ViewVC 1.1.26