⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xwin.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
		{
			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 + -