📄 xwin.c
字号:
{
pixel = *(data++) << 16;
pixel |= *(data++) << 8;
pixel |= *(data++);
SPLITCOLOUR24(pixel, pc);
value = MAKECOLOUR(pc);
LOUT32(out, value);
}
}
}
static uint8 *
translate_image(RDPCLIENT * This, int width, int height, uint8 * data)
{
int size;
uint8 *out;
uint8 *end;
/*
If RDP depth and X Visual depths match,
and arch(endian) matches, no need to translate:
just return data.
Note: select_visual should've already ensured g_no_translate
is only set for compatible depths, but the RDP depth might've
changed during connection negotiations.
*/
if (This->xwin.no_translate_image)
{
if ((This->xwin.depth == 15 && This->server_depth == 15) ||
(This->xwin.depth == 16 && This->server_depth == 16) ||
(This->xwin.depth == 24 && This->server_depth == 24))
return data;
}
size = width * height * (This->xwin.bpp / 8);
out = (uint8 *) xmalloc(size);
end = out + size;
switch (This->server_depth)
{
case 24:
switch (This->xwin.bpp)
{
case 32:
translate24to32(This, data, out, end);
break;
case 24:
translate24to24(This, data, out, end);
break;
case 16:
translate24to16(This, data, out, end);
break;
}
break;
case 16:
switch (This->xwin.bpp)
{
case 32:
translate16to32(This, (uint16 *) data, out, end);
break;
case 24:
translate16to24(This, (uint16 *) data, out, end);
break;
case 16:
translate16to16(This, (uint16 *) data, out, end);
break;
}
break;
case 15:
switch (This->xwin.bpp)
{
case 32:
translate15to32(This, (uint16 *) data, out, end);
break;
case 24:
translate15to24(This, (uint16 *) data, out, end);
break;
case 16:
translate15to16(This, (uint16 *) data, out, end);
break;
}
break;
case 8:
switch (This->xwin.bpp)
{
case 8:
translate8to8(This, data, out, end);
break;
case 16:
translate8to16(This, data, out, end);
break;
case 24:
translate8to24(This, data, out, end);
break;
case 32:
translate8to32(This, data, out, end);
break;
}
break;
}
return out;
}
BOOL
get_key_state(RDPCLIENT * This, unsigned int state, uint32 keysym)
{
int modifierpos, key, keysymMask = 0;
int offset;
KeyCode keycode = XKeysymToKeycode(This->display, keysym);
if (keycode == NoSymbol)
return False;
for (modifierpos = 0; modifierpos < 8; modifierpos++)
{
offset = This->xwin.mod_map->max_keypermod * modifierpos;
for (key = 0; key < This->xwin.mod_map->max_keypermod; key++)
{
if (This->xwin.mod_map->modifiermap[offset + key] == keycode)
keysymMask |= 1 << modifierpos;
}
}
return (state & keysymMask) ? True : False;
}
static void
calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
{
*shift_l = ffs(mask) - 1;
mask >>= *shift_l;
*shift_r = 8 - ffs(mask & ~(mask >> 1));
}
/* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
calculates the bits-per-pixel of this channel (a.k.a. colour weight).
*/
static unsigned
calculate_mask_weight(uint32 mask)
{
unsigned weight = 0;
do
{
weight += (mask & 1);
}
while (mask >>= 1);
return weight;
}
static BOOL
select_visual(RDPCLIENT * This)
{
XPixmapFormatValues *pfm;
int pixmap_formats_count, visuals_count;
XVisualInfo *vmatches = NULL;
XVisualInfo template;
int i;
unsigned red_weight, blue_weight, green_weight;
red_weight = blue_weight = green_weight = 0;
if (This->server_depth == -1)
{
This->server_depth = DisplayPlanes(This->display, DefaultScreen(This->display));
}
pfm = XListPixmapFormats(This->display, &pixmap_formats_count);
if (pfm == NULL)
{
error("Unable to get list of pixmap formats from display.\n");
XCloseDisplay(This->display);
return False;
}
/* Search for best TrueColor visual */
template.class = TrueColor;
vmatches = XGetVisualInfo(This->display, VisualClassMask, &template, &visuals_count);
This->xwin.visual = NULL;
This->xwin.no_translate_image = False;
This->xwin.compatible_arch = False;
if (vmatches != NULL)
{
for (i = 0; i < visuals_count; ++i)
{
XVisualInfo *visual_info = &vmatches[i];
BOOL can_translate_to_bpp = False;
int j;
/* Try to find a no-translation visual that'll
allow us to use RDP bitmaps directly as ZPixmaps. */
if (!This->xwin.xserver_be && (((visual_info->depth == 15) &&
/* R5G5B5 */
(visual_info->red_mask == 0x7c00) &&
(visual_info->green_mask == 0x3e0) &&
(visual_info->blue_mask == 0x1f)) ||
((visual_info->depth == 16) &&
/* R5G6B5 */
(visual_info->red_mask == 0xf800) &&
(visual_info->green_mask == 0x7e0) &&
(visual_info->blue_mask == 0x1f)) ||
((visual_info->depth == 24) &&
/* R8G8B8 */
(visual_info->red_mask == 0xff0000) &&
(visual_info->green_mask == 0xff00) &&
(visual_info->blue_mask == 0xff))))
{
This->xwin.visual = visual_info->visual;
This->xwin.depth = visual_info->depth;
This->xwin.compatible_arch = !This->xwin.host_be;
This->xwin.no_translate_image = (visual_info->depth == This->server_depth);
if (This->xwin.no_translate_image)
/* We found the best visual */
break;
}
else
{
This->xwin.compatible_arch = False;
}
if (visual_info->depth > 24)
{
/* Avoid 32-bit visuals and likes like the plague.
They're either untested or proven to work bad
(e.g. nvidia's Composite 32-bit visual).
Most implementation offer a 24-bit visual anyway. */
continue;
}
/* Only care for visuals, for whose BPPs (not depths!)
we have a translateXtoY function. */
for (j = 0; j < pixmap_formats_count; ++j)
{
if (pfm[j].depth == visual_info->depth)
{
if ((pfm[j].bits_per_pixel == 16) ||
(pfm[j].bits_per_pixel == 24) ||
(pfm[j].bits_per_pixel == 32))
{
can_translate_to_bpp = True;
}
break;
}
}
/* Prefer formats which have the most colour depth.
We're being truly aristocratic here, minding each
weight on its own. */
if (can_translate_to_bpp)
{
unsigned vis_red_weight =
calculate_mask_weight(visual_info->red_mask);
unsigned vis_green_weight =
calculate_mask_weight(visual_info->green_mask);
unsigned vis_blue_weight =
calculate_mask_weight(visual_info->blue_mask);
if ((vis_red_weight >= red_weight)
&& (vis_green_weight >= green_weight)
&& (vis_blue_weight >= blue_weight))
{
red_weight = vis_red_weight;
green_weight = vis_green_weight;
blue_weight = vis_blue_weight;
This->xwin.visual = visual_info->visual;
This->xwin.depth = visual_info->depth;
}
}
}
XFree(vmatches);
}
if (This->xwin.visual != NULL)
{
This->owncolmap = False;
calculate_shifts(This->xwin.visual->red_mask, &This->xwin.red_shift_r, &This->xwin.red_shift_l);
calculate_shifts(This->xwin.visual->green_mask, &This->xwin.green_shift_r, &This->xwin.green_shift_l);
calculate_shifts(This->xwin.visual->blue_mask, &This->xwin.blue_shift_r, &This->xwin.blue_shift_l);
}
else
{
template.class = PseudoColor;
template.depth = 8;
template.colormap_size = 256;
vmatches =
XGetVisualInfo(This->display,
VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
&template, &visuals_count);
if (vmatches == NULL)
{
error("No usable TrueColor or PseudoColor visuals on this display.\n");
XCloseDisplay(This->display);
XFree(pfm);
return False;
}
/* we use a colourmap, so the default visual should do */
This->owncolmap = True;
This->xwin.visual = vmatches[0].visual;
This->xwin.depth = vmatches[0].depth;
}
This->xwin.bpp = 0;
for (i = 0; i < pixmap_formats_count; ++i)
{
XPixmapFormatValues *pf = &pfm[i];
if (pf->depth == This->xwin.depth)
{
This->xwin.bpp = pf->bits_per_pixel;
if (This->xwin.no_translate_image)
{
switch (This->server_depth)
{
case 15:
case 16:
if (This->xwin.bpp != 16)
This->xwin.no_translate_image = False;
break;
case 24:
/* Yes, this will force image translation
on most modern servers which use 32 bits
for R8G8B8. */
if (This->xwin.bpp != 24)
This->xwin.no_translate_image = False;
break;
default:
This->xwin.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 int
error_handler(RDPCLIENT * This, Display * dpy, XErrorEvent * eev)
{
if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))
{
fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");
fprintf(stderr,
"This is most likely caused by a broken window manager (commonly KWin).\n");
return 0;
}
return This->xwin.old_error_handler(dpy, eev);
}
*/
BOOL
ui_init(RDPCLIENT * This)
{
int screen_num;
This->display = XOpenDisplay(NULL);
if (This->display == NULL)
{
error("Failed to open display: %s\n", XDisplayName(NULL));
return False;
}
{
uint16 endianess_test = 1;
This->xwin.host_be = !(BOOL) (*(uint8 *) (&endianess_test));
}
/*This->xwin.old_error_handler = XSetErrorHandler(error_handler);*/
This->xwin.xserver_be = (ImageByteOrder(This->display) == MSBFirst);
screen_num = DefaultScreen(This->display);
This->xwin.x_socket = ConnectionNumber(This->display);
This->xwin.screen = ScreenOfDisplay(This->display, screen_num);
This->xwin.depth = DefaultDepthOfScreen(This->xwin.screen);
if (!select_visual(This))
return False;
if (This->xwin.no_translate_image)
{
DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
}
if (This->server_depth > This->xwin.bpp)
{
warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
This->server_depth, This->xwin.bpp);
}
DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
This->server_depth, This->xwin.depth, This->xwin.bpp, This->xwin.xserver_be, This->xwin.host_be));
if (!This->owncolmap)
{
This->xwin.xcolmap =
XCreateColormap(This->display, RootWindowOfScreen(This->xwin.screen), This->xwin.visual,
AllocNone);
if (This->xwin.depth <= 8)
warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", This->xwin.depth);
}
if ((!This->ownbackstore) && (DoesBackingStore(This->xwin.screen) != Always))
{
warning("External BackingStore not available. Using internal.\n");
This->ownbackstore = True;
}
/*
* Determine desktop size
*/
if (This->fullscreen)
{
This->width = WidthOfScreen(This->xwin.screen);
This->height = HeightOfScreen(This->xwin.screen);
This->xwin.using_full_workarea = True;
}
else if (This->width < 0)
{
/* Percent of screen */
if (-This->width >= 100)
This->xwin.using_full_workarea = True;
This->height = HeightOfScreen(This->xwin.screen) * (-This->width) / 100;
This->width = WidthOfScreen(This->xwin.screen) * (-This->width) / 100;
}
else if (This->width == 0)
{
/* Fetch geometry from _NET_WORKAREA */
uint32 x, y, cx, cy;
if (get_current_workarea(This, &x, &y, &cx, &cy) == 0)
{
This->width = cx;
This->height = cy;
This->xwin.using_full_workarea = True;
}
else
{
warning("Failed to get workarea: probably your window manager does not support extended hints\n");
This->width = WidthOfScreen(This->xwin.screen);
This->height = HeightOfScreen(This->xwin.screen);
}
}
/* make sure width is a multiple of 4 */
This->width = (This->width + 3) & ~3;
This->xwin.mod_map = XGetModifierMapping(This->display);
xkeymap_init(This);
if (This->enable_compose)
This->xwin.IM = XOpenIM(This->display, NULL, NULL, NULL);
xclip_init(This);
ewmh_init(This);
if (This->seamless_rdp)
seamless_init(This);
DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", This->server_depth, This->xwin.bpp, This->xwin.depth));
return True;
}
void
ui_deinit(RDPCLIENT * This)
{
while (This->xwin.seamless_windows)
{
XDestroyWindow(This->display, This->xwin.seamless_windows->wnd);
sw_remove_window(This, This->xwin.seamless_windows);
}
xclip_deinit(This);
if (This->xwin.IM != NULL)
XCloseIM(This->xwin.IM);
if (This->xwin.null_cursor != NULL)
ui_destroy_cursor(This, This->xwin.null_cursor);
XFreeModifiermap(This->xwin.mod_map);
if (This->ownbackstore)
XFreePixmap(This->display, This->xwin.backstore);
XFreeGC(This->display, This->xwin.gc);
XCloseDisplay(This->display);
This->display = NULL;
}
static void
get_window_attribs(RDPCLIENT * This, XSetWindowAttributes * attribs)
{
attribs->background_pixel = BlackPixelOfScreen(This->xwin.screen);
attribs->background_pixel = WhitePixelOfScreen(This->xwin.screen);
attribs->border_pixel = WhitePixelOfScreen(This->xwin.screen);
attribs->backing_store = This->ownbackstore ? NotUseful : Always;
attribs->override_redirect = This->fullscreen;
attribs->colormap = This->xwin.xcolmap;
}
static void
get_input_mask(RDPCLIENT * This, long *input_mask)
{
*input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
if (This->sendmotion)
*input_mask |= PointerMotionMask;
if (This->ownbackstore)
*input_mask |= ExposureMask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -