--- sourceforge.net/trunk/rdesktop/xwin.c 2004/02/07 18:47:06 603 +++ sourceforge.net/trunk/rdesktop/xwin.c 2004/05/27 10:19:41 704 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,9 @@ static int g_x_socket; static Screen *g_screen; Window g_wnd; +extern uint32 g_embed_wnd; BOOL g_enable_compose = False; +BOOL g_Unobscured; /* used for screenblt */ static GC g_gc = NULL; static Visual *g_visual; static int g_depth; @@ -55,6 +58,7 @@ static Atom g_protocol_atom, g_kill_atom; static BOOL g_focused; static BOOL g_mouse_in_wnd; +static BOOL g_arch_match = False; /* set to True if RGB XServer and little endian */ /* endianness */ static BOOL g_host_be; @@ -63,7 +67,7 @@ static int g_red_shift_l, g_blue_shift_l, g_green_shift_l; /* software backing store */ -static BOOL g_ownbackstore; +extern BOOL g_ownbackstore; static Pixmap g_backstore = 0; /* Moving in single app mode */ @@ -112,7 +116,7 @@ } /* colour maps */ -BOOL g_owncolmap = False; +extern BOOL g_owncolmap; static Colormap g_xcolmap; static uint32 *g_colmap = NULL; @@ -168,12 +172,9 @@ split_colour15(uint32 colour) { PixelColour rv; - rv.red = (colour & 0x7c00) >> 10; - rv.red = (rv.red * 0xff) / 0x1f; - rv.green = (colour & 0x03e0) >> 5; - rv.green = (rv.green * 0xff) / 0x1f; - rv.blue = (colour & 0x1f); - rv.blue = (rv.blue * 0xff) / 0x1f; + rv.red = ((colour >> 7 ) & 0xf8) | ((colour >> 12) & 0x7); + rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); + rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); return rv; } @@ -181,12 +182,9 @@ split_colour16(uint32 colour) { PixelColour rv; - rv.red = (colour & 0xf800) >> 11; - rv.red = (rv.red * 0xff) / 0x1f; - rv.green = (colour & 0x07e0) >> 5; - rv.green = (rv.green * 0xff) / 0x3f; - rv.blue = (colour & 0x001f); - rv.blue = (rv.blue * 0xff) / 0x1f; + rv.red = ((colour >> 8 ) & 0xf8) | ((colour >> 13) & 0x7); + rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); + rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); return rv; } @@ -195,8 +193,8 @@ { PixelColour rv; rv.blue = (colour & 0xff0000) >> 16; - rv.green = (colour & 0xff00) >> 8; - rv.red = (colour & 0xff); + rv.green = (colour & 0x00ff00) >> 8; + rv.red = (colour & 0x0000ff); return rv; } @@ -232,6 +230,15 @@ return make_colour(pc); } +#define UNROLL8(stm) { stm stm stm stm stm stm stm stm } +#define REPEAT(stm) \ +{ \ + while (out <= end - 8 * 4) \ + UNROLL8(stm) \ + while (out < end) \ + { stm } \ +} + static void translate8to8(uint8 * data, uint8 * out, uint8 * end) { @@ -244,22 +251,29 @@ { uint16 value; + if (g_arch_match) + REPEAT(*((uint16 *) out) = g_colmap[*(data++)]; out += 2; + ) + else +if (g_xserver_be) +{ while (out < end) { value = (uint16) g_colmap[*(data++)]; - - if (g_xserver_be) - { - *(out++) = value >> 8; - *(out++) = value; - } - else - { - *(out++) = value; - *(out++) = value >> 8; - } + *(out++) = value >> 8; + *(out++) = value; } } +else +{ + while (out < end) + { + value = (uint16) g_colmap[*(data++)]; + *(out++) = value; + *(out++) = value >> 8; + } +} +} /* little endian - conversion happens when colourmap is built */ static void @@ -267,18 +281,21 @@ { uint32 value; - while (out < end) + if (g_xserver_be) { - value = g_colmap[*(data++)]; - - if (g_xserver_be) + while (out < end) { + value = g_colmap[*(data++)]; *(out++) = value >> 16; *(out++) = value >> 8; *(out++) = value; } - else + } + else + { + while (out < end) { + value = g_colmap[*(data++)]; *(out++) = value; *(out++) = value >> 8; *(out++) = value >> 16; @@ -291,26 +308,33 @@ { uint32 value; + if (g_arch_match) + REPEAT(*((uint32 *) out) = g_colmap[*(data++)]; out += 4; + ) + else +if (g_xserver_be) +{ while (out < end) { value = g_colmap[*(data++)]; - - if (g_xserver_be) - { - *(out++) = value >> 24; - *(out++) = value >> 16; - *(out++) = value >> 8; - *(out++) = value; - } - else - { - *(out++) = value; - *(out++) = value >> 8; - *(out++) = value >> 16; - *(out++) = value >> 24; - } + *(out++) = value >> 24; + *(out++) = value >> 16; + *(out++) = value >> 8; + *(out++) = value; + } +} +else +{ + while (out < end) + { + value = g_colmap[*(data++)]; + *(out++) = value; + *(out++) = value >> 8; + *(out++) = value >> 16; + *(out++) = value >> 24; } } +} static void translate15to16(uint16 * data, uint8 * out, uint8 * end) @@ -592,9 +616,24 @@ static uint8 * translate_image(int width, int height, uint8 * data) { - int size = width * height * g_bpp / 8; - uint8 *out = (uint8 *) xmalloc(size); - uint8 *end = out + size; + int size; + uint8 *out; + uint8 *end; + + /* if server and xserver bpp match, */ + /* and arch(endian) matches, no need to translate */ + /* just return data */ + if (g_arch_match) + { + if (g_depth == 15 && g_server_bpp == 15) + return data; + if (g_depth == 16 && g_server_bpp == 16) + return data; + } + + size = width * height * (g_bpp / 8); + out = (uint8 *) xmalloc(size); + end = out + size; switch (g_server_bpp) { @@ -732,6 +771,10 @@ TrueColorVisual = True; } + test = 1; + g_host_be = !(BOOL) (*(uint8 *) (&test)); + g_xserver_be = (ImageByteOrder(g_display) == MSBFirst); + if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8))) { /* we use a colourmap, so the default visual should do */ @@ -758,6 +801,11 @@ calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l); calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l); calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l); + + /* if RGB video and averything is little endian */ + if (vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) + if (!g_xserver_be && !g_host_be) + g_arch_match = True; } pfm = XListPixmapFormats(g_display, &i); @@ -791,12 +839,11 @@ warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n"); } - if (DoesBackingStore(g_screen) != Always) + if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always)) + { + warning("External BackingStore not available, using internal\n"); g_ownbackstore = True; - - test = 1; - g_host_be = !(BOOL) (*(uint8 *) (&test)); - g_xserver_be = (ImageByteOrder(g_display) == MSBFirst); + } /* * Determine desktop size @@ -927,6 +974,11 @@ XFree(sizehints); } + if (g_embed_wnd) + { + XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0); + } + input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask; @@ -958,6 +1010,7 @@ XMaskEvent(g_display, VisibilityChangeMask, &xevent); } while (xevent.type != VisibilityNotify); + g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured; g_focused = False; g_mouse_in_wnd = False; @@ -975,6 +1028,27 @@ } void +ui_resize_window() +{ + XSizeHints *sizehints; + + sizehints = XAllocSizeHints(); + if (sizehints) + { + sizehints->flags = PMinSize | PMaxSize; + sizehints->min_width = sizehints->max_width = g_width; + sizehints->min_height = sizehints->max_height = g_height; + XSetWMNormalHints(g_display, g_wnd, sizehints); + XFree(sizehints); + } + + if (!(g_fullscreen || g_embed_wnd)) + { + XResizeWindow(g_display, g_wnd, g_width, g_height); + } +} + +void ui_destroy_window(void) { if (g_IC != NULL) @@ -1035,6 +1109,9 @@ switch (xevent.type) { + case VisibilityNotify: + g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured; + break; case ClientMessage: /* the window manager told us to quit */ if ((xevent.xclient.message_type == g_protocol_atom) @@ -1272,13 +1349,14 @@ int ui_select(int rdp_socket) { - int n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket; + int n; fd_set rfds, wfds; struct timeval tv; BOOL s_timeout = False; while (True) { + n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket; /* Process any events already waiting */ if (!xwin_process_events()) /* User quit */ @@ -1367,7 +1445,7 @@ XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height); XFree(image); - if (!g_owncolmap) + if (tdata != data) xfree(tdata); return (HBITMAP) bitmap; } @@ -1406,7 +1484,7 @@ } XFree(image); - if (!g_owncolmap) + if (tdata != data) xfree(tdata); } @@ -1730,7 +1808,7 @@ { case 0: /* Solid */ SET_FOREGROUND(fgcolour); - FILL_RECTANGLE(x, y, cx, cy); + FILL_RECTANGLE_BACKSTORE(x, y, cx, cy); break; case 2: /* Hatch */ @@ -1741,7 +1819,7 @@ XSetFillStyle(g_display, g_gc, FillOpaqueStippled); XSetStipple(g_display, g_gc, fill); XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin); - FILL_RECTANGLE(x, y, cx, cy); + FILL_RECTANGLE_BACKSTORE(x, y, cx, cy); XSetFillStyle(g_display, g_gc, FillSolid); XSetTSOrigin(g_display, g_gc, 0, 0); ui_destroy_glyph((HGLYPH) fill); @@ -1751,15 +1829,12 @@ 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_RECTANGLE(x, y, cx, cy); - + FILL_RECTANGLE_BACKSTORE(x, y, cx, cy); XSetFillStyle(g_display, g_gc, FillSolid); XSetTSOrigin(g_display, g_gc, 0, 0); ui_destroy_glyph((HGLYPH) fill); @@ -1770,6 +1845,9 @@ } RESET_FUNCTION(opcode); + + if (g_ownbackstore) + XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); } void @@ -1778,9 +1856,25 @@ /* src */ int srcx, int srcy) { SET_FUNCTION(opcode); - XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y); if (g_ownbackstore) - XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y); + { + if (g_Unobscured) + { + XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y); + XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, + y); + } + else + { + XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y); + XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, + y); + } + } + else + { + XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y); + } RESET_FUNCTION(opcode); } @@ -1917,6 +2011,12 @@ SET_FOREGROUND(bgcolour); + /* Sometimes, the boxcx value is something really large, like + 32691. This makes XCopyArea fail with Xvnc. The code below + is a quick fix. */ + if (boxx + boxcx > g_width) + boxcx = g_width - boxx; + if (boxcx > 1) { FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);