📄 xwin.c
字号:
{ XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0); } input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask; 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; 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_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); }}/* Process all events in Xlib queue Returns 0 after user quit, 1 otherwise */static intxwin_process_events(void){ XEvent xevent; KeySym keysym; uint16 button, flags; uint32 ev_time; key_translation tr; char str[256]; Status status; while (XPending(g_display) > 0) { XNextEvent(g_display, &xevent); if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True)) { DEBUG_KBD(("Filtering event\n")); continue; } flags = 0; switch (xevent.type) { case VisibilityNotify: 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; tr = xkeymap_translate_key(keysym, xevent.xkey.keycode, xevent.xkey.state); if (tr.scancode == 0) break; save_remote_modifiers(tr.scancode); ensure_remote_modifiers(ev_time, tr); rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode); restore_remote_modifiers(ev_time, tr.scancode); 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; tr = xkeymap_translate_key(keysym, xevent.xkey.keycode, xevent.xkey.state); if (tr.scancode == 0) break; rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode); break; case ButtonPress: flags = MOUSE_FLAG_DOWN; /* fall through */ case ButtonRelease: g_last_gesturetime = xevent.xbutton.time; button = xkeymap_translate_button(xevent.xbutton.button); if (button == 0) break; /* If win_button_size is nonzero, enable single app mode */ if (xevent.xbutton.y < g_win_button_size) { /* Stop moving window when button is released, regardless of cursor position */ if (g_moving_wnd && (xevent.type == ButtonRelease)) g_moving_wnd = False; /* 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 */ break; } else if (xevent.xbutton.x >= g_width - g_win_button_size * 3) { /* The minimize button. Iconify window. */ XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display)); break; } else if (xevent.xbutton.x <= g_win_button_size) { /* The system menu. Ignore. */ break; } else { /* The title bar. */ if ((xevent.type == ButtonPress) && !g_fullscreen && g_hide_decorations) { g_moving_wnd = True; g_move_x_offset = xevent.xbutton.x; g_move_y_offset = xevent.xbutton.y; } break; } } rdp_send_input(time(NULL), RDP_INPUT_MOUSE, flags | button, xevent.xbutton.x, xevent.xbutton.y); 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); rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y); 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); 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: XCopyArea(g_display, g_backstore, g_wnd, g_gc, xevent.xexpose.x, xevent.xexpose.y, 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); 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; 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); 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; } rdpdr_check_fds(&rfds, &wfds, (BOOL) False); if (FD_ISSET(rdp_socket, &rfds)) return 1;#ifdef WITH_RDPSND if (g_dsp_busy && FD_ISSET(g_dsp_fd, &wfds)) wave_out_play();#endif }}voidui_move_pointer(int x, int y){ XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);}HBITMAPui_create_bitmap(int width, int height, uint8 * data){ XImage *image; Pixmap bitmap; uint8 *tdata; int bitmap_pad; if (g_server_bpp == 8) { bitmap_pad = 8; } else { bitmap_pad = g_bpp; if (g_bpp == 24) bitmap_pad = 32; } tdata = (g_owncolmap ? data : translate_image(width, height, data)); bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth); image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0, (char *) tdata, width, height, bitmap_pad, 0); XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height); XFree(image); if (tdata != data) xfree(tdata); return (HBITMAP) bitmap;}voidui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data){ XImage *image; uint8 *tdata; int bitmap_pad; if (g_server_bpp == 8) { bitmap_pad = 8; } else { bitmap_pad = g_bpp; if (g_bpp == 24) bitmap_pad = 32; } tdata = (g_owncolmap ? data : translate_image(width, height, data)); image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0, (char *) tdata, width, height, bitmap_pad, 0); if (g_ownbackstore) { XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy); XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); } else { XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy); } XFree(image); if (tdata != data) xfree(tdata);}voidui_destroy_bitmap(HBITMAP bmp){ XFreePixmap(g_display, (Pixmap) bmp);}HGLYPHui_create_glyph(int width, int height, uint8 * data){ XImage *image; Pixmap bitmap; int scanline; scanline = (width + 7) / 8; bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1); if (g_create_glyph_gc == 0) g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL); image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data, width, height, 8, scanline); image->byte_order = MSBFirst; image->bitmap_bit_order = MSBFirst; XInitImage(image); XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height); XFree(image); return (HGLYPH) bitmap;}voidui_destroy_glyph(HGLYPH glyph){ XFreePixmap(g_display, (Pixmap) glyph);}HCURSORui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask, uint8 * xormask){ HGLYPH maskglyph, cursorglyph; XColor bg, fg; Cursor xcursor; uint8 *cursor, *pcursor; uint8 *mask, *pmask; uint8 nextbit; int scanline, offset; int i, j; scanline = (width + 7) / 8; offset = scanline * height; cursor = (uint8 *) xmalloc(offset); memset(cursor, 0, offset); mask = (uint8 *) xmalloc(offset); memset(mask, 0, offset); /* approximate AND and XOR masks with a monochrome X pointer */ for (i = 0; i < height; i++) { offset -= scanline; pcursor = &cursor[offset]; pmask = &mask[offset]; for (j = 0; j < scanline; j++) { for (nextbit = 0x80; nextbit != 0; nextbit >>= 1) { if (xormask[0] || xormask[1] || xormask[2]) { *pcursor |= (~(*andmask) & nextbit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -