📄 xwin.c
字号:
/* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. User interface services - X Window System 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <X11/Xlib.h>#include <X11/Xutil.h>#include <unistd.h>#include <sys/time.h>#include <time.h>#include <errno.h>#include <strings.h>#include "rdesktop.h"#include "xproto.h"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 char g_title[];extern int g_server_bpp;extern int g_win_button_size;Display *g_display;Time g_last_gesturetime;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 GC g_create_bitmap_gc = NULL;static GC g_create_glyph_gc = NULL;static Visual *g_visual;static int g_depth;static int g_bpp;static XIM g_IM;static XIC g_IC;static XModifierKeymap *g_mod_map;static Cursor g_current_cursor;static HCURSOR g_null_cursor = NULL;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;static 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;static Pixmap g_backstore = 0;/* Moving in single app mode */static BOOL g_moving_wnd;static int g_move_x_offset = 0;static int g_move_y_offset = 0;#ifdef WITH_RDPSNDextern int g_dsp_fd;extern BOOL g_dsp_busy;extern BOOL g_rdpsnd;#endif/* MWM decorations */#define MWM_HINTS_DECORATIONS (1L << 1)#define PROP_MOTIF_WM_HINTS_ELEMENTS 5typedef struct{ uint32 flags; uint32 functions; uint32 decorations; sint32 inputMode; uint32 status;}PropMotifWmHints;typedef struct{ uint32 red; uint32 green; uint32 blue;}PixelColour;#define FILL_RECTANGLE(x,y,cx,cy)\{ \ XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \ if (g_ownbackstore) \ XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \}#define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\{ \ 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;static uint32 *g_colmap = NULL;#define TRANSLATE(col) ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )#define SET_FOREGROUND(col) XSetForeground(g_display, g_gc, TRANSLATE(col));#define SET_BACKGROUND(col) XSetBackground(g_display, g_gc, TRANSLATE(col));static int rop2_map[] = { GXclear, /* 0 */ GXnor, /* DPon */ GXandInverted, /* DPna */ GXcopyInverted, /* Pn */ GXandReverse, /* PDna */ GXinvert, /* Dn */ GXxor, /* DPx */ GXnand, /* DPan */ GXand, /* DPa */ GXequiv, /* DPxn */ GXnoop, /* D */ GXorInverted, /* DPno */ GXcopy, /* P */ GXorReverse, /* PDno */ GXor, /* DPo */ GXset /* 1 */};#define SET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }#define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }static voidmwm_hide_decorations(void){ PropMotifWmHints motif_hints; Atom hintsatom; /* setup the property */ motif_hints.flags = MWM_HINTS_DECORATIONS; motif_hints.decorations = 0; /* get the atom for the property */ hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False); if (!hintsatom) { warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n"); return; } XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace, (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);}#define SPLITCOLOUR15(colour, rv) \{ \ rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \ rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \ rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \}#define SPLITCOLOUR16(colour, rv) \{ \ rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \ rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \ rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \} \#define SPLITCOLOUR24(colour, rv) \{ \ rv.blue = (colour & 0xff0000) >> 16; \ rv.green = (colour & 0x00ff00) >> 8; \ rv.red = (colour & 0x0000ff); \}#define MAKECOLOUR(pc) \ ((pc.red >> g_red_shift_r) << g_red_shift_l) \ | ((pc.green >> g_green_shift_r) << g_green_shift_l) \ | ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \#define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }#define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }#define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \ x = (x << 16) | (x >> 16); }#define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }#define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }#define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }#define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }#define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }#define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }static uint32translate_colour(uint32 colour){ PixelColour pc; switch (g_server_bpp) { case 15: SPLITCOLOUR15(colour, pc); break; case 16: SPLITCOLOUR16(colour, pc); break; case 24: SPLITCOLOUR24(colour, pc); break; } return MAKECOLOUR(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 } \}/* 3 byte output repeat */#define REPEAT3(stm) \{ \ while (out <= end - 8 * 3) \ UNROLL8(stm) \ while (out < end) \ { stm } \}/* 4 byte output repeat */#define REPEAT4(stm) \{ \ while (out <= end - 8 * 4) \ UNROLL8(stm) \ while (out < end) \ { stm } \}/* *INDENT-ON* */static voidtranslate8to8(const uint8 * data, uint8 * out, uint8 * end){ while (out < end) *(out++) = (uint8) g_colmap[*(data++)];}static voidtranslate8to16(const uint8 * data, uint8 * out, uint8 * end){ uint16 value; if (g_arch_match) { /* *INDENT-OFF* */ REPEAT2 ( *((uint16 *) out) = g_colmap[*(data++)]; out += 2; ) /* *INDENT-ON* */ } else if (g_xserver_be) { while (out < end) { value = (uint16) g_colmap[*(data++)]; BOUT16(out, value); } } else { while (out < end) { value = (uint16) g_colmap[*(data++)]; LOUT16(out, value); } }}/* little endian - conversion happens when colourmap is built */static voidtranslate8to24(const uint8 * data, uint8 * out, uint8 * end){ uint32 value; if (g_xserver_be) { while (out < end) { value = g_colmap[*(data++)]; BOUT24(out, value); } } else { while (out < end) { value = g_colmap[*(data++)]; LOUT24(out, value); } }}static voidtranslate8to32(const uint8 * data, uint8 * out, uint8 * end){ uint32 value; if (g_arch_match) { /* *INDENT-OFF* */ REPEAT4 ( *((uint32 *) out) = g_colmap[*(data++)]; out += 4; ) /* *INDENT-ON* */ } else if (g_xserver_be) { while (out < end) { value = g_colmap[*(data++)]; BOUT32(out, value); } } else { while (out < end) { value = g_colmap[*(data++)]; LOUT32(out, value); } }}static voidtranslate15to16(const uint16 * data, uint8 * out, uint8 * end){ uint16 pixel; uint16 value; PixelColour pc; if (g_xserver_be) { while (out < end) { pixel = *(data++); if (g_host_be) { BSWAP16(pixel); } SPLITCOLOUR15(pixel, pc); value = MAKECOLOUR(pc); BOUT16(out, value); } } else { while (out < end) { pixel = *(data++); if (g_host_be) { BSWAP16(pixel); } SPLITCOLOUR15(pixel, pc); value = MAKECOLOUR(pc); LOUT16(out, value); } }}static voidtranslate15to24(const uint16 * data, uint8 * out, uint8 * end){ uint32 value; uint16 pixel; PixelColour pc; if (g_arch_match) { /* *INDENT-OFF* */ REPEAT3 ( pixel = *(data++); SPLITCOLOUR15(pixel, pc); *(out++) = pc.blue; *(out++) = pc.green; *(out++) = pc.red; ) /* *INDENT-ON* */ } else if (g_xserver_be) { while (out < end) { pixel = *(data++); if (g_host_be) { BSWAP16(pixel); } SPLITCOLOUR15(pixel, pc); value = MAKECOLOUR(pc); BOUT24(out, value); } } else { while (out < end) { pixel = *(data++); if (g_host_be) { BSWAP16(pixel); } SPLITCOLOUR15(pixel, pc); value = MAKECOLOUR(pc); LOUT24(out, value); } }}static voidtranslate15to32(const uint16 * data, uint8 * out, uint8 * end){ uint16 pixel; uint32 value; PixelColour pc; if (g_arch_match) { /* *INDENT-OFF* */ REPEAT4 ( pixel = *(data++); SPLITCOLOUR15(pixel, pc); *(out++) = pc.blue; *(out++) = pc.green; *(out++) = pc.red; *(out++) = 0; ) /* *INDENT-ON* */ } else if (g_xserver_be) { while (out < end) { pixel = *(data++); if (g_host_be) { BSWAP16(pixel); } SPLITCOLOUR15(pixel, pc); value = MAKECOLOUR(pc); BOUT32(out, value); } } else { while (out < end) { pixel = *(data++); if (g_host_be) { BSWAP16(pixel); } SPLITCOLOUR15(pixel, pc); value = MAKECOLOUR(pc); LOUT32(out, value); } }}static voidtranslate16to16(const uint16 * data, uint8 * out, uint8 * end){ uint16 pixel; uint16 value; PixelColour pc; if (g_xserver_be) { if (g_host_be) { while (out < end) { pixel = *(data++); BSWAP16(pixel); SPLITCOLOUR16(pixel, pc); value = MAKECOLOUR(pc); BOUT16(out, value); } } else { while (out < end) { pixel = *(data++); SPLITCOLOUR16(pixel, pc); value = MAKECOLOUR(pc); BOUT16(out, value); } } } else { if (g_host_be) { while (out < end) { pixel = *(data++); BSWAP16(pixel); SPLITCOLOUR16(pixel, pc); value = MAKECOLOUR(pc); LOUT16(out, value); } } else { while (out < end) { pixel = *(data++); SPLITCOLOUR16(pixel, pc); value = MAKECOLOUR(pc); LOUT16(out, value); } } }}static voidtranslate16to24(const uint16 * data, uint8 * out, uint8 * end){ uint32 value; uint16 pixel; PixelColour pc; if (g_arch_match) { /* *INDENT-OFF* */ REPEAT3 ( pixel = *(data++); SPLITCOLOUR16(pixel, pc); *(out++) = pc.blue; *(out++) = pc.green; *(out++) = pc.red; ) /* *INDENT-ON* */ } else if (g_xserver_be) { if (g_host_be) { while (out < end) { pixel = *(data++); BSWAP16(pixel); SPLITCOLOUR16(pixel, pc); value = MAKECOLOUR(pc); BOUT24(out, value); } } else { while (out < end) { pixel = *(data++); SPLITCOLOUR16(pixel, pc); value = MAKECOLOUR(pc); BOUT24(out, value); } } } else { if (g_host_be) { while (out < end) { pixel = *(data++); BSWAP16(pixel); SPLITCOLOUR16(pixel, pc); value = MAKECOLOUR(pc); LOUT24(out, value); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -