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

📄 xwin.c

📁 rdesktop is a client for Microsoft Windows NT Terminal Server, Windows 2000 Terminal Services, Wind
💻 C
📖 第 1 页 / 共 5 页
字号:
	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);	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);	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, BOOL down){	uint16 button, flags = 0;	g_last_gesturetime = xevent.xbutton.time;	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 */static intxwin_process_events(void){	XEvent xevent;	KeySym keysym;	uint32 ev_time;	char str[256];	Status status;	int events = 0;	seamless_window *sw;	while ((XPending(g_display) > 0) && events++ < 20)	{		XNextEvent(g_display, &xevent);		if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))		{			DEBUG_KBD(("Filtering event\n"));			continue;		}		switch (xevent.type)		{			case VisibilityNotify:				if (xevent.xvisibility.window == g_wnd)					g_Unobscured =						xevent.xvisibility.state == VisibilityUnobscured;				break;			case ClientMessage:				/* the window manager told us to quit */				if ((xevent.xclient.message_type == g_protocol_atom)				    && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))					/* Quit */					return 0;				break;			case KeyPress:				g_last_gesturetime = xevent.xkey.time;				if (g_IC != NULL)					/* Multi_key compatible version */				{					XmbLookupString(g_IC,							&xevent.xkey, str, sizeof(str), &keysym,							&status);					if (!((status == XLookupKeySym) || (status == XLookupBoth)))					{						error("XmbLookupString failed with status 0x%x\n",						      status);						break;					}				}				else				{					/* Plain old XLookupString */					DEBUG_KBD(("\nNo input context, using XLookupString\n"));					XLookupString((XKeyEvent *) & xevent,						      str, sizeof(str), &keysym, NULL);				}				DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,					   get_ksname(keysym)));				ev_time = time(NULL);				if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))					break;				xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,						  ev_time, True, 0);				break;			case KeyRelease:				g_last_gesturetime = xevent.xkey.time;				XLookupString((XKeyEvent *) & xevent, str,					      sizeof(str), &keysym, NULL);				DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,					   get_ksname(keysym)));				ev_time = time(NULL);				if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))					break;				xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,						  ev_time, False, 0);				break;			case ButtonPress:				handle_button_event(xevent, True);				break;			case ButtonRelease:				handle_button_event(xevent, False);				break;			case MotionNotify:				if (g_moving_wnd)				{					XMoveWindow(g_display, g_wnd,						    xevent.xmotion.x_root - g_move_x_offset,						    xevent.xmotion.y_root - g_move_y_offset);					break;				}				if (g_fullscreen && !g_focused)					XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,						       CurrentTime);				if (xevent.xmotion.window == g_wnd)				{					rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,						       xevent.xmotion.x, xevent.xmotion.y);				}				else				{					/* SeamlessRDP */					rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,						       xevent.xmotion.x_root,						       xevent.xmotion.y_root);				}				break;			case FocusIn:				if (xevent.xfocus.mode == NotifyGrab)					break;				g_focused = True;				reset_modifier_keys();				if (g_grab_keyboard && g_mouse_in_wnd)					XGrabKeyboard(g_display, g_wnd, True,						      GrabModeAsync, GrabModeAsync, CurrentTime);				sw = sw_get_window_by_wnd(xevent.xfocus.window);				if (!sw)					break;				if (sw->id != g_seamless_focused)				{					seamless_send_focus(sw->id, 0);					g_seamless_focused = sw->id;				}				break;			case FocusOut:				if (xevent.xfocus.mode == NotifyUngrab)					break;				g_focused = False;				if (xevent.xfocus.mode == NotifyWhileGrabbed)					XUngrabKeyboard(g_display, CurrentTime);				break;			case EnterNotify:				/* we only register for this event when in fullscreen mode */				/* or grab_keyboard */				g_mouse_in_wnd = True;				if (g_fullscreen)				{					XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,						       CurrentTime);					break;				}				if (g_focused)					XGrabKeyboard(g_display, g_wnd, True,						      GrabModeAsync, GrabModeAsync, CurrentTime);				break;			case LeaveNotify:				/* we only register for this event when grab_keyboard */				g_mouse_in_wnd = False;				XUngrabKeyboard(g_display, CurrentTime);				break;			case Expose:				if (xevent.xexpose.window == g_wnd)				{					XCopyArea(g_display, g_backstore, xevent.xexpose.window,						  g_gc,						  xevent.xexpose.x, xevent.xexpose.y,						  xevent.xexpose.width, xevent.xexpose.height,						  xevent.xexpose.x, xevent.xexpose.y);				}				else				{					sw = sw_get_window_by_wnd(xevent.xexpose.window);					if (!sw)						break;					XCopyArea(g_display, g_backstore,						  xevent.xexpose.window, g_gc,						  xevent.xexpose.x + sw->xoffset,						  xevent.xexpose.y + sw->yoffset,						  xevent.xexpose.width,						  xevent.xexpose.height, xevent.xexpose.x,						  xevent.xexpose.y);				}				break;			case MappingNotify:				/* Refresh keyboard mapping if it has changed. This is important for				   Xvnc, since it allocates keycodes dynamically */				if (xevent.xmapping.request == MappingKeyboard				    || xevent.xmapping.request == MappingModifier)					XRefreshKeyboardMapping(&xevent.xmapping);				if (xevent.xmapping.request == MappingModifier)				{					XFreeModifiermap(g_mod_map);					g_mod_map = XGetModifierMapping(g_display);				}				break;				/* clipboard stuff */			case SelectionNotify:				xclip_handle_SelectionNotify(&xevent.xselection);				break;			case SelectionRequest:				xclip_handle_SelectionRequest(&xevent.xselectionrequest);				break;			case SelectionClear:				xclip_handle_SelectionClear();				break;			case PropertyNotify:				xclip_handle_PropertyNotify(&xevent.xproperty);				if (xevent.xproperty.window == g_wnd)					break;				if (xevent.xproperty.window == DefaultRootWindow(g_display))					break;				/* seamless */				sw = sw_get_window_by_wnd(xevent.xproperty.window);				if (!sw)					break;				if ((xevent.xproperty.atom == g_net_wm_state_atom)				    && (xevent.xproperty.state == PropertyNewValue))				{					sw->state = ewmh_get_window_state(sw->wnd);					seamless_send_state(sw->id, sw->state, 0);				}				if ((xevent.xproperty.atom == g_net_wm_desktop_atom)				    && (xevent.xproperty.state == PropertyNewValue))				{					sw->desktop = ewmh_get_window_desktop(sw->wnd);					sw_all_to_desktop(sw->wnd, sw->desktop);				}				break;			case MapNotify:				if (!g_seamless_active)					rdp_send_client_window_status(1);				break;			case UnmapNotify:				if (!g_seamless_active)					rdp_send_client_window_status(0);				break;			case ConfigureNotify:				if (!g_seamless_active)					break;				sw = sw_get_window_by_wnd(xevent.xconfigure.window);				if (!sw)					break;				gettimeofday(sw->position_timer, NULL);				if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=				    1000000)				{					sw->position_timer->tv_usec +=						SEAMLESSRDP_POSITION_TIMER - 1000000;					sw->position_timer->tv_sec += 1;				}				else				{					sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;				}				sw_handle_restack(sw);				break;		}	}	/* Keep going */	return 1;}/* Returns 0 after user quit, 1 otherwise */intui_select(int rdp_socket){	int n;	fd_set rfds, wfds;	struct timeval tv;	BOOL s_timeout = False;	while (True)	{		n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;		/* Process any events already waiting */		if (!xwin_process_events())			/* User quit */			return 0;		if (g_seamless_active)			sw_check_timers();		FD_ZERO(&rfds);		FD_ZERO(&wfds);		FD_SET(rdp_socket, &rfds);		FD_SET(g_x_socket, &rfds);#ifdef WITH_RDPSND		/* FIXME: there should be an API for registering fds */		if (g_dsp_busy)		{			FD_SET(g_dsp_fd, &wfds);			n = (g_dsp_fd > n) ? g_dsp_fd : n;		}#endif		/* default timeout */		tv.tv_sec = 60;		tv.tv_usec = 0;		/* add redirection handles */		rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);		seamless_select_timeout(&tv);		n++;		switch (select(n, &rfds, &wfds, NULL, &tv))		{			case -1:				error("select: %s\n", strerror(errno));			case 0:				/* Abort serial read calls */				if (s_timeout)					rdpdr_check_fds(&rfds, &wfds, (BOOL) True);				continue;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -