// // I_ShutdownInput // void STACK_ARGS I_ShutdownInput (void) { I_PauseMouse(); #ifdef WIN32 // denis - in fullscreen, prevent exit on accidental windows key press UnhookWindowsHookEx(g_hKeyboardHook); #endif }
// // I_InitFocus // // Sets the initial value of window_focused. // static void I_InitFocus() { window_focused = I_CheckFocusState(); if (window_focused) { SDL_WM_GrabInput(SDL_GRAB_ON); I_ResumeMouse(); } else { SDL_WM_GrabInput(SDL_GRAB_OFF); I_PauseMouse(); } }
bool SDLVideo::SetMode(int width, int height, int bits, bool fullscreen) { Uint32 flags = (vid_vsync ? SDL_HWSURFACE | SDL_DOUBLEBUF : SDL_SWSURFACE); if (fullscreen && !vidModeList.empty()) flags |= SDL_FULLSCREEN; else flags |= SDL_RESIZABLE; if (fullscreen && bits == 8) flags |= SDL_HWPALETTE; // TODO: check for multicore flags |= SDL_ASYNCBLIT; // [SL] SDL_SetVideoMode reinitializes DirectInput if DirectX is being used. // This interferes with RawWin32Mouse's input handlers so we need to // disable them prior to reinitalizing DirectInput... I_PauseMouse(); int sbits = bits; #ifdef _WIN32 // fullscreen directx requires a 32-bit mode to fix broken palette // [Russell] - Use for gdi as well, fixes d2 map02 water if (fullscreen) sbits = 32; #endif #ifdef SDL_GL_SWAP_CONTROL SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vid_vsync); #endif if (!(sdlScreen = SDL_SetVideoMode(width, height, sbits, flags))) return false; // [SL] ...and re-enable RawWin32Mouse's input handlers after // DirectInput is reinitalized. I_ResumeMouse(); screenw = width; screenh = height; screenbits = bits; return true; }
// // I_UpdateInputGrabbing // // Determines if SDL should grab the mouse based on the game window having // focus and the status of the menu and console. // static void I_UpdateInputGrabbing() { #ifndef GCONSOLE bool can_grab = false; bool grabbed = SDL_WM_GrabInput(SDL_GRAB_QUERY); if (!window_focused) can_grab = false; else if (vid_fullscreen) can_grab = true; else if (nomouse) can_grab = false; else if (configuring_controls) can_grab = true; else if (menuactive || ConsoleState == c_down || paused) can_grab = false; else if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) && !demoplayback) can_grab = true; // force I_ResumeMouse or I_PauseMouse if toggling between fullscreen/windowed static float prev_vid_fullscreen = vid_fullscreen; if (vid_fullscreen != prev_vid_fullscreen) grabbed = !can_grab; prev_vid_fullscreen = vid_fullscreen; // check if the window focus changed (or menu/console status changed) if (can_grab && !grabbed) { SDL_WM_GrabInput(SDL_GRAB_ON); I_ResumeMouse(); I_FlushInput(); } else if (grabbed && !can_grab) { SDL_WM_GrabInput(SDL_GRAB_OFF); I_PauseMouse(); } #endif }
// // I_GetEvent // void I_GetEvent (void) { event_t event; event_t mouseevent = {ev_mouse, 0, 0, 0}; static int mbuttons = 0; int sendmouseevent = 0; SDL_Event ev; if (!havefocus) I_PauseMouse(); else { I_ResumeMouse(); } while(SDL_PollEvent(&ev)) { event.data1 = event.data2 = event.data3 = 0; switch(ev.type) { case SDL_QUIT: AddCommandString("menu_quit"); break; // Resizable window mode resolutions case SDL_VIDEORESIZE: { if (!vid_fullscreen) { char Command[64]; mousegrabbed = false; snprintf(Command, sizeof(Command), "vid_setmode %d %d", ev.resize.w, ev.resize.h); AddCommandString(Command); vid_defwidth.Set((float)ev.resize.w); vid_defheight.Set((float)ev.resize.h); } } break; case SDL_ACTIVEEVENT: // need to update our focus state UpdateFocus(); break; case SDL_KEYDOWN: event.type = ev_keydown; event.data1 = ev.key.keysym.sym; if(event.data1 >= SDLK_KP0 && event.data1 <= SDLK_KP9) event.data2 = event.data3 = '0' + (event.data1 - SDLK_KP0); else if(event.data1 == SDLK_KP_PERIOD) event.data2 = event.data3 = '.'; else if(event.data1 == SDLK_KP_DIVIDE) event.data2 = event.data3 = '/'; else if(event.data1 == SDLK_KP_ENTER) event.data2 = event.data3 = '\r'; else if ( (ev.key.keysym.unicode & 0xFF80) == 0 ) event.data2 = event.data3 = ev.key.keysym.unicode; else event.data2 = event.data3 = 0; #ifdef _XBOX // Fix for ENTER key on Xbox if(event.data1 == SDLK_RETURN) event.data2 = event.data3 = '\r'; #endif #ifdef WIN32 //HeX9109: Alt+F4 for cheats! Thanks Spleen if(event.data1 == SDLK_F4 && SDL_GetModState() & (KMOD_LALT | KMOD_RALT)) AddCommandString("menu_quit"); // SoM: Ignore the tab portion of alt-tab presses if(event.data1 == SDLK_TAB && SDL_GetModState() & (KMOD_LALT | KMOD_RALT)) event.data1 = event.data2 = event.data3 = 0; else #endif D_PostEvent(&event); break; case SDL_KEYUP: event.type = ev_keyup; event.data1 = ev.key.keysym.sym; if ( (ev.key.keysym.unicode & 0xFF80) == 0 ) event.data2 = event.data3 = ev.key.keysym.unicode; else event.data2 = event.data3 = 0; D_PostEvent(&event); break; case SDL_MOUSEMOTION: if(flushmouse) { flushmouse = false; break; } if (!havefocus) break; // denis - ignore artificially inserted events (see SDL_WarpMouse below) if(ev.motion.x == screen->width/2 && ev.motion.y == screen->height/2) { break; } mouseevent.data2 += AccelerateMouse(ev.motion.xrel); mouseevent.data3 -= AccelerateMouse(ev.motion.yrel); sendmouseevent = 1; break; case SDL_MOUSEBUTTONDOWN: if(nomouse || !havefocus) break; event.type = ev_keydown; if(ev.button.button == SDL_BUTTON_LEFT) { event.data1 = KEY_MOUSE1; mbuttons |= 1; } else if(ev.button.button == SDL_BUTTON_RIGHT) { event.data1 = KEY_MOUSE2; mbuttons |= 2; } else if(ev.button.button == SDL_BUTTON_MIDDLE) { event.data1 = KEY_MOUSE3; mbuttons |= 4; } else if(ev.button.button == SDL_BUTTON_WHEELUP) event.data1 = KEY_MWHEELUP; else if(ev.button.button == SDL_BUTTON_WHEELDOWN) event.data1 = KEY_MWHEELDOWN; D_PostEvent(&event); break; case SDL_MOUSEBUTTONUP: if(nomouse || !havefocus) break; event.type = ev_keyup; if(ev.button.button == SDL_BUTTON_LEFT) { event.data1 = KEY_MOUSE1; mbuttons &= ~1; } else if(ev.button.button == SDL_BUTTON_RIGHT) { event.data1 = KEY_MOUSE2; mbuttons &= ~2; } else if(ev.button.button == SDL_BUTTON_MIDDLE) { event.data1 = KEY_MOUSE3; mbuttons &= ~4; } else if(ev.button.button == SDL_BUTTON_WHEELUP) event.data1 = KEY_MWHEELUP; else if(ev.button.button == SDL_BUTTON_WHEELDOWN) event.data1 = KEY_MWHEELDOWN; D_PostEvent(&event); break; case SDL_JOYBUTTONDOWN: if(ev.jbutton.which == joy_active) { event.type = ev_keydown; event.data1 = ev.jbutton.button + KEY_JOY1; event.data2 = event.data1; D_PostEvent(&event); break; } case SDL_JOYBUTTONUP: if(ev.jbutton.which == joy_active) { event.type = ev_keyup; event.data1 = ev.jbutton.button + KEY_JOY1; event.data2 = event.data1; D_PostEvent(&event); break; } case SDL_JOYAXISMOTION: if(ev.jaxis.which == joy_active) { event.type = ev_joystick; event.data1 = 0; event.data2 = ev.jaxis.axis; if( (ev.jaxis.value < JOY_DEADZONE) && (ev.jaxis.value > -JOY_DEADZONE) ) event.data3 = 0; else event.data3 = ev.jaxis.value; D_PostEvent(&event); break; } case SDL_JOYHATMOTION: if(ev.jhat.which == joy_active) { // Each of these need to be tested because more than one can be pressed and a // unique event is needed for each if(ev.jhat.value & SDL_HAT_UP) RegisterJoystickEvent(&ev, SDL_HAT_UP); if(ev.jhat.value & SDL_HAT_RIGHT) RegisterJoystickEvent(&ev, SDL_HAT_RIGHT); if(ev.jhat.value & SDL_HAT_DOWN) RegisterJoystickEvent(&ev, SDL_HAT_DOWN); if(ev.jhat.value & SDL_HAT_LEFT) RegisterJoystickEvent(&ev, SDL_HAT_LEFT); break; } }; } if(!nomouse) { if(sendmouseevent) { mouseevent.data1 = mbuttons; D_PostEvent(&mouseevent); } if(mousegrabbed && screen) { SDL_WarpMouse(screen->width/ 2, screen->height / 2); } } if(use_joystick) UpdateJoystickEvents(); }
// // I_GetEvent // // Pumps SDL for new input events and posts them to the Doom event queue. // Keyboard and joystick events are retreived directly from SDL while mouse // movement and buttons are handled by the MouseInput class. // void I_GetEvent() { const int MAX_EVENTS = 256; static SDL_Event sdl_events[MAX_EVENTS]; event_t event; // Process mouse movement and button events if (mouse_input) mouse_input->processEvents(); // Force SDL to gather events from input devices. This is called // implicitly from SDL_PollEvent but since we're using SDL_PeepEvents to // process only non-mouse events, SDL_PumpEvents is necessary. SDL_PumpEvents(); int num_events = SDL_PeepEvents(sdl_events, MAX_EVENTS, SDL_GETEVENT, SDL_ALLEVENTS & ~SDL_MOUSEEVENTMASK); for (int i = 0; i < num_events; i++) { event.data1 = event.data2 = event.data3 = 0; SDL_Event* sdl_ev = &sdl_events[i]; switch (sdl_ev->type) { case SDL_QUIT: AddCommandString("quit"); break; case SDL_VIDEORESIZE: { // Resizable window mode resolutions if (!vid_fullscreen) { std::stringstream Command; Command << "vid_setmode " << sdl_ev->resize.w << " " << sdl_ev->resize.h; AddCommandString(Command.str()); vid_defwidth.Set((float)sdl_ev->resize.w); vid_defheight.Set((float)sdl_ev->resize.h); } break; } case SDL_ACTIVEEVENT: // need to update our focus state I_UpdateFocus(); // pause the mouse when the focus goes away (eg, alt-tab) if (!window_focused) I_PauseMouse(); break; case SDL_KEYDOWN: event.type = ev_keydown; event.data1 = sdl_ev->key.keysym.sym; if (event.data1 >= SDLK_KP0 && event.data1 <= SDLK_KP9) event.data2 = event.data3 = '0' + (event.data1 - SDLK_KP0); else if (event.data1 == SDLK_KP_PERIOD) event.data2 = event.data3 = '.'; else if (event.data1 == SDLK_KP_DIVIDE) event.data2 = event.data3 = '/'; else if (event.data1 == SDLK_KP_ENTER) event.data2 = event.data3 = '\r'; else if ((sdl_ev->key.keysym.unicode & 0xFF80) == 0) event.data2 = event.data3 = sdl_ev->key.keysym.unicode; else event.data2 = event.data3 = 0; #ifdef _XBOX // Fix for ENTER key on Xbox if (event.data1 == SDLK_RETURN) event.data2 = event.data3 = '\r'; #endif #ifdef _WIN32 //HeX9109: Alt+F4 for cheats! Thanks Spleen if (event.data1 == SDLK_F4 && SDL_GetModState() & (KMOD_LALT | KMOD_RALT)) AddCommandString("quit"); // SoM: Ignore the tab portion of alt-tab presses // [AM] Windows 7 seems to preempt this check. if (event.data1 == SDLK_TAB && SDL_GetModState() & (KMOD_LALT | KMOD_RALT)) event.data1 = event.data2 = event.data3 = 0; else #endif D_PostEvent(&event); break; case SDL_KEYUP: event.type = ev_keyup; event.data1 = sdl_ev->key.keysym.sym; if ((sdl_ev->key.keysym.unicode & 0xFF80) == 0) event.data2 = event.data3 = sdl_ev->key.keysym.unicode; else event.data2 = event.data3 = 0; D_PostEvent(&event); break; case SDL_JOYBUTTONDOWN: if (sdl_ev->jbutton.which == joy_active) { event.type = ev_keydown; event.data1 = sdl_ev->jbutton.button + KEY_JOY1; event.data2 = event.data1; D_PostEvent(&event); break; } case SDL_JOYBUTTONUP: if (sdl_ev->jbutton.which == joy_active) { event.type = ev_keyup; event.data1 = sdl_ev->jbutton.button + KEY_JOY1; event.data2 = event.data1; D_PostEvent(&event); break; } case SDL_JOYAXISMOTION: if (sdl_ev->jaxis.which == joy_active) { event.type = ev_joystick; event.data1 = 0; event.data2 = sdl_ev->jaxis.axis; if ((sdl_ev->jaxis.value < JOY_DEADZONE) && (sdl_ev->jaxis.value > -JOY_DEADZONE)) event.data3 = 0; else event.data3 = sdl_ev->jaxis.value; D_PostEvent(&event); break; } case SDL_JOYHATMOTION: if (sdl_ev->jhat.which == joy_active) { // Each of these need to be tested because more than one can be pressed and a // unique event is needed for each if (sdl_ev->jhat.value & SDL_HAT_UP) RegisterJoystickEvent(sdl_ev, SDL_HAT_UP); if (sdl_ev->jhat.value & SDL_HAT_RIGHT) RegisterJoystickEvent(sdl_ev, SDL_HAT_RIGHT); if (sdl_ev->jhat.value & SDL_HAT_DOWN) RegisterJoystickEvent(sdl_ev, SDL_HAT_DOWN); if (sdl_ev->jhat.value & SDL_HAT_LEFT) RegisterJoystickEvent(sdl_ev, SDL_HAT_LEFT); break; } }; } if (use_joystick) UpdateJoystickEvents(); }
// // SDLMouse::~SDLMouse // SDLMouse::~SDLMouse() { I_PauseMouse(); }
// // ISDL12Window::setMode // // Sets the window size to the specified size and frees the existing primary // surface before instantiating a new primary surface. This function performs // no sanity checks on the desired video mode. // // NOTE: If a hardware surface is obtained or the surface's screen pitch // will create cache thrashing (tested by pitch & 511 == 0), a SDL software // surface will be created and used for drawing video frames. This software // surface is then blitted to the screen at the end of the frame, prior to // calling SDL_Flip. // bool ISDL12Window::setMode(uint16_t video_width, uint16_t video_height, uint8_t video_bpp, bool video_fullscreen, bool vsync) { uint32_t flags = 0; if (vsync) flags |= SDL_HWSURFACE | SDL_DOUBLEBUF; else flags |= SDL_SWSURFACE; if (video_fullscreen) flags |= SDL_FULLSCREEN; else flags |= SDL_RESIZABLE; if (video_fullscreen && video_bpp == 8) flags |= SDL_HWPALETTE; // TODO: check for multicore flags |= SDL_ASYNCBLIT; //if (video_fullscreen) // flags = ((flags & (~SDL_SWSURFACE)) | SDL_HWSURFACE); #ifdef SDL_GL_SWAP_CONTROL SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vsync); #endif // [SL] SDL_SetVideoMode reinitializes DirectInput if DirectX is being used. // This interferes with RawWin32Mouse's input handlers so we need to // disable them prior to reinitalizing DirectInput... I_PauseMouse(); SDL_Surface* sdl_surface = SDL_SetVideoMode(video_width, video_height, video_bpp, flags); if (sdl_surface == NULL) { I_FatalError("I_SetVideoMode: unable to set video mode %ux%ux%u (%s): %s\n", video_width, video_height, video_bpp, video_fullscreen ? "fullscreen" : "windowed", SDL_GetError()); return false; } assert(sdl_surface == SDL_GetVideoSurface()); // [SL] ...and re-enable RawWin32Mouse's input handlers after // DirectInput is reinitalized. I_ResumeMouse(); PixelFormat format; I_BuildPixelFormatFromSDLSurface(sdl_surface, &format); // just in case SDL couldn't set the exact video mode we asked for... mWidth = sdl_surface->w; mHeight = sdl_surface->h; mBitsPerPixel = format.getBitsPerPixel(); mIsFullScreen = (sdl_surface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN; mUseVSync = vsync; if (SDL_MUSTLOCK(sdl_surface)) SDL_LockSurface(sdl_surface); // lock prior to accessing pixel format delete mSurfaceManager; bool got_hardware_surface = (sdl_surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE; bool create_software_surface = (sdl_surface->pitch & 511) == 0 || // pitch is a multiple of 512 (thrashes the cache) got_hardware_surface; // drawing directly to hardware surfaces is slower if (create_software_surface) mSurfaceManager = new ISDL12SoftwareWindowSurfaceManager(mWidth, mHeight, &format); else mSurfaceManager = new ISDL12DirectWindowSurfaceManager(mWidth, mHeight, &format); assert(mSurfaceManager != NULL); assert(getPrimarySurface() != NULL); if (SDL_MUSTLOCK(sdl_surface)) SDL_UnlockSurface(sdl_surface); mVideoMode = IVideoMode(mWidth, mHeight, mBitsPerPixel, mIsFullScreen); assert(mWidth >= 0 && mWidth <= MAXWIDTH); assert(mHeight >= 0 && mHeight <= MAXHEIGHT); assert(mBitsPerPixel == 8 || mBitsPerPixel == 32); // Tell argb_t the pixel format if (format.getBitsPerPixel() == 32) argb_t::setChannels(format.getAPos(), format.getRPos(), format.getGPos(), format.getBPos()); else argb_t::setChannels(3, 2, 1, 0); // [SL] SDL can create SDL_VIDEORESIZE events in response to SDL_SetVideoMode // and we need to filter those out. mIgnoreResize = true; return true; }