예제 #1
0
static void handle_key(XGenericEventCookie *cookie)
{
	XIDeviceEvent *ev = (XIDeviceEvent *)cookie->data;
	qboolean down = cookie->evtype == XI_KeyPress;
	int keycode = ev->detail;
	unsigned time = Sys_XTimeToSysTime(ev->time);

	// Ignore shift_level for game key press
	KeySym keysym = XkbKeycodeToKeysym(x11display.dpy, keycode, 0, 0);
	int key = XLateKey( keysym );

	// Set or clear 1 in the shift_level bitmask
	if ( keysym == XK_Shift_L || keysym == XK_Shift_R )
		shift_level ^=  (-down ^ shift_level) & 1;

	// Set or clear 2 in the shift_level bitmask
	else if( keysym == XK_ISO_Level3_Shift )
		shift_level ^=  (-down ^ shift_level) & 2;

	Key_Event(key, down, time);

	if( down )
	{
		// Use shift_level for chat and console input
		qwchar wc = keysym2ucs(XkbKeycodeToKeysym(x11display.dpy, keycode, 0, shift_level));
		if( wc == -1 && key > K_NUMLOCK && key <= KP_EQUAL )
			wc = ( qwchar )key;

		// Convert ctrl-c / ctrl-v combinations to the expected events
		if( Key_IsDown(K_LCTRL) || Key_IsDown(K_RCTRL) )
		{
			if( key == 'v' )
			{
				key = CTRLV;
				wc = CTRLV;
			}
			else if( key == 'c' )
			{
				key = CTRLC;
				wc = CTRLC;
			}
		}
		Key_CharEvent( key, wc );
	}
}
예제 #2
0
/*
* IN_Android_OnInputEvent
*/
static int32_t IN_Android_OnInputEvent( struct android_app *app, AInputEvent *event )
{
	int32_t type = AInputEvent_getType( event );
	int64_t time;

	if( type == AINPUT_EVENT_TYPE_KEY )
	{
		int32_t keycode = AKeyEvent_getKeyCode( event );
		int key;

		if( keycode >= ( sizeof( s_android_scantokey ) / sizeof( s_android_scantokey[0] ) ) )
			return 0;

		if( ( keycode >= AKEYCODE_DPAD_UP ) && ( keycode <= AKEYCODE_DPAD_RIGHT ) &&
			( AInputEvent_getSource( event ) == AINPUT_SOURCE_KEYBOARD ) )
		{
			key = keycode + ( K_UPARROW - AKEYCODE_DPAD_UP );
		}
		else
		{
			key = s_android_scantokey[keycode];
		}
		if( !key )
			return 0;

		time = AKeyEvent_getEventTime( event ) / ( ( int64_t )1000000 );

		switch( AKeyEvent_getAction( event ) )
		{
		case AKEY_EVENT_ACTION_DOWN:
		case AKEY_EVENT_ACTION_MULTIPLE:
			if( ( key == K_ESCAPE ) && IN_Android_HideSoftKeyboard() ) // Instead of broken AInputQueue_preDispatchEvent.
				return 1;

			Key_Event( key, true, time );

			if( Key_IsDown( K_LCTRL ) || Key_IsDown( K_RCTRL ) )
			{
				if( key == 'v' )
					Key_CharEvent( KC_CTRLV, KC_CTRLV );
				else if( key == 'c' )
					Key_CharEvent( KC_CTRLC, KC_CTRLC );
				else
					Key_CharEvent( key, IN_Android_KeyEvent2UCS( event ) );
			}
			else
			{
				Key_CharEvent( key, IN_Android_KeyEvent2UCS( event ) );
			}
			break;

		case AKEY_EVENT_ACTION_UP:
			Key_Event( key, false, time );
			break;
		}

		return 1;
	}

	if( type == AINPUT_EVENT_TYPE_MOTION )
	{
		int32_t action = AMotionEvent_getAction( event );
		int32_t source = AInputEvent_getSource( event );
		int x, y;

		time = AMotionEvent_getEventTime( event ) / ( ( int64_t )1000000 );

		switch( source )
		{
		case AINPUT_SOURCE_TOUCHSCREEN:
			{
				touchevent_t type;
				size_t i, pointerCount = 0, p;

				switch( action & AMOTION_EVENT_ACTION_MASK )
				{
				case AMOTION_EVENT_ACTION_DOWN:
				case AMOTION_EVENT_ACTION_POINTER_DOWN:
					type = TOUCH_DOWN;
					pointerCount = 1;
					break;
				case AMOTION_EVENT_ACTION_POINTER_UP:
					type = TOUCH_UP;
					pointerCount = 1;
					break;
				case AMOTION_EVENT_ACTION_MOVE:
					type = TOUCH_MOVE;
					pointerCount = AMotionEvent_getPointerCount( event );
					break;
				case AMOTION_EVENT_ACTION_UP:
				case AMOTION_EVENT_ACTION_CANCEL:
				case AMOTION_EVENT_ACTION_OUTSIDE:
					type = TOUCH_UP;
					pointerCount = AMotionEvent_getPointerCount( event );
					break;
				}

				p = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
				for( i = 0; i < pointerCount; ++i, ++p )
				{
					if( IN_Android_EventToWindowCoordinates( event, p, &x, &y ) )
						CL_TouchEvent( AMotionEvent_getPointerId( event, p ), type, x, y, time );
				}
			}
			break;

		case AINPUT_SOURCE_JOYSTICK:
			{
				float hatXValue = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_HAT_X, 0 );
				float hatYValue = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_HAT_Y, 0 );
				int hatX = 0, hatY = 0;
				static int oldHatX = 0, oldHatY = 0;
				bool leftTrigger, rightTrigger;
				static bool oldLeftTrigger = false, oldRightTrigger = false;

				in_android_thumbsticks[0] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_X, 0 );
				in_android_thumbsticks[1] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_Y, 0 );
				in_android_thumbsticks[2] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_Z, 0 );
				in_android_thumbsticks[3] = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RZ, 0 );

				hatX = ( hatXValue > 0.5f ) - ( hatXValue < -0.5f );
				hatY = ( hatYValue > 0.5f ) - ( hatYValue < -0.5f );
				if( hatX != oldHatX )
				{
					if( oldHatX )
						Key_Event( K_DPAD_LEFT + ( oldHatX > 0 ), false, time );
					if( hatX )
						Key_Event( K_DPAD_LEFT + ( hatX > 0 ), true, time );
					oldHatX = hatX;
				}
				if( hatY != oldHatY )
				{
					if( oldHatY )
						Key_Event( K_DPAD_UP + ( oldHatY > 0 ), false, time );
					if( hatY )
						Key_Event( K_DPAD_UP + ( hatY > 0 ), true, time );
					oldHatY = hatY;
				}

				leftTrigger = ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_BRAKE, 0 ) > ( 30.0f / 255.0f ) )
					|| ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_LTRIGGER, 0 ) > ( 30.0f / 255.0f ) );
				rightTrigger = ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_GAS, 0 ) > ( 30.0f / 255.0f ) )
					|| ( AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_RTRIGGER, 0 ) > ( 30.0f / 255.0f ) );
				if( leftTrigger != oldLeftTrigger )
				{
					Key_Event( K_LTRIGGER, leftTrigger, time );
					oldLeftTrigger = leftTrigger;
				}
				if( rightTrigger != oldRightTrigger )
				{
					Key_Event( K_RTRIGGER, rightTrigger, time );
					oldRightTrigger = rightTrigger;
				}
			}
			break;

		case AINPUT_SOURCE_MOUSE:
			{
				switch( action & AMOTION_EVENT_ACTION_MASK )
				{
				case AMOTION_EVENT_ACTION_DOWN:
				case AMOTION_EVENT_ACTION_UP:
					{
						static int32_t oldButtonState = 0;
						int32_t buttonState = AMotionEvent_getButtonState( event );
						int32_t buttonsDown = buttonState & ~oldButtonState, buttonsUp = oldButtonState & ~buttonState;
						int32_t buttonsChanged = buttonsDown | buttonsUp;
						int button;
						oldButtonState = buttonState;
						for( button = 0; buttonsChanged >> button; button++ )
						{
							if( buttonsChanged & ( 1 << button ) )
								Key_MouseEvent( K_MOUSE1 + button, ( buttonsDown & ( 1 << button ) ) ? true : false, time );
						}
					}
					break;
				case AMOTION_EVENT_ACTION_HOVER_MOVE:
				case AMOTION_EVENT_ACTION_MOVE:
					if( IN_Android_EventToWindowCoordinates( event, 0, &x, &y ) )
						CL_MouseSet( x, y, false );
					break;
				case AMOTION_EVENT_ACTION_SCROLL:
					{
						float scroll = AMotionEvent_getAxisValue( event, AMOTION_EVENT_AXIS_VSCROLL, 0 );
						if( scroll > 0.0f )
						{
							Key_Event( K_MWHEELUP, true, time );
							Key_Event( K_MWHEELUP, false, time );
						}
						else if( scroll < 0.0f )
						{
							Key_Event( K_MWHEELDOWN, true, time );
							Key_Event( K_MWHEELDOWN, false, time );
						}
					}
					break;
				}
			}
			break;
		}

		return 1;
	}
예제 #3
0
static void IN_HandleEvents( void )
{
	Uint16 *wtext = NULL;
	SDL_PumpEvents();
	SDL_Event event;

	while( SDL_PollEvent( &event ) ) {
		switch( event.type ) {
			case SDL_KEYDOWN:
				key_event( &event.key, true );

				// Emulate copy/paste
				#if defined( __APPLE__ )
					#define KEYBOARD_COPY_PASTE_MODIFIER KMOD_GUI
				#else
					#define KEYBOARD_COPY_PASTE_MODIFIER KMOD_CTRL
				#endif
				
				if( event.key.keysym.sym == SDLK_c ) {
					if( event.key.keysym.mod & KEYBOARD_COPY_PASTE_MODIFIER ) {
						Key_CharEvent( KC_CTRLC, KC_CTRLC );
					}
				}
				else if( event.key.keysym.sym == SDLK_v ) {
					if( event.key.keysym.mod & KEYBOARD_COPY_PASTE_MODIFIER ) {
						Key_CharEvent( KC_CTRLV, KC_CTRLV );
					}
				}

				break;

			case SDL_KEYUP:
				key_event( &event.key, false );
				break;

			case SDL_TEXTINPUT:
				// SDL_iconv_utf8_ucs2 uses "UCS-2-INTERNAL" as tocode and fails to convert text on Linux
				// where SDL_iconv uses system iconv. So we force needed encoding directly

				#if SDL_BYTEORDER == SDL_LIL_ENDIAN
					#define UCS_2_INTERNAL "UCS-2LE"
				#else
					#define UCS_2_INTERNAL "UCS-2BE"
				#endif

				wtext = (Uint16 *)SDL_iconv_string( UCS_2_INTERNAL, "UTF-8", event.text.text, SDL_strlen( event.text.text ) + 1 );
				if( wtext ) {
					wchar_t charkey = wtext[0];
					int key = ( charkey <= 255 ) ? charkey : 0;
					Key_CharEvent( key, charkey );
					SDL_free( wtext );
				}
				break;

			case SDL_MOUSEMOTION:
				mouse_motion_event( &event.motion );
				break;

			case SDL_MOUSEBUTTONDOWN:
				mouse_button_event( &event.button, true );
				break;

			case SDL_MOUSEBUTTONUP:
				mouse_button_event( &event.button, false );
				break;

			case SDL_MOUSEWHEEL:
				mouse_wheel_event( &event.wheel );
				break;

			case SDL_QUIT:
				Cbuf_ExecuteText( EXEC_NOW, "quit" );
				break;

			case SDL_WINDOWEVENT:
				switch( event.window.event ) {
					case SDL_WINDOWEVENT_SHOWN:
						AppActivate( true );
						break;
					case SDL_WINDOWEVENT_HIDDEN:
						AppActivate( false );
						break;
					case SDL_WINDOWEVENT_CLOSE:
						break;
					case SDL_WINDOWEVENT_FOCUS_GAINED:
						input_focus = true;
						break;
					case SDL_WINDOWEVENT_FOCUS_LOST:
						input_focus = false;
						break;
					case SDL_WINDOWEVENT_MOVED:
						// FIXME: move this somewhere else
						Cvar_SetValue( "vid_xpos", event.window.data1 );
						Cvar_SetValue( "vid_ypos", event.window.data2 );
						vid_xpos->modified = false;
						vid_ypos->modified = false;
						break;
				}
				break;
		}
	}
}
예제 #4
0
파일: vid_win.c 프로젝트: Bad-ptr/q2pro
// main window procedure
STATIC LONG WINAPI Win_MainWndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
    switch( uMsg ) {
    case WM_MOUSEWHEEL:
        if( win.mouse.initialized == WIN_MOUSE_LEGACY ) {
            mouse_wheel_event( ( short )HIWORD( wParam ) );
        }
        break;
    case WM_MOUSEHWHEEL:
        if( win.mouse.initialized == WIN_MOUSE_LEGACY ) {
            mouse_hwheel_event( ( short )HIWORD( wParam ) );
        }
        break;

    case WM_NCMOUSEMOVE:
        if( win.mouse.initialized ) {
            // don't hide cursor
            IN_MouseEvent( -1, -1 );
        }
        break;

    case WM_MOUSEMOVE:
        if( win.mouse.initialized ) {
            int x = ( short )LOWORD( lParam );
            int y = ( short )HIWORD( lParam );

            IN_MouseEvent( x, y );
        }
        // fall through

    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_RBUTTONDOWN:
    case WM_RBUTTONUP:
    case WM_MBUTTONDOWN:
    case WM_MBUTTONUP:
    case WM_XBUTTONDOWN:
    case WM_XBUTTONUP:
        if( win.mouse.initialized == WIN_MOUSE_LEGACY ) {
            legacy_mouse_event( wParam );
        }
        break;

    case WM_HOTKEY:
        return FALSE;

    case WM_INPUT:
        if( wParam == RIM_INPUT && win.mouse.initialized == WIN_MOUSE_RAW ) {
            raw_input_event( ( HANDLE )lParam );
        }
        break;

    case WM_CLOSE:
        PostQuitMessage( 0 );
        return FALSE;

    case WM_ACTIVATE:
        Win_Activate( wParam );
        break;

    case WM_WINDOWPOSCHANGING:
        if( !( win.flags & QVF_FULLSCREEN ) ) {
            WINDOWPOS *pos = ( WINDOWPOS * )lParam;
            if( !( pos->flags & SWP_NOSIZE ) ) {
                resizing_event( hWnd, pos );
            }
        }
        break;

    case WM_SIZE:
        if( wParam == SIZE_RESTORED && !( win.flags & QVF_FULLSCREEN ) ) {
            int w = ( short )LOWORD( lParam );
            int h = ( short )HIWORD( lParam );

            win.rc.width = w;
            win.rc.height = h;

            win.mode_changed |= MODE_SIZE;
        }
        break;

    case WM_MOVE: 
        if( !( win.flags & QVF_FULLSCREEN ) ) {
            int x = ( short )LOWORD( lParam );
            int y = ( short )HIWORD( lParam );
            RECT r;

            // adjust for non-client area
            get_nc_area_size( hWnd, &r );
            win.rc.x = x + r.left;
            win.rc.y = y + r.top;

            win.mode_changed |= MODE_POS;
        }
        break;

    case WM_SYSCOMMAND:
        switch( wParam & 0xFFF0 ) {
        case SC_SCREENSAVE:
            return FALSE;
        case SC_MAXIMIZE:
            if( !vid_fullscreen->integer ) {
                VID_ToggleFullscreen();
            }
            return FALSE;
        }
        break;

    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
        legacy_key_event( wParam, lParam, qtrue );
        return FALSE;

    case WM_KEYUP:
    case WM_SYSKEYUP:
        legacy_key_event( wParam, lParam, qfalse );
        return FALSE;

    case WM_SYSCHAR:
    case WM_CHAR:
#if USE_CHAR_EVENTS
        Key_CharEvent( wParam );
#endif
        return FALSE;

    default:    
        break;
    }

    // pass all unhandled messages to DefWindowProc
    return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
예제 #5
0
static void HandleEvents( void )
{
	XEvent event;
	qboolean dowarp = qfalse, was_focused = focus;
	int mwx = x11display.win_width / 2;
	int mwy = x11display.win_height / 2;
	char *p;
	int key = 0;
	int time = 0;

	assert( x11display.dpy && x11display.win );

#ifdef WSW_EVDEV
	if( mouse_active && m_evdev_num )
	{
		evdev_read();
	}
	else
#endif
		if( mouse_active && !dgamouse )
		{
			int root_x, root_y, win_x, win_y;
			unsigned int mask;
			Window root, child;

			if( XQueryPointer( x11display.dpy, x11display.win, &root, &child,
				&root_x, &root_y, &win_x, &win_y, &mask ) )
			{
				mx += ( (int)win_x - mwx );
				my += ( (int)win_y - mwy );
				mwx = win_x;
				mwy = win_y;

				if( mx || my )
					dowarp = qtrue;

				if( ignore_one )
				{
					mx = my = 0;
					ignore_one = qfalse;
				}
			}
		}


		while( XPending( x11display.dpy ) )
		{
			XNextEvent( x11display.dpy, &event );

			switch( event.type )
			{
			case KeyPress:
				time = Sys_XTimeToSysTime(event.xkey.time);
				p = XLateKey( &event.xkey, &key );
				if( key )
					Key_Event( key, qtrue, time );
				while ( p && *p )
				{
					qwchar wc = Q_GrabWCharFromUtf8String( (const char **)&p );
					Key_CharEvent( key, wc );
				}
				break;

			case KeyRelease:
				if( repeated_press( &event ) )
					break; // don't send release events when repeating

				time = Sys_XTimeToSysTime(event.xkey.time);
				XLateKey( &event.xkey, &key );
				Key_Event( key, event.type == KeyPress, time );
				break;

			case MotionNotify:
#ifdef WSW_EVDEV
				if( mouse_active && dgamouse && !m_evdev_num )
#else
				if( mouse_active && dgamouse )
#endif
				{
					mx += event.xmotion.x_root;
					my += event.xmotion.y_root;
					if( ignore_one )
					{
						mx = my = 0;
						ignore_one = qfalse;
					}
				}
				break;

			case ButtonPress:
				if( ( cls.key_dest == key_console ) && !in_grabinconsole->integer )
					break;
#ifdef WSW_EVDEV
				if( m_evdev_num )
					break;
#endif
				time = Sys_XTimeToSysTime(event.xkey.time);
				if( event.xbutton.button == 1 ) Key_MouseEvent( K_MOUSE1, 1, time );
				else if( event.xbutton.button == 2 ) Key_MouseEvent( K_MOUSE3, 1, time );
				else if( event.xbutton.button == 3 ) Key_MouseEvent( K_MOUSE2, 1, time );
				else if( event.xbutton.button == 4 ) Key_Event( K_MWHEELUP, 1, time );
				else if( event.xbutton.button == 5 ) Key_Event( K_MWHEELDOWN, 1, time );
				else if( event.xbutton.button >= 6 && event.xbutton.button <= 10 ) Key_MouseEvent( K_MOUSE4+event.xbutton.button-6, 1, time );
				break;

			case ButtonRelease:
				if( ( cls.key_dest == key_console ) && !in_grabinconsole->integer )
					break;
#ifdef WSW_EVDEV
				if( m_evdev_num )
					break;
#endif
				time = Sys_XTimeToSysTime(event.xkey.time);
				if( event.xbutton.button == 1 ) Key_MouseEvent( K_MOUSE1, 0, time );
				else if( event.xbutton.button == 2 ) Key_MouseEvent( K_MOUSE3, 0, time );
				else if( event.xbutton.button == 3 ) Key_MouseEvent( K_MOUSE2, 0, time );
				else if( event.xbutton.button == 4 ) Key_Event( K_MWHEELUP, 0, time );
				else if( event.xbutton.button == 5 ) Key_Event( K_MWHEELDOWN, 0, time );
				else if( event.xbutton.button >= 6 && event.xbutton.button <= 10 ) Key_MouseEvent( K_MOUSE4+event.xbutton.button-6, 0, time );
				break;

			case FocusIn:
				if( x11display.ic )
					XSetICFocus(x11display.ic);
				if( !focus )
				{
					focus = qtrue;
				}
				break;

			case FocusOut:
				if( x11display.ic )
					XUnsetICFocus(x11display.ic);
				if( focus )
				{
					Key_ClearStates();
					focus = qfalse;
				}
				break;

			case ClientMessage:
				if( event.xclient.data.l[0] == x11display.wmDeleteWindow )
					Cbuf_ExecuteText( EXEC_NOW, "quit" );
				break;

			case MapNotify:
				mapped = qtrue;
				if( x11display.modeset )
				{
					if ( x11display.dpy && x11display.win )
					{
						XSetInputFocus( x11display.dpy, x11display.win, RevertToPointerRoot, CurrentTime );
						x11display.modeset = qfalse;
					}
				}
				if( input_active )
				{
					uninstall_grabs();
					install_grabs();
				}
				break;

			case ConfigureNotify:
				VID_AppActivate( qtrue, qfalse );
				break;

			case PropertyNotify:
				if( event.xproperty.window == x11display.win )
				{
					if ( event.xproperty.atom == x11display.wmState )
					{
						qboolean was_minimized = minimized;

						_X11_CheckWMSTATE();

						if( minimized != was_minimized )
						{
							// FIXME: find a better place for this?..
							CL_SoundModule_Activate( !minimized );
						}
					}
				}
				break;
			}
		}

		if( dowarp )
		{
			XWarpPointer( x11display.dpy, None, x11display.win, 0, 0, 0, 0,
				x11display.win_width/2, x11display.win_height/2 );
		}

		// set fullscreen or windowed mode upon focus in/out events if:
		//  a) lost focus in fullscreen -> windowed
		//  b) received focus -> fullscreen if a)
		if( ( focus != was_focused ) )
		{
			if( x11display.features.wmStateFullscreen )
			{
				if( !focus && Cvar_Value( "vid_fullscreen" ) )
				{
					go_fullscreen_on_focus = qtrue;
					Cbuf_ExecuteText( EXEC_APPEND, "vid_fullscreen 0\n" );
				}
				else if( focus && go_fullscreen_on_focus )
				{
					go_fullscreen_on_focus = qfalse;
					Cbuf_ExecuteText( EXEC_APPEND, "vid_fullscreen 1\n" );
				}
			}
		}
}