--- sourceforge.net/trunk/rdesktop/xwin.c 2004/03/13 12:08:18 636 +++ sourceforge.net/trunk/rdesktop/xwin.c 2004/06/11 22:37:05 709 @@ -43,8 +43,9 @@ static int g_x_socket; static Screen *g_screen; Window g_wnd; -uint32 g_embed_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; @@ -57,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; @@ -65,7 +67,7 @@ static int g_red_shift_l, g_blue_shift_l, g_green_shift_l; /* software backing store */ -BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */ +extern BOOL g_ownbackstore; static Pixmap g_backstore = 0; /* Moving in single app mode */ @@ -114,7 +116,7 @@ } /* colour maps */ -BOOL g_owncolmap = False; +extern BOOL g_owncolmap; static Colormap g_xcolmap; static uint32 *g_colmap = NULL; @@ -170,9 +172,9 @@ split_colour15(uint32 colour) { PixelColour rv; - rv.red = (colour & 0x7c00) >> 7; - rv.green = (colour & 0x03e0) >> 2; - rv.blue = (colour & 0x001f) << 3; + 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; } @@ -180,9 +182,9 @@ split_colour16(uint32 colour) { PixelColour rv; - rv.red = (colour & 0xf800) >> 8; - rv.green = (colour & 0x07e0) >> 3; - rv.blue = (colour & 0x001f) << 3; + 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; } @@ -228,6 +230,32 @@ return make_colour(pc); } +/* indent is confused by UNROLL8 */ +/* *INDENT-OFF* */ + +/* repeat and unroll, similar to bitmap.c */ +/* potentialy any of the following translate */ +/* functions can use repeat but just doing */ +/* the most common ones */ + +#define UNROLL8(stm) { stm stm stm stm stm stm stm stm } +/* 2 byte output repeat */ +#define REPEAT2(stm) \ +{ \ + while (out <= end - 8 * 2) \ + UNROLL8(stm) \ + while (out < end) \ + { stm } \ +} +/* 4 byte output repeat */ +#define REPEAT4(stm) \ +{ \ + while (out <= end - 8 * 4) \ + UNROLL8(stm) \ + while (out < end) \ + { stm } \ +} + static void translate8to8(uint8 * data, uint8 * out, uint8 * end) { @@ -240,17 +268,28 @@ { uint16 value; - while (out < end) + if (g_arch_match) { - value = (uint16) g_colmap[*(data++)]; - - if (g_xserver_be) + REPEAT2 + ( + *((uint16 *) out) = g_colmap[*(data++)]; + out += 2; + ) + } + else if (g_xserver_be) + { + while (out < end) { + value = (uint16) g_colmap[*(data++)]; *(out++) = value >> 8; *(out++) = value; } - else + } + else + { + while (out < end) { + value = (uint16) g_colmap[*(data++)]; *(out++) = value; *(out++) = value >> 8; } @@ -263,18 +302,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; @@ -287,19 +329,30 @@ { uint32 value; - while (out < end) + if (g_arch_match) { - value = g_colmap[*(data++)]; - - if (g_xserver_be) + REPEAT4 + ( + *((uint32 *) out) = g_colmap[*(data++)]; + out += 4; + ) + } + else if (g_xserver_be) + { + while (out < end) { + value = g_colmap[*(data++)]; *(out++) = value >> 24; *(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; @@ -308,6 +361,8 @@ } } +/* *INDENT-ON* */ + static void translate15to16(uint16 * data, uint8 * out, uint8 * end) { @@ -588,9 +643,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) { @@ -728,6 +798,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 */ @@ -754,6 +828,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); @@ -793,10 +872,6 @@ g_ownbackstore = True; } - test = 1; - g_host_be = !(BOOL) (*(uint8 *) (&test)); - g_xserver_be = (ImageByteOrder(g_display) == MSBFirst); - /* * Determine desktop size */ @@ -926,10 +1001,10 @@ XFree(sizehints); } - if ( g_embed_wnd ) - { - XReparentWindow(g_display, g_wnd, (Window)g_embed_wnd, 0, 0); - } + if (g_embed_wnd) + { + XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0); + } input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask; @@ -962,6 +1037,7 @@ XMaskEvent(g_display, VisibilityChangeMask, &xevent); } while (xevent.type != VisibilityNotify); + g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured; g_focused = False; g_mouse_in_wnd = False; @@ -979,6 +1055,39 @@ } void +ui_resize_window() +{ + XSizeHints *sizehints; + Pixmap bs; + + 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); + } + + /* create new backstore pixmap */ + if (g_backstore != 0) + { + bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth); + XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen)); + XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height); + XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0); + XFreePixmap(g_display, g_backstore); + g_backstore = bs; + } +} + +void ui_destroy_window(void) { if (g_IC != NULL) @@ -1039,6 +1148,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) @@ -1372,7 +1484,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; } @@ -1411,7 +1523,7 @@ } XFree(image); - if (!g_owncolmap) + if (tdata != data) xfree(tdata); } @@ -1735,7 +1847,7 @@ { case 0: /* Solid */ SET_FOREGROUND(fgcolour); - FILL_RECTANGLE(x, y, cx, cy); + FILL_RECTANGLE_BACKSTORE(x, y, cx, cy); break; case 2: /* Hatch */ @@ -1746,7 +1858,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); @@ -1756,15 +1868,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); @@ -1775,6 +1884,9 @@ } RESET_FUNCTION(opcode); + + if (g_ownbackstore) + XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); } void @@ -1785,8 +1897,18 @@ SET_FUNCTION(opcode); if (g_ownbackstore) { - 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); + 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 {