--- sourceforge.net/trunk/rdesktop/xwin.c 2006/12/07 15:23:45 1346 +++ sourceforge.net/trunk/rdesktop/xwin.c 2007/05/14 12:11:15 1407 @@ -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-2005 + Copyright (C) Matthew Chapman 1999-2007 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 @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -28,18 +29,15 @@ #include "rdesktop.h" #include "xproto.h" -/* We can't include Xproto.h because of conflicting defines for BOOL */ -#define X_ConfigureWindow 12 - extern int g_width; 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; -extern BOOL g_hide_decorations; +extern RD_BOOL g_sendmotion; +extern RD_BOOL g_fullscreen; +extern RD_BOOL g_grab_keyboard; +extern RD_BOOL g_hide_decorations; extern char g_title[]; /* Color depth of the RDP session. As of RDP 5.1, it may be 8, 15, 16 or 24. */ @@ -71,7 +69,7 @@ unsigned int desktop; struct timeval *position_timer; - BOOL outstanding_position; + RD_BOOL outstanding_position; unsigned int outpos_serial; int outpos_xoffset, outpos_yoffset; int outpos_width, outpos_height; @@ -80,14 +78,14 @@ } seamless_window; static seamless_window *g_seamless_windows = NULL; static unsigned long g_seamless_focused = 0; -static BOOL g_seamless_started = False; /* Server end is up and running */ -static BOOL g_seamless_active = False; /* We are currently in seamless mode */ -static BOOL g_seamless_hidden = False; /* Desktop is hidden on server */ -extern BOOL g_seamless_rdp; +static RD_BOOL g_seamless_started = False; /* Server end is up and running */ +static RD_BOOL g_seamless_active = False; /* We are currently in seamless mode */ +static RD_BOOL g_seamless_hidden = False; /* Desktop is hidden on server */ +extern RD_BOOL g_seamless_rdp; extern uint32 g_embed_wnd; -BOOL g_enable_compose = False; -BOOL g_Unobscured; /* used for screenblt */ +RD_BOOL g_enable_compose = False; +RD_BOOL g_Unobscured; /* used for screenblt */ static GC g_gc = NULL; static GC g_create_bitmap_gc = NULL; static GC g_create_glyph_gc = NULL; @@ -104,20 +102,23 @@ static XIM g_IM; static XIC g_IC; static XModifierKeymap *g_mod_map; +/* Maps logical (xmodmap -pp) pointing device buttons (0-based) back + to physical (1-based) indices. */ +static unsigned char g_pointer_log_to_phys_map[16]; static Cursor g_current_cursor; -static HCURSOR g_null_cursor = NULL; +static RD_HCURSOR g_null_cursor = NULL; static Atom g_protocol_atom, g_kill_atom; extern Atom g_net_wm_state_atom; extern Atom g_net_wm_desktop_atom; -static BOOL g_focused; -static BOOL g_mouse_in_wnd; +static RD_BOOL g_focused; +static RD_BOOL g_mouse_in_wnd; /* Indicates that: 1) visual has 15, 16 or 24 depth and the same color channel masks as its RDP equivalent (implies X server is LE), 2) host is LE This will trigger an optimization whose real value is questionable. */ -static BOOL g_compatible_arch; +static RD_BOOL g_compatible_arch; /* Indicates whether RDP's bitmaps and our XImages have the same binary format. If so, we can avoid an expensive translation. Note that this can be true when g_compatible_arch is false, @@ -128,26 +129,26 @@ ('host' is the machine running rdesktop; the host simply memcpy's so its endianess doesn't matter) */ -static BOOL g_no_translate_image = False; +static RD_BOOL g_no_translate_image = False; /* endianness */ -static BOOL g_host_be; -static BOOL g_xserver_be; +static RD_BOOL g_host_be; +static RD_BOOL g_xserver_be; static int g_red_shift_r, g_blue_shift_r, g_green_shift_r; static int g_red_shift_l, g_blue_shift_l, g_green_shift_l; /* software backing store */ -extern BOOL g_ownbackstore; +extern RD_BOOL g_ownbackstore; static Pixmap g_backstore = 0; /* Moving in single app mode */ -static BOOL g_moving_wnd; +static RD_BOOL g_moving_wnd; static int g_move_x_offset = 0; static int g_move_y_offset = 0; -static BOOL g_using_full_workarea = False; +static RD_BOOL g_using_full_workarea = False; #ifdef WITH_RDPSND -extern BOOL g_rdpsnd; +extern RD_BOOL g_rdpsnd; #endif /* MWM decorations */ @@ -248,7 +249,7 @@ } /* colour maps */ -extern BOOL g_owncolmap; +extern RD_BOOL g_owncolmap; static Colormap g_xcolmap; static uint32 *g_colmap = NULL; @@ -472,7 +473,7 @@ static seamless_group * -sw_find_group(unsigned long id, BOOL dont_create) +sw_find_group(unsigned long id, RD_BOOL dont_create) { seamless_window *sw; seamless_group *sg; @@ -1262,7 +1263,23 @@ return out; } -BOOL +static void +xwin_refresh_pointer_map(void) +{ + unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)]; + int i, pointer_buttons; + + pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map)); + for (i = 0; i < pointer_buttons; ++i) + { + /* This might produce multiple logical buttons mapping + to a single physical one, but hey, that's + life... */ + g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1; + } +} + +RD_BOOL get_key_state(unsigned int state, uint32 keysym) { int modifierpos, key, keysymMask = 0; @@ -1310,7 +1327,7 @@ return weight; } -static BOOL +static RD_BOOL select_visual(int screen_num) { XPixmapFormatValues *pfm; @@ -1349,7 +1366,7 @@ for (i = 0; i < visuals_count; ++i) { XVisualInfo *visual_info = &vmatches[i]; - BOOL can_translate_to_bpp = False; + RD_BOOL can_translate_to_bpp = False; int j; /* Try to find a no-translation visual that'll @@ -1521,7 +1538,7 @@ return g_old_error_handler(dpy, eev); } -BOOL +RD_BOOL ui_init(void) { int screen_num; @@ -1535,7 +1552,7 @@ { uint16 endianess_test = 1; - g_host_be = !(BOOL) (*(uint8 *) (&endianess_test)); + g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test)); } g_old_error_handler = XSetErrorHandler(error_handler); @@ -1616,6 +1633,7 @@ g_width = (g_width + 3) & ~3; g_mod_map = XGetModifierMapping(g_display); + xwin_refresh_pointer_map(); xkeymap_init(); @@ -1687,7 +1705,7 @@ *input_mask |= LeaveWindowMask; } -BOOL +RD_BOOL ui_create_window(void) { uint8 null_pointer_mask[1] = { 0x80 }; @@ -1735,6 +1753,7 @@ } XStoreName(g_display, g_wnd, g_title); + ewmh_set_wm_name(g_wnd, g_title); if (g_hide_decorations) mwm_hide_decorations(g_wnd); @@ -1874,10 +1893,16 @@ } static void -handle_button_event(XEvent xevent, BOOL down) +handle_button_event(XEvent xevent, RD_BOOL down) { uint16 button, flags = 0; g_last_gesturetime = xevent.xbutton.time; + /* Reverse the pointer button mapping, e.g. in the case of + "left-handed mouse mode"; the RDP session expects to + receive physical buttons (true in mstsc as well) and + logical button behavior depends on the remote desktop's own + mouse settings */ + xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1]; button = xkeymap_translate_button(xevent.xbutton.button); if (button == 0) return; @@ -2165,6 +2190,12 @@ XFreeModifiermap(g_mod_map); g_mod_map = XGetModifierMapping(g_display); } + + if (xevent.xmapping.request == MappingPointer) + { + xwin_refresh_pointer_map(); + } + break; /* clipboard stuff */ @@ -2248,7 +2279,7 @@ int n; fd_set rfds, wfds; struct timeval tv; - BOOL s_timeout = False; + RD_BOOL s_timeout = False; while (True) { @@ -2292,7 +2323,7 @@ /* Abort serial read calls */ if (s_timeout) - rdpdr_check_fds(&rfds, &wfds, (BOOL) True); + rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True); continue; } @@ -2300,7 +2331,7 @@ rdpsnd_check_fds(&rfds, &wfds); #endif - rdpdr_check_fds(&rfds, &wfds, (BOOL) False); + rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False); if (FD_ISSET(rdp_socket, &rfds)) return 1; @@ -2314,7 +2345,7 @@ XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y); } -HBITMAP +RD_HBITMAP ui_create_bitmap(int width, int height, uint8 * data) { XImage *image; @@ -2344,7 +2375,7 @@ XFree(image); if (tdata != data) xfree(tdata); - return (HBITMAP) bitmap; + return (RD_HBITMAP) bitmap; } void @@ -2392,12 +2423,12 @@ } void -ui_destroy_bitmap(HBITMAP bmp) +ui_destroy_bitmap(RD_HBITMAP bmp) { XFreePixmap(g_display, (Pixmap) bmp); } -HGLYPH +RD_HGLYPH ui_create_glyph(int width, int height, uint8 * data) { XImage *image; @@ -2419,20 +2450,20 @@ XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height); XFree(image); - return (HGLYPH) bitmap; + return (RD_HGLYPH) bitmap; } void -ui_destroy_glyph(HGLYPH glyph) +ui_destroy_glyph(RD_HGLYPH glyph) { XFreePixmap(g_display, (Pixmap) glyph); } -HCURSOR +RD_HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask, uint8 * xormask) { - HGLYPH maskglyph, cursorglyph; + RD_HGLYPH maskglyph, cursorglyph; XColor bg, fg; Cursor xcursor; uint8 *cursor, *pcursor; @@ -2496,11 +2527,11 @@ ui_destroy_glyph(cursorglyph); xfree(mask); xfree(cursor); - return (HCURSOR) xcursor; + return (RD_HCURSOR) xcursor; } void -ui_set_cursor(HCURSOR cursor) +ui_set_cursor(RD_HCURSOR cursor) { g_current_cursor = (Cursor) cursor; XDefineCursor(g_display, g_wnd, g_current_cursor); @@ -2508,7 +2539,7 @@ } void -ui_destroy_cursor(HCURSOR cursor) +ui_destroy_cursor(RD_HCURSOR cursor) { XFreeCursor(g_display, (Cursor) cursor); } @@ -2526,7 +2557,7 @@ (xc)->flags = DoRed | DoGreen | DoBlue; -HCOLOURMAP +RD_HCOLOURMAP ui_create_colourmap(COLOURMAP * colours) { COLOURENTRY *entry; @@ -2622,12 +2653,12 @@ XStoreColors(g_display, map, xcolours, ncolours); xfree(xcolours); - return (HCOLOURMAP) map; + return (RD_HCOLOURMAP) map; } } void -ui_destroy_colourmap(HCOLOURMAP map) +ui_destroy_colourmap(RD_HCOLOURMAP map) { if (!g_owncolmap) xfree(map); @@ -2636,7 +2667,7 @@ } void -ui_set_colourmap(HCOLOURMAP map) +ui_set_colourmap(RD_HCOLOURMAP map) { if (!g_owncolmap) { @@ -2724,7 +2755,7 @@ 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); + ui_destroy_glyph((RD_HGLYPH) fill); break; case 3: /* Pattern */ @@ -2739,7 +2770,7 @@ 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); + ui_destroy_glyph((RD_HGLYPH) fill); break; default: @@ -2782,7 +2813,7 @@ void ui_memblt(uint8 opcode, /* dest */ int x, int y, int cx, int cy, - /* src */ HBITMAP src, int srcx, int srcy) + /* src */ RD_HBITMAP src, int srcx, int srcy) { SET_FUNCTION(opcode); XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y); @@ -2797,7 +2828,7 @@ void ui_triblt(uint8 opcode, /* dest */ int x, int y, int cx, int cy, - /* src */ HBITMAP src, int srcx, int srcy, + /* src */ RD_HBITMAP src, int srcx, int srcy, /* brush */ BRUSH * brush, int bgcolour, int fgcolour) { /* This is potentially difficult to do in general. Until someone @@ -2855,7 +2886,7 @@ void ui_polygon(uint8 opcode, /* mode */ uint8 fillmode, - /* dest */ POINT * point, int npoints, + /* dest */ RD_POINT * point, int npoints, /* brush */ BRUSH * brush, int bgcolour, int fgcolour) { uint8 style, i, ipattern[8]; @@ -2898,7 +2929,7 @@ FILL_POLYGON((XPoint *) point, npoints); XSetFillStyle(g_display, g_gc, FillSolid); XSetTSOrigin(g_display, g_gc, 0, 0); - ui_destroy_glyph((HGLYPH) fill); + ui_destroy_glyph((RD_HGLYPH) fill); break; case 3: /* Pattern */ @@ -2913,7 +2944,7 @@ FILL_POLYGON((XPoint *) point, npoints); XSetFillStyle(g_display, g_gc, FillSolid); XSetTSOrigin(g_display, g_gc, 0, 0); - ui_destroy_glyph((HGLYPH) fill); + ui_destroy_glyph((RD_HGLYPH) fill); break; default: @@ -2925,7 +2956,7 @@ void ui_polyline(uint8 opcode, - /* dest */ POINT * points, int npoints, + /* dest */ RD_POINT * points, int npoints, /* pen */ PEN * pen) { /* TODO: set join style */ @@ -2976,7 +3007,7 @@ 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); + ui_destroy_glyph((RD_HGLYPH) fill); break; case 3: /* Pattern */ @@ -2991,7 +3022,7 @@ 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); + ui_destroy_glyph((RD_HGLYPH) fill); break; default: @@ -3005,7 +3036,7 @@ void ui_draw_glyph(int mixmode, /* dest */ int x, int y, int cx, int cy, - /* src */ HGLYPH glyph, int srcx, int srcy, + /* src */ RD_HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour) { SET_FOREGROUND(fgcolour); @@ -3219,7 +3250,7 @@ return; image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0, - (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8); + (char *) data, cx, cy, g_bpp, 0); if (g_ownbackstore) { @@ -3253,7 +3284,7 @@ void -ui_seamless_begin(BOOL hidden) +ui_seamless_begin(RD_BOOL hidden) { if (!g_seamless_rdp) return;