--- sourceforge.net/trunk/rdesktop/xwin.c 2005/02/28 22:38:24 822 +++ sourceforge.net/trunk/rdesktop/xwin.c 2005/08/04 13:39:57 976 @@ -1,7 +1,7 @@ /* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. User interface services - X Window System - Copyright (C) Matthew Chapman 1999-2002 + Copyright (C) Matthew Chapman 1999-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,6 +32,7 @@ extern int g_height; extern int g_xpos; extern int g_ypos; +extern int g_pos; extern BOOL g_sendmotion; extern BOOL g_fullscreen; extern BOOL g_grab_keyboard; @@ -119,6 +120,31 @@ XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \ } +#define FILL_POLYGON(p,np)\ +{ \ + XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \ + if (g_ownbackstore) \ + XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \ +} + +#define DRAW_ELLIPSE(x,y,cx,cy,m)\ +{ \ + switch (m) \ + { \ + case 0: /* Outline */ \ + XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \ + if (g_ownbackstore) \ + XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \ + break; \ + case 1: /* Filled */ \ + XFillArc(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, \ + cx, cy, 0, 360*64); \ + if (g_ownbackstore) \ + XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); \ + break; \ + } \ +} + /* colour maps */ extern BOOL g_owncolmap; static Colormap g_xcolmap; @@ -662,6 +688,7 @@ } else { + while (out < end) { pixel = *(data++); SPLITCOLOUR16(pixel, pc); @@ -1137,6 +1164,12 @@ wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width; wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height; + /* Handle -x-y portion of geometry string */ + if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2))) + g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width; + if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4))) + g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height; + attribs.background_pixel = BlackPixelOfScreen(g_screen); attribs.border_pixel = WhitePixelOfScreen(g_screen); attribs.backing_store = g_ownbackstore ? NotUseful : Always; @@ -1180,6 +1213,8 @@ if (sizehints) { sizehints->flags = PMinSize | PMaxSize; + if (g_pos) + sizehints->flags |= PPosition; sizehints->min_width = sizehints->max_width = g_width; sizehints->min_height = sizehints->max_height = g_height; XSetWMNormalHints(g_display, g_wnd, sizehints); @@ -1192,7 +1227,7 @@ } input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | - VisibilityChangeMask | FocusChangeMask; + VisibilityChangeMask | FocusChangeMask | StructureNotifyMask; if (g_sendmotion) input_mask |= PointerMotionMask; @@ -1306,7 +1341,7 @@ } } -/* Process all events in Xlib queue +/* Process events in Xlib queue Returns 0 after user quit, 1 otherwise */ static int xwin_process_events(void) @@ -1315,11 +1350,11 @@ KeySym keysym; uint16 button, flags; uint32 ev_time; - key_translation tr; char str[256]; Status status; + int events = 0; - while (XPending(g_display) > 0) + while ((XPending(g_display) > 0) && events++ < 20) { XNextEvent(g_display, &xevent); @@ -1367,24 +1402,15 @@ str, sizeof(str), &keysym, NULL); } - DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym, + DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym, get_ksname(keysym))); ev_time = time(NULL); if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True)) break; - tr = xkeymap_translate_key(keysym, - xevent.xkey.keycode, xevent.xkey.state); - - if (tr.scancode == 0) - break; - - save_remote_modifiers(tr.scancode); - ensure_remote_modifiers(ev_time, tr); - rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode); - restore_remote_modifiers(ev_time, tr.scancode); - + xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state, + ev_time, True, 0); break; case KeyRelease: @@ -1392,20 +1418,15 @@ XLookupString((XKeyEvent *) & xevent, str, sizeof(str), &keysym, NULL); - DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym, + DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym, get_ksname(keysym))); ev_time = time(NULL); if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False)) break; - tr = xkeymap_translate_key(keysym, - xevent.xkey.keycode, xevent.xkey.state); - - if (tr.scancode == 0) - break; - - rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode); + xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state, + ev_time, False, 0); break; case ButtonPress: @@ -1563,6 +1584,12 @@ case PropertyNotify: xclip_handle_PropertyNotify(&xevent.xproperty); break; + case MapNotify: + rdp_send_client_window_status(1); + break; + case UnmapNotify: + rdp_send_client_window_status(0); + break; } } /* Keep going */ @@ -2165,6 +2192,151 @@ FILL_RECTANGLE(x, y, cx, cy); } +void +ui_polygon(uint8 opcode, + /* mode */ uint8 fillmode, + /* dest */ POINT * point, int npoints, + /* brush */ BRUSH * brush, int bgcolour, int fgcolour) +{ + uint8 style, i, ipattern[8]; + Pixmap fill; + + SET_FUNCTION(opcode); + + switch (fillmode) + { + case ALTERNATE: + XSetFillRule(g_display, g_gc, EvenOddRule); + break; + case WINDING: + XSetFillRule(g_display, g_gc, WindingRule); + break; + default: + unimpl("fill mode %d\n", fillmode); + } + + if (brush) + style = brush->style; + else + style = 0; + + switch (style) + { + case 0: /* Solid */ + SET_FOREGROUND(fgcolour); + FILL_POLYGON((XPoint *) point, npoints); + break; + + case 2: /* Hatch */ + fill = (Pixmap) ui_create_glyph(8, 8, + hatch_patterns + brush->pattern[0] * 8); + SET_FOREGROUND(fgcolour); + SET_BACKGROUND(bgcolour); + XSetFillStyle(g_display, g_gc, FillOpaqueStippled); + XSetStipple(g_display, g_gc, fill); + XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin); + FILL_POLYGON((XPoint *) point, npoints); + XSetFillStyle(g_display, g_gc, FillSolid); + XSetTSOrigin(g_display, g_gc, 0, 0); + ui_destroy_glyph((HGLYPH) fill); + break; + + case 3: /* Pattern */ + for (i = 0; i != 8; i++) + ipattern[7 - i] = brush->pattern[i]; + fill = (Pixmap) ui_create_glyph(8, 8, ipattern); + SET_FOREGROUND(bgcolour); + SET_BACKGROUND(fgcolour); + XSetFillStyle(g_display, g_gc, FillOpaqueStippled); + XSetStipple(g_display, g_gc, fill); + XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin); + FILL_POLYGON((XPoint *) point, npoints); + XSetFillStyle(g_display, g_gc, FillSolid); + XSetTSOrigin(g_display, g_gc, 0, 0); + ui_destroy_glyph((HGLYPH) fill); + break; + + default: + unimpl("brush %d\n", brush->style); + } + + RESET_FUNCTION(opcode); +} + +void +ui_polyline(uint8 opcode, + /* dest */ POINT * points, int npoints, + /* pen */ PEN * pen) +{ + /* TODO: set join style */ + SET_FUNCTION(opcode); + SET_FOREGROUND(pen->colour); + XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious); + if (g_ownbackstore) + XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints, + CoordModePrevious); + RESET_FUNCTION(opcode); +} + +void +ui_ellipse(uint8 opcode, + /* mode */ uint8 fillmode, + /* dest */ int x, int y, int cx, int cy, + /* brush */ BRUSH * brush, int bgcolour, int fgcolour) +{ + uint8 style, i, ipattern[8]; + Pixmap fill; + + SET_FUNCTION(opcode); + + if (brush) + style = brush->style; + else + style = 0; + + switch (style) + { + case 0: /* Solid */ + SET_FOREGROUND(fgcolour); + DRAW_ELLIPSE(x, y, cx, cy, fillmode); + break; + + case 2: /* Hatch */ + fill = (Pixmap) ui_create_glyph(8, 8, + hatch_patterns + brush->pattern[0] * 8); + SET_FOREGROUND(fgcolour); + SET_BACKGROUND(bgcolour); + XSetFillStyle(g_display, g_gc, FillOpaqueStippled); + XSetStipple(g_display, g_gc, fill); + XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin); + DRAW_ELLIPSE(x, y, cx, cy, fillmode); + XSetFillStyle(g_display, g_gc, FillSolid); + XSetTSOrigin(g_display, g_gc, 0, 0); + ui_destroy_glyph((HGLYPH) fill); + break; + + case 3: /* Pattern */ + for (i = 0; i != 8; i++) + ipattern[7 - i] = brush->pattern[i]; + fill = (Pixmap) ui_create_glyph(8, 8, ipattern); + SET_FOREGROUND(bgcolour); + SET_BACKGROUND(fgcolour); + XSetFillStyle(g_display, g_gc, FillOpaqueStippled); + XSetStipple(g_display, g_gc, fill); + XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin); + DRAW_ELLIPSE(x, y, cx, cy, fillmode); + XSetFillStyle(g_display, g_gc, FillSolid); + XSetTSOrigin(g_display, g_gc, 0, 0); + ui_destroy_glyph((HGLYPH) fill); + break; + + default: + unimpl("brush %d\n", brush->style); + } + + RESET_FUNCTION(opcode); +} + /* warning, this function only draws on wnd or backstore, not both */ void ui_draw_glyph(int mixmode, @@ -2220,11 +2392,13 @@ } void -ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y, +ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y, int clipx, int clipy, int clipcx, int clipcy, - int boxx, int boxy, int boxcx, int boxcy, int bgcolour, - int fgcolour, uint8 * text, uint8 length) + int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush, + int bgcolour, int fgcolour, uint8 * text, uint8 length) { + /* TODO: use brush appropriately */ + FONTGLYPH *glyph; int i, j, xyoffset, x1, y1; DATABLOB *entry;