📄 xwin.c
字号:
green_weight = vis_green_weight; blue_weight = vis_blue_weight; g_visual = visual_info->visual; g_depth = visual_info->depth; } } } XFree(vmatches); } if (g_visual != NULL) { g_owncolmap = False; calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l); calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l); calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l); } else { template.class = PseudoColor; template.depth = 8; template.colormap_size = 256; vmatches = XGetVisualInfo(g_display, VisualClassMask | VisualDepthMask | VisualColormapSizeMask, &template, &visuals_count); if (vmatches == NULL) { error("No usable TrueColor or PseudoColor visuals on this display.\n"); XCloseDisplay(g_display); XFree(pfm); return False; } /* we use a colourmap, so the default visual should do */ g_owncolmap = True; g_visual = vmatches[0].visual; g_depth = vmatches[0].depth; } g_bpp = 0; for (i = 0; i < pixmap_formats_count; ++i) { XPixmapFormatValues *pf = &pfm[i]; if (pf->depth == g_depth) { g_bpp = pf->bits_per_pixel; if (g_no_translate_image) { switch (g_server_depth) { case 15: case 16: if (g_bpp != 16) g_no_translate_image = False; break; case 24: /* Yes, this will force image translation on most modern servers which use 32 bits for R8G8B8. */ if (g_bpp != 24) g_no_translate_image = False; break; default: g_no_translate_image = False; break; } } /* Pixmap formats list is a depth-to-bpp mapping -- there's just a single entry for every depth, so we can safely break here */ break; } } XFree(pfm); pfm = NULL; return True;}static XErrorHandler g_old_error_handler;static RD_BOOL g_error_expected = False;/* Check if the X11 window corresponding to a seamless window with specified id exists. */RD_BOOLsw_window_exists(unsigned long id){ seamless_window *sw; char *name; Status sts = 0; sw = sw_get_window_by_id(id); if (!sw) return False; g_error_expected = True; sts = XFetchName(g_display, sw->wnd, &name); g_error_expected = False; if (sts) { XFree(name); } return sts;}static interror_handler(Display * dpy, XErrorEvent * eev){ if (g_error_expected) return 0; return g_old_error_handler(dpy, eev);}RD_BOOLui_init(void){ int screen_num; g_display = XOpenDisplay(NULL); if (g_display == NULL) { error("Failed to open display: %s\n", XDisplayName(NULL)); return False; } { uint16 endianess_test = 1; g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test)); } g_old_error_handler = XSetErrorHandler(error_handler); g_xserver_be = (ImageByteOrder(g_display) == MSBFirst); screen_num = DefaultScreen(g_display); g_x_socket = ConnectionNumber(g_display); g_screen = ScreenOfDisplay(g_display, screen_num); g_depth = DefaultDepthOfScreen(g_screen); if (!select_visual(screen_num)) return False; if (g_no_translate_image) { DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n")); } if (g_server_depth > g_bpp) { warning("Remote desktop colour depth %d higher than display colour depth %d.\n", g_server_depth, g_bpp); } DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n", g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be)); if (!g_owncolmap) { g_xcolmap = XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual, AllocNone); if (g_depth <= 8) warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth); } if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always)) { warning("External BackingStore not available. Using internal.\n"); g_ownbackstore = True; } /* * Determine desktop size */ if (g_fullscreen) { g_width = WidthOfScreen(g_screen); g_height = HeightOfScreen(g_screen); g_using_full_workarea = True; } else if (g_width < 0) { /* Percent of screen */ if (-g_width >= 100) g_using_full_workarea = True; g_height = HeightOfScreen(g_screen) * (-g_width) / 100; g_width = WidthOfScreen(g_screen) * (-g_width) / 100; } else if (g_width == 0) { /* Fetch geometry from _NET_WORKAREA */ uint32 x, y, cx, cy; if (get_current_workarea(&x, &y, &cx, &cy) == 0) { g_width = cx; g_height = cy; g_using_full_workarea = True; } else { warning("Failed to get workarea: probably your window manager does not support extended hints\n"); g_width = WidthOfScreen(g_screen); g_height = HeightOfScreen(g_screen); } } /* make sure width is a multiple of 4 */ g_width = (g_width + 3) & ~3; g_mod_map = XGetModifierMapping(g_display); xwin_refresh_pointer_map(); xkeymap_init(); if (g_enable_compose) g_IM = XOpenIM(g_display, NULL, NULL, NULL); xclip_init(); ewmh_init(); if (g_seamless_rdp) { seamless_init(); } DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth)); return True;}voidui_deinit(void){ while (g_seamless_windows) { XDestroyWindow(g_display, g_seamless_windows->wnd); sw_remove_window(g_seamless_windows); } xclip_deinit(); if (g_IM != NULL) XCloseIM(g_IM); if (g_null_cursor != NULL) ui_destroy_cursor(g_null_cursor); XFreeModifiermap(g_mod_map); if (g_ownbackstore) XFreePixmap(g_display, g_backstore); XFreeGC(g_display, g_gc); XCloseDisplay(g_display); g_display = NULL;}static voidget_window_attribs(XSetWindowAttributes * attribs){ attribs->background_pixel = BlackPixelOfScreen(g_screen); attribs->background_pixel = WhitePixelOfScreen(g_screen); attribs->border_pixel = WhitePixelOfScreen(g_screen); attribs->backing_store = g_ownbackstore ? NotUseful : Always; attribs->override_redirect = g_fullscreen; attribs->colormap = g_xcolmap;}static voidget_input_mask(long *input_mask){ *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask; if (g_sendmotion) *input_mask |= PointerMotionMask; if (g_ownbackstore) *input_mask |= ExposureMask; if (g_fullscreen || g_grab_keyboard) *input_mask |= EnterWindowMask; if (g_grab_keyboard) *input_mask |= LeaveWindowMask;}RD_BOOLui_create_window(void){ uint8 null_pointer_mask[1] = { 0x80 }; uint8 null_pointer_data[24] = { 0x00 }; XSetWindowAttributes attribs; XClassHint *classhints; XSizeHints *sizehints; int wndwidth, wndheight; long input_mask, ic_input_mask; XEvent xevent; 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; get_window_attribs(&attribs); g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth, wndheight, 0, g_depth, InputOutput, g_visual, CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | CWBorderPixel, &attribs); if (g_gc == NULL) { g_gc = XCreateGC(g_display, g_wnd, 0, NULL); ui_reset_clip(); } if (g_create_bitmap_gc == NULL) g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL); if ((g_ownbackstore) && (g_backstore == 0)) { g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth); /* clear to prevent rubbish being exposed at startup */ XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen)); XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height); } XStoreName(g_display, g_wnd, g_title); ewmh_set_wm_name(g_wnd, g_title); if (g_hide_decorations) mwm_hide_decorations(g_wnd); classhints = XAllocClassHint(); if (classhints != NULL) { classhints->res_name = classhints->res_class = "rdesktop"; XSetClassHint(g_display, g_wnd, classhints); XFree(classhints); } sizehints = XAllocSizeHints(); 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); XFree(sizehints); } if (g_embed_wnd) { XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0); } get_input_mask(&input_mask); if (g_IM != NULL) { g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing), XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL); if ((g_IC != NULL) && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL)) input_mask |= ic_input_mask; } XSelectInput(g_display, g_wnd, input_mask); XMapWindow(g_display, g_wnd); /* wait for VisibilityNotify */ do { XMaskEvent(g_display, VisibilityChangeMask, &xevent); } while (xevent.type != VisibilityNotify); g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured; g_focused = False; g_mouse_in_wnd = False; /* handle the WM_DELETE_WINDOW protocol */ g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True); g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True); XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1); /* create invisible 1x1 cursor to be used as null cursor */ if (g_null_cursor == NULL) g_null_cursor = ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data); if (g_seamless_rdp) { seamless_restack_test(); } return True;}voidui_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; }}voidui_destroy_window(void){ if (g_IC != NULL) XDestroyIC(g_IC); XDestroyWindow(g_display, g_wnd);}voidxwin_toggle_fullscreen(void){ Pixmap contents = 0; if (g_seamless_active) /* Turn off SeamlessRDP mode */ ui_seamless_toggle(); if (!g_ownbackstore) { /* need to save contents of window */ contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth); XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0); } ui_destroy_window(); g_fullscreen = !g_fullscreen; ui_create_window(); XDefineCursor(g_display, g_wnd, g_current_cursor); if (!g_ownbackstore) { XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0); XFreePixmap(g_display, contents); }}static voidhandle_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; if (down) flags = MOUSE_FLAG_DOWN; /* Stop moving window when button is released, regardless of cursor position */ if (g_moving_wnd && (xevent.type == ButtonRelease)) g_moving_wnd = False; /* If win_button_size is nonzero, enable single app mode */ if (xevent.xbutton.y < g_win_button_size) { /* Check from right to left: */ if (xevent.xbutton.x >= g_width - g_win_button_size) { /* The close button, continue */ ; } else if (xevent.xbutton.x >= g_width - g_win_button_size * 2) { /* The maximize/restore button. Do not send to server. It might be a good idea to change the cursor or give some other visible indication that rdesktop inhibited this click */ if (xevent.type == ButtonPress) return; } else if (xevent.xbutton.x >= g_width - g_win_button_size * 3) { /* The minimize button. Iconify window. */ if (xevent.type == ButtonRelease) { /* Release the mouse button outside the minimize button, to prevent the actual minimazation to happen */ rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1); XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display)); return; } } else if (xevent.xbutton.x <= g_win_button_size) { /* The system menu. Ignore. */ if (xevent.type == ButtonPress) return; } else { /* The title bar. */ if (xevent.type == ButtonPress) { if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea) { g_moving_wnd = True; g_move_x_offset = xevent.xbutton.x; g_move_y_offset = xevent.xbutton.y; } return; } } } if (xevent.xmotion.window == g_wnd) { rdp_send_input(time(NULL), RDP_INPUT_MOUSE, flags | button, xevent.xbutton.x, xevent.xbutton.y); } else { /* SeamlessRDP */ rdp_send_input(time(NULL), RDP_INPUT_MOUSE, flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root); }}/* Process events in Xlib queue Returns 0 after user quit, 1 otherwise */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -