📄 sdl_x11events.c
字号:
if ( SDL_IC != NULL ) { XUnsetICFocus(SDL_IC); }#endif /* Queue leaving fullscreen mode */ switch_waiting = 0x01; switch_time = SDL_GetTicks() + 200; } break;#ifdef X_HAVE_UTF8_STRING /* Some IM requires MappingNotify to be passed to XRefreshKeyboardMapping by the app. */ case MappingNotify: { XRefreshKeyboardMapping(&xevent.xmapping); } break;#endif /* X_HAVE_UTF8_STRING */ /* Generated upon EnterWindow and FocusIn */ case KeymapNotify: {#ifdef DEBUG_XEVENTSprintf("KeymapNotify!\n");#endif X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); } break; /* Mouse motion? */ case MotionNotify: { if ( SDL_VideoSurface ) { if ( mouse_relative ) { if ( using_dga & DGA_MOUSE ) {#ifdef DEBUG_MOTION printf("DGA motion: %d,%d\n", xevent.xmotion.x_root, xevent.xmotion.y_root);#endif posted = SDL_PrivateMouseMotion(0, 1, xevent.xmotion.x_root, xevent.xmotion.y_root); } else { posted = X11_WarpedMotion(this,&xevent); } } else {#ifdef DEBUG_MOTION printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);#endif posted = SDL_PrivateMouseMotion(0, 0, xevent.xmotion.x, xevent.xmotion.y); } } } break; /* Mouse button press? */ case ButtonPress: { posted = SDL_PrivateMouseButton(SDL_PRESSED, xevent.xbutton.button, 0, 0); } break; /* Mouse button release? */ case ButtonRelease: { posted = SDL_PrivateMouseButton(SDL_RELEASED, xevent.xbutton.button, 0, 0); } break; /* Key press? */ case KeyPress: { SDL_keysym keysym; KeyCode keycode = xevent.xkey.keycode;#ifdef DEBUG_XEVENTSprintf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);#endif /* If we're not doing translation, we're done! */ if ( !SDL_TranslateUNICODE ) { /* Get the translated SDL virtual keysym and put it on the queue.*/ keysym.scancode = keycode; keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); keysym.mod = KMOD_NONE; keysym.unicode = 0; posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); break; } /* Look up the translated value for the key event */#ifdef X_HAVE_UTF8_STRING if ( SDL_IC != NULL ) { Status status; KeySym xkeysym; int i; /* A UTF-8 character can be at most 6 bytes */ /* ... It's true, but Xutf8LookupString can return more than one characters. Moreover, the spec. put no upper bound, so we should be ready for longer strings. */ char keybuf[32]; char *keydata = keybuf; int count; Uint16 utf16buf[32]; Uint16 *utf16data = utf16buf; int utf16size; int utf16length; count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, sizeof(keybuf), &xkeysym, &status); if (XBufferOverflow == status) { /* The IM has just generated somewhat long string. We need a longer buffer in this case. */ keydata = SDL_malloc(count); if ( keydata == NULL ) { SDL_OutOfMemory(); break; } count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, count, &xkeysym, &status); } switch (status) { case XBufferOverflow: { /* Oops! We have allocated the bytes as requested by Xutf8LookupString, so the length of the buffer must be sufficient. This case should never happen! */ SDL_SetError("Xutf8LookupString indicated a double buffer overflow!"); break; } case XLookupChars: case XLookupBoth: { if (0 == count) { break; } /* We got a converted string from IM. Make sure to deliver all characters to the application as SDL events. Note that an SDL event can only carry one UTF-16 encoding unit, and a surrogate pair is delivered as two SDL events. I guess this behaviour is probably _imported_ from Windows or MacOS. To do so, we need to convert the UTF-8 data into UTF-16 data (not UCS4/UTF-32!). We need an estimate of the number of UTF-16 encoding units here. The worst case is pure ASCII string. Assume so. */ /* In 1.3 SDL may have a text event instead, that carries the whole UTF-8 string with it. */ utf16size = count * sizeof(Uint16); if (utf16size > sizeof(utf16buf)) { utf16data = (Uint16 *) SDL_malloc(utf16size); if (utf16data == NULL) { SDL_OutOfMemory(); break; } } utf16length = Utf8ToUtf16((Uint8 *)keydata, count, utf16data, utf16size); if (utf16length < 0) { /* The keydata contained an invalid byte sequence. It should be a bug of the IM or Xlib... */ SDL_SetError("Oops! Xutf8LookupString returned an invalid UTF-8 sequence!"); break; } /* Deliver all UTF-16 encoding units. At this moment, SDL event queue has a fixed size (128 events), and an SDL event can hold just one UTF-16 encoding unit. So, if we receive more than 128 UTF-16 encoding units from a commit, exceeded characters will be lost. */ for (i = 0; i < utf16length - 1; i++) { keysym.scancode = 0; keysym.sym = SDLK_UNKNOWN; keysym.mod = KMOD_NONE; keysym.unicode = utf16data[i]; posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); } /* The keysym for the last character carries the scancode and symbol that corresponds to the X11 keycode. */ if (utf16length > 0) { keysym.scancode = keycode; keysym.sym = (keycode ? X11_TranslateKeycode(SDL_Display, keycode) : 0); keysym.mod = KMOD_NONE; keysym.unicode = utf16data[utf16length - 1]; posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); } break; } case XLookupKeySym: { /* I'm not sure whether it is possible that a zero keycode makes XLookupKeySym status. What I'm sure is that a combination of a zero scan code and a non zero sym makes SDL_PrivateKeyboard strange state... So, just discard it. If this doesn't work, I'm receiving bug reports, and I can know under what condition this case happens. */ if (keycode) { keysym.scancode = keycode; keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); keysym.mod = KMOD_NONE; keysym.unicode = 0; posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); } break; } case XLookupNone: { /* IM has eaten the event. */ break; } default: /* An unknown status from Xutf8LookupString. */ SDL_SetError("Oops! Xutf8LookupStringreturned an unknown status"); } /* Release dynamic buffers if allocated. */ if (keydata != NULL && keybuf != keydata) { SDL_free(keydata); } if (utf16data != NULL && utf16buf != utf16data) { SDL_free(utf16data); } } else#endif { static XComposeStatus state; char keybuf[32]; keysym.scancode = keycode; keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); keysym.mod = KMOD_NONE; keysym.unicode = 0; if ( XLookupString(&xevent.xkey, keybuf, sizeof(keybuf), NULL, &state) ) { /* * FIXME: XLookupString() may yield more than one * character, so we need a mechanism to allow for * this (perhaps null keypress events with a * unicode value) */ keysym.unicode = (Uint8)keybuf[0]; } posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); } } break; /* Key release? */ case KeyRelease: { SDL_keysym keysym; KeyCode keycode = xevent.xkey.keycode; if (keycode == 0) { /* There should be no KeyRelease for keycode == 0, since it is a notification from IM but a real keystroke. */ /* We need to emit some diagnostic message here. */ break; }#ifdef DEBUG_XEVENTSprintf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);#endif /* Get the translated SDL virtual keysym */ keysym.scancode = keycode; keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); keysym.mod = KMOD_NONE; keysym.unicode = 0; posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); } break; /* Have we been iconified? */ case UnmapNotify: {#ifdef DEBUG_XEVENTSprintf("UnmapNotify!\n");#endif /* If we're active, make ourselves inactive */ if ( SDL_GetAppState() & SDL_APPACTIVE ) { /* Swap out the gamma before we go inactive */ X11_SwapVidModeGamma(this); /* Send an internal deactivate event */ posted = SDL_PrivateAppActive(0, SDL_APPACTIVE|SDL_APPINPUTFOCUS); } } break; /* Have we been restored? */ case MapNotify: {#ifdef DEBUG_XEVENTSprintf("MapNotify!\n");#endif /* If we're not active, make ourselves active */ if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) { /* Send an internal activate event */ posted = SDL_PrivateAppActive(1, SDL_APPACTIVE); /* Now that we're active, swap the gamma back */ X11_SwapVidModeGamma(this); } if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) { X11_EnterFullScreen(this); } else { X11_GrabInputNoLock(this, this->input_grab); } X11_CheckMouseModeNoLock(this); if ( SDL_VideoSurface ) { X11_RefreshDisplay(this); } } break; /* Have we been resized or moved? */ case ConfigureNotify: {#ifdef DEBUG_XEVENTSprintf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height);#endif if ( SDL_VideoSurface ) { if ((xevent.xconfigure.width != SDL_VideoSurface->w) || (xevent.xconfigure.height != SDL_VideoSurface->h)) { /* FIXME: Find a better fix for the bug with KDE 1.2 */ if ( ! ((xevent.xconfigure.width == 32) && (xevent.xconfigure.height == 32)) ) { SDL_PrivateResize(xevent.xconfigure.width, xevent.xconfigure.height); } } else { /* OpenGL windows need to know about the change */ if ( SDL_VideoSurface->flags & SDL_OPENGL ) { SDL_PrivateExpose(); } } } } break; /* Have we been requested to quit (or another client message?) */ case ClientMessage: { if ( (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == WM_DELETE_WINDOW) ) { posted = SDL_PrivateQuit(); } else if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.event.xevent = xevent; posted = SDL_PrivateSysWMEvent(&wmmsg); } } break; /* Do we need to refresh ourselves? */ case Expose: {#ifdef DEBUG_XEVENTSprintf("Expose (count = %d)\n", xevent.xexpose.count);#endif if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) { X11_RefreshDisplay(this); } } break; default: {#ifdef DEBUG_XEVENTSprintf("Unhandled event %d\n", xevent.type);#endif /* Only post the event if we're watching for it */ if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.event.xevent = xevent; posted = SDL_PrivateSysWMEvent(&wmmsg); } } break; } return(posted);}/* Ack! XPending() actually performs a blocking read if no events available */int X11_Pending(Display *display){ /* Flush the display connection and look to see if events are queued */ XFlush(display); if ( XEventsQueued(display, QueuedAlready) ) { return(1); } /* More drastic measures are required -- see if X is ready to talk */ { static struct timeval zero_time; /* static == 0 */ int x11_fd; fd_set fdset; x11_fd = ConnectionNumber(display); FD_ZERO(&fdset); FD_SET(x11_fd, &fdset); if ( select(x11_fd+1, &fdset, NULL, NULL, &zero_time) == 1 ) { return(XPending(display)); } } /* Oh well, nothing is ready .. */ return(0);}void X11_PumpEvents(_THIS){ int pending; /* Keep processing pending events */ pending = 0; while ( X11_Pending(SDL_Display) ) { X11_DispatchEvent(this); ++pending; } if ( switch_waiting ) { Uint32 now; now = SDL_GetTicks(); if ( pending || !SDL_VideoSurface ) { /* Try again later... */ if ( switch_waiting & SDL_FULLSCREEN ) { switch_time = now + 1500; } else { switch_time = now + 200; } } else if ( (int)(switch_time-now) <= 0 ) { Uint32 go_fullscreen; go_fullscreen = switch_waiting & SDL_FULLSCREEN; switch_waiting = 0; if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) { if ( go_fullscreen ) { X11_EnterFullScreen(this); } else { X11_LeaveFullScreen(this); } } /* Handle focus in/out when grabbed */ if ( go_fullscreen ) { X11_GrabInputNoLock(this, this->input_grab); } else { X11_GrabInputNoLock(this, SDL_GRAB_OFF); } X11_CheckMouseModeNoLock(this); } }}void X11_InitKeymap(void){ int i; /* Odd keys used in international keyboards */ for ( i=0; i<SDL_arraysize(ODD_keymap); ++i ) ODD_keymap[i] = SDLK_UNKNOWN; /* Some of these might be mappable to an existing SDLK_ code */ ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -