2014-08-24 17:41:41 -07:00
/*
2016-01-01 00:11:04 -08:00
* Copyright 2011 - 2016 Branimir Karadzic . All rights reserved .
* License : https : //github.com/bkaradzic/bgfx#license-bsd-2-clause
2014-08-24 17:41:41 -07:00
*/
# include "entry_p.h"
2016-01-04 18:08:46 +01:00
# if ENTRY_CONFIG_USE_NATIVE && (BX_PLATFORM_BSD || BX_PLATFORM_LINUX || BX_PLATFORM_RPI)
2014-08-24 17:41:41 -07:00
# define XK_MISCELLANY
# define XK_LATIN1
# include <X11/keysymdef.h>
2015-02-06 16:49:04 -08:00
# include <X11/Xlib.h> // will include X11 which #defines None... Don't mess with order of includes.
2015-09-18 20:16:24 -07:00
# include <bgfx/bgfxplatform.h>
2014-08-24 17:41:41 -07:00
# undef None
# include <bx/thread.h>
# include <bx/os.h>
2014-10-02 19:52:43 -07:00
# include <bx/handlealloc.h>
2014-08-24 17:41:41 -07:00
# include <string.h> // memset
2014-10-02 19:52:43 -07:00
# include <string>
2014-08-24 17:41:41 -07:00
2014-12-21 13:35:11 -08:00
# include <fcntl.h>
2014-08-24 17:41:41 -07:00
namespace entry
{
2014-12-21 13:35:11 -08:00
# define JS_EVENT_BUTTON 0x01 /* button pressed/released */
# define JS_EVENT_AXIS 0x02 /* joystick moved */
# define JS_EVENT_INIT 0x80 /* initial state of device */
struct JoystickEvent
{
uint32_t time ; /* event timestamp in milliseconds */
int16_t value ; /* value */
uint8_t type ; /* event type */
uint8_t number ; /* axis/button number */
} ;
static Key : : Enum s_translateButton [ ] =
{
Key : : GamepadA ,
Key : : GamepadB ,
Key : : GamepadX ,
Key : : GamepadY ,
Key : : GamepadShoulderL ,
Key : : GamepadShoulderR ,
Key : : GamepadBack ,
Key : : GamepadStart ,
Key : : GamepadGuide ,
Key : : GamepadThumbL ,
Key : : GamepadThumbR ,
} ;
static GamepadAxis : : Enum s_translateAxis [ ] =
{
GamepadAxis : : LeftX ,
GamepadAxis : : LeftY ,
GamepadAxis : : LeftZ ,
GamepadAxis : : RightX ,
GamepadAxis : : RightY ,
GamepadAxis : : RightZ ,
} ;
2016-01-23 17:09:28 -08:00
struct AxisDpadRemap
{
Key : : Enum first ;
Key : : Enum second ;
} ;
static AxisDpadRemap s_axisDpad [ ] =
{
{ Key : : GamepadLeft , Key : : GamepadRight } ,
{ Key : : GamepadUp , Key : : GamepadDown } ,
{ Key : : None , Key : : None } ,
{ Key : : GamepadLeft , Key : : GamepadRight } ,
{ Key : : GamepadUp , Key : : GamepadDown } ,
{ Key : : None , Key : : None } ,
} ;
BX_STATIC_ASSERT ( BX_COUNTOF ( s_translateAxis ) = = BX_COUNTOF ( s_axisDpad ) ) ;
2014-12-21 13:35:11 -08:00
struct Joystick
{
2015-06-14 17:29:17 -07:00
Joystick ( )
: m_fd ( - 1 )
{
}
2014-12-21 13:35:11 -08:00
void init ( )
{
m_fd = open ( " /dev/input/js0 " , O_RDONLY | O_NONBLOCK ) ;
memset ( m_value , 0 , sizeof ( m_value ) ) ;
// Deadzone values from xinput.h
m_deadzone [ GamepadAxis : : LeftX ] =
m_deadzone [ GamepadAxis : : LeftY ] = 7849 ;
m_deadzone [ GamepadAxis : : RightX ] =
m_deadzone [ GamepadAxis : : RightY ] = 8689 ;
m_deadzone [ GamepadAxis : : LeftZ ] =
m_deadzone [ GamepadAxis : : RightZ ] = 30 ;
}
void shutdown ( )
{
2015-06-14 17:29:17 -07:00
if ( - 1 ! = m_fd )
2014-12-21 13:35:11 -08:00
{
close ( m_fd ) ;
}
}
bool filter ( GamepadAxis : : Enum _axis , int32_t * _value )
{
const int32_t old = m_value [ _axis ] ;
const int32_t deadzone = m_deadzone [ _axis ] ;
int32_t value = * _value ;
value = value > deadzone | | value < - deadzone ? value : 0 ;
m_value [ _axis ] = value ;
* _value = value ;
return old ! = value ;
}
2014-12-25 09:27:51 -08:00
bool update ( EventQueue & _eventQueue )
2014-12-21 13:35:11 -08:00
{
2015-06-14 17:29:17 -07:00
if ( - 1 = = m_fd )
2014-12-21 13:35:11 -08:00
{
2014-12-25 09:27:51 -08:00
return false ;
}
2014-12-21 13:35:11 -08:00
2014-12-25 09:27:51 -08:00
JoystickEvent event ;
int32_t bytes = read ( m_fd , & event , sizeof ( JoystickEvent ) ) ;
if ( bytes ! = sizeof ( JoystickEvent ) )
{
return false ;
}
WindowHandle defaultWindow = { 0 } ;
GamepadHandle handle = { 0 } ;
2014-12-21 13:35:11 -08:00
2014-12-25 09:27:51 -08:00
if ( event . type & JS_EVENT_BUTTON )
{
if ( event . number < BX_COUNTOF ( s_translateButton ) )
2014-12-21 13:35:11 -08:00
{
2014-12-25 09:27:51 -08:00
_eventQueue . postKeyEvent ( defaultWindow , s_translateButton [ event . number ] , 0 , 0 ! = event . value ) ;
2014-12-21 13:35:11 -08:00
}
2014-12-25 09:27:51 -08:00
}
else if ( event . type & JS_EVENT_AXIS )
{
if ( event . number < BX_COUNTOF ( s_translateAxis ) )
2014-12-21 13:35:11 -08:00
{
2014-12-25 09:27:51 -08:00
GamepadAxis : : Enum axis = s_translateAxis [ event . number ] ;
int32_t value = event . value ;
if ( filter ( axis , & value ) )
2014-12-21 13:35:11 -08:00
{
2014-12-25 09:27:51 -08:00
_eventQueue . postAxisEvent ( defaultWindow , handle , axis , value ) ;
2016-01-23 17:09:28 -08:00
if ( Key : : None ! = s_axisDpad [ axis ] . first )
{
if ( m_value [ axis ] = = 0 )
{
_eventQueue . postKeyEvent ( defaultWindow , s_axisDpad [ axis ] . first , 0 , false ) ;
_eventQueue . postKeyEvent ( defaultWindow , s_axisDpad [ axis ] . second , 0 , false ) ;
}
else
{
_eventQueue . postKeyEvent ( defaultWindow
, 0 > m_value [ axis ] ? s_axisDpad [ axis ] . first : s_axisDpad [ axis ] . second
, 0
, true
) ;
}
}
2014-12-21 13:35:11 -08:00
}
}
}
2014-12-25 09:27:51 -08:00
return true ;
2014-12-21 13:35:11 -08:00
}
int m_fd ;
int32_t m_value [ GamepadAxis : : Count ] ;
int32_t m_deadzone [ GamepadAxis : : Count ] ;
} ;
static Joystick s_joystick ;
2014-08-24 17:41:41 -07:00
static uint8_t s_translateKey [ 512 ] ;
static void initTranslateKey ( uint16_t _xk , Key : : Enum _key )
{
_xk + = 256 ;
BX_CHECK ( _xk < BX_COUNTOF ( s_translateKey ) , " Out of bounds %d. " , _xk ) ;
s_translateKey [ _xk & 0x1ff ] = ( uint8_t ) _key ;
}
Key : : Enum fromXk ( uint16_t _xk )
{
_xk + = 256 ;
return 512 > _xk ? ( Key : : Enum ) s_translateKey [ _xk ] : Key : : None ;
}
struct MainThreadEntry
{
int m_argc ;
char * * m_argv ;
static int32_t threadFunc ( void * _userData ) ;
} ;
2014-10-02 19:52:43 -07:00
struct Msg
{
Msg ( )
: m_x ( 0 )
, m_y ( 0 )
, m_width ( 0 )
, m_height ( 0 )
, m_flags ( 0 )
{
}
int32_t m_x ;
int32_t m_y ;
uint32_t m_width ;
uint32_t m_height ;
uint32_t m_flags ;
std : : string m_title ;
} ;
2014-08-24 17:41:41 -07:00
struct Context
{
Context ( )
: m_modifiers ( Modifier : : None )
, m_exit ( false )
{
memset ( s_translateKey , 0 , sizeof ( s_translateKey ) ) ;
initTranslateKey ( XK_Escape , Key : : Esc ) ;
initTranslateKey ( XK_Return , Key : : Return ) ;
initTranslateKey ( XK_Tab , Key : : Tab ) ;
initTranslateKey ( XK_BackSpace , Key : : Backspace ) ;
initTranslateKey ( XK_space , Key : : Space ) ;
initTranslateKey ( XK_Up , Key : : Up ) ;
initTranslateKey ( XK_Down , Key : : Down ) ;
initTranslateKey ( XK_Left , Key : : Left ) ;
initTranslateKey ( XK_Right , Key : : Right ) ;
2015-05-30 13:11:18 -07:00
initTranslateKey ( XK_Insert , Key : : Insert ) ;
initTranslateKey ( XK_Delete , Key : : Delete ) ;
2014-08-24 17:41:41 -07:00
initTranslateKey ( XK_Home , Key : : Home ) ;
initTranslateKey ( XK_KP_End , Key : : End ) ;
2015-05-30 13:11:18 -07:00
initTranslateKey ( XK_Page_Up , Key : : PageUp ) ;
2015-05-30 18:00:24 -07:00
initTranslateKey ( XK_Page_Down , Key : : PageDown ) ;
2014-08-24 17:41:41 -07:00
initTranslateKey ( XK_Print , Key : : Print ) ;
initTranslateKey ( XK_equal , Key : : Plus ) ;
initTranslateKey ( XK_minus , Key : : Minus ) ;
2015-05-30 13:11:18 -07:00
initTranslateKey ( XK_bracketleft , Key : : LeftBracket ) ;
initTranslateKey ( XK_bracketright , Key : : RightBracket ) ;
initTranslateKey ( XK_semicolon , Key : : Semicolon ) ;
initTranslateKey ( XK_apostrophe , Key : : Quote ) ;
initTranslateKey ( XK_comma , Key : : Comma ) ;
initTranslateKey ( XK_period , Key : : Period ) ;
initTranslateKey ( XK_slash , Key : : Slash ) ;
initTranslateKey ( XK_backslash , Key : : Backslash ) ;
initTranslateKey ( XK_grave , Key : : Tilde ) ;
2014-08-24 17:41:41 -07:00
initTranslateKey ( XK_F1 , Key : : F1 ) ;
initTranslateKey ( XK_F2 , Key : : F2 ) ;
initTranslateKey ( XK_F3 , Key : : F3 ) ;
initTranslateKey ( XK_F4 , Key : : F4 ) ;
initTranslateKey ( XK_F5 , Key : : F5 ) ;
initTranslateKey ( XK_F6 , Key : : F6 ) ;
initTranslateKey ( XK_F7 , Key : : F7 ) ;
initTranslateKey ( XK_F8 , Key : : F8 ) ;
initTranslateKey ( XK_F9 , Key : : F9 ) ;
initTranslateKey ( XK_F10 , Key : : F10 ) ;
initTranslateKey ( XK_F11 , Key : : F11 ) ;
initTranslateKey ( XK_F12 , Key : : F12 ) ;
initTranslateKey ( XK_KP_Insert , Key : : NumPad0 ) ;
initTranslateKey ( XK_KP_End , Key : : NumPad1 ) ;
initTranslateKey ( XK_KP_Down , Key : : NumPad2 ) ;
initTranslateKey ( XK_KP_Page_Down , Key : : NumPad3 ) ;
initTranslateKey ( XK_KP_Left , Key : : NumPad4 ) ;
initTranslateKey ( XK_KP_Begin , Key : : NumPad5 ) ;
initTranslateKey ( XK_KP_Right , Key : : NumPad6 ) ;
initTranslateKey ( XK_KP_Home , Key : : NumPad7 ) ;
initTranslateKey ( XK_KP_Up , Key : : NumPad8 ) ;
initTranslateKey ( XK_KP_Page_Up , Key : : NumPad9 ) ;
initTranslateKey ( ' 0 ' , Key : : Key0 ) ;
initTranslateKey ( ' 1 ' , Key : : Key1 ) ;
initTranslateKey ( ' 2 ' , Key : : Key2 ) ;
initTranslateKey ( ' 3 ' , Key : : Key3 ) ;
initTranslateKey ( ' 4 ' , Key : : Key4 ) ;
initTranslateKey ( ' 5 ' , Key : : Key5 ) ;
initTranslateKey ( ' 6 ' , Key : : Key6 ) ;
initTranslateKey ( ' 7 ' , Key : : Key7 ) ;
initTranslateKey ( ' 8 ' , Key : : Key8 ) ;
initTranslateKey ( ' 9 ' , Key : : Key9 ) ;
initTranslateKey ( ' a ' , Key : : KeyA ) ;
initTranslateKey ( ' b ' , Key : : KeyB ) ;
initTranslateKey ( ' c ' , Key : : KeyC ) ;
initTranslateKey ( ' d ' , Key : : KeyD ) ;
initTranslateKey ( ' e ' , Key : : KeyE ) ;
initTranslateKey ( ' f ' , Key : : KeyF ) ;
initTranslateKey ( ' g ' , Key : : KeyG ) ;
initTranslateKey ( ' h ' , Key : : KeyH ) ;
initTranslateKey ( ' i ' , Key : : KeyI ) ;
initTranslateKey ( ' j ' , Key : : KeyJ ) ;
initTranslateKey ( ' k ' , Key : : KeyK ) ;
initTranslateKey ( ' l ' , Key : : KeyL ) ;
initTranslateKey ( ' m ' , Key : : KeyM ) ;
initTranslateKey ( ' n ' , Key : : KeyN ) ;
initTranslateKey ( ' o ' , Key : : KeyO ) ;
initTranslateKey ( ' p ' , Key : : KeyP ) ;
initTranslateKey ( ' q ' , Key : : KeyQ ) ;
initTranslateKey ( ' r ' , Key : : KeyR ) ;
initTranslateKey ( ' s ' , Key : : KeyS ) ;
initTranslateKey ( ' t ' , Key : : KeyT ) ;
initTranslateKey ( ' u ' , Key : : KeyU ) ;
initTranslateKey ( ' v ' , Key : : KeyV ) ;
initTranslateKey ( ' w ' , Key : : KeyW ) ;
initTranslateKey ( ' x ' , Key : : KeyX ) ;
initTranslateKey ( ' y ' , Key : : KeyY ) ;
initTranslateKey ( ' z ' , Key : : KeyZ ) ;
2015-03-02 16:54:22 +01:00
m_mx = 0 ;
m_my = 0 ;
m_mz = 0 ;
2014-08-24 17:41:41 -07:00
}
int32_t run ( int _argc , char * * _argv )
{
XInitThreads ( ) ;
m_display = XOpenDisplay ( 0 ) ;
int32_t screen = DefaultScreen ( m_display ) ;
2014-10-02 19:52:43 -07:00
m_depth = DefaultDepth ( m_display , screen ) ;
m_visual = DefaultVisual ( m_display , screen ) ;
m_root = RootWindow ( m_display , screen ) ;
2014-08-24 17:41:41 -07:00
2015-10-04 14:27:20 -07:00
memset ( & m_windowAttrs , 0 , sizeof ( m_windowAttrs ) ) ;
m_windowAttrs . background_pixmap = 0 ;
m_windowAttrs . border_pixel = 0 ;
m_windowAttrs . event_mask = 0
2014-08-24 17:41:41 -07:00
| ButtonPressMask
| ButtonReleaseMask
| ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
| StructureNotifyMask
;
2014-10-02 19:52:43 -07:00
m_windowAlloc . alloc ( ) ;
m_window [ 0 ] = XCreateWindow ( m_display
, m_root
2014-08-24 17:41:41 -07:00
, 0 , 0
2015-10-20 22:45:35 -07:00
, 1 , 1 , 0
2014-10-02 19:52:43 -07:00
, m_depth
2014-08-24 17:41:41 -07:00
, InputOutput
2014-10-02 19:52:43 -07:00
, m_visual
2014-08-24 17:41:41 -07:00
, CWBorderPixel | CWEventMask
2015-10-04 14:27:20 -07:00
, & m_windowAttrs
2014-08-24 17:41:41 -07:00
) ;
2014-09-22 20:37:49 -07:00
// Clear window to black.
XSetWindowAttributes attr ;
memset ( & attr , 0 , sizeof ( attr ) ) ;
2014-10-02 19:52:43 -07:00
XChangeWindowAttributes ( m_display , m_window [ 0 ] , CWBackPixel , & attr ) ;
2014-09-22 20:37:49 -07:00
const char * wmDeleteWindowName = " WM_DELETE_WINDOW " ;
2014-08-24 17:41:41 -07:00
Atom wmDeleteWindow ;
XInternAtoms ( m_display , ( char * * ) & wmDeleteWindowName , 1 , False , & wmDeleteWindow ) ;
2014-10-02 19:52:43 -07:00
XSetWMProtocols ( m_display , m_window [ 0 ] , & wmDeleteWindow , 1 ) ;
2014-08-24 17:41:41 -07:00
2014-10-02 19:52:43 -07:00
XMapWindow ( m_display , m_window [ 0 ] ) ;
XStoreName ( m_display , m_window [ 0 ] , " BGFX " ) ;
2014-08-24 17:41:41 -07:00
2015-10-03 09:37:09 -07:00
XIM im ;
im = XOpenIM ( m_display , NULL , NULL , NULL ) ;
XIC ic ;
ic = XCreateIC ( im
, XNInputStyle
, 0
| XIMPreeditNothing
| XIMStatusNothing
, XNClientWindow
, m_window [ 0 ]
, NULL
2015-10-04 14:32:54 -07:00
) ;
2015-10-03 09:37:09 -07:00
2014-09-22 20:37:49 -07:00
//
2014-10-02 19:52:43 -07:00
bgfx : : x11SetDisplayWindow ( m_display , m_window [ 0 ] ) ;
2014-08-24 17:41:41 -07:00
MainThreadEntry mte ;
mte . m_argc = _argc ;
mte . m_argv = _argv ;
bx : : Thread thread ;
thread . init ( mte . threadFunc , & mte ) ;
2014-09-19 08:57:35 -07:00
WindowHandle defaultWindow = { 0 } ;
2015-10-20 22:45:35 -07:00
m_eventQueue . postSizeEvent ( defaultWindow , 1 , 1 ) ;
2014-09-19 08:57:35 -07:00
2014-12-21 13:35:11 -08:00
s_joystick . init ( ) ;
2014-08-24 17:41:41 -07:00
while ( ! m_exit )
{
2014-12-25 09:27:51 -08:00
bool joystick = s_joystick . update ( m_eventQueue ) ;
bool xpending = XPending ( m_display ) ;
2014-12-21 13:35:11 -08:00
2014-12-25 09:27:51 -08:00
if ( ! xpending )
{
bx : : sleep ( joystick ? 8 : 16 ) ;
}
else
2014-08-24 17:41:41 -07:00
{
XEvent event ;
XNextEvent ( m_display , & event ) ;
switch ( event . type )
{
case Expose :
break ;
case ClientMessage :
2014-09-22 20:37:49 -07:00
if ( ( Atom ) event . xclient . data . l [ 0 ] = = wmDeleteWindow )
2014-08-24 17:41:41 -07:00
{
m_eventQueue . postExitEvent ( ) ;
}
break ;
case ButtonPress :
case ButtonRelease :
{
const XButtonEvent & xbutton = event . xbutton ;
2015-03-02 16:54:22 +01:00
MouseButton : : Enum mb = MouseButton : : None ;
2014-08-24 17:41:41 -07:00
switch ( xbutton . button )
{
case Button1 : mb = MouseButton : : Left ; break ;
case Button2 : mb = MouseButton : : Middle ; break ;
case Button3 : mb = MouseButton : : Right ; break ;
2015-03-02 16:54:22 +01:00
case Button4 : + + m_mz ; break ;
case Button5 : - - m_mz ; break ;
2014-08-24 17:41:41 -07:00
}
2015-03-02 16:54:22 +01:00
WindowHandle handle = findHandle ( xbutton . window ) ;
2014-08-24 17:41:41 -07:00
if ( MouseButton : : None ! = mb )
{
2014-10-02 19:52:43 -07:00
m_eventQueue . postMouseEvent ( handle
2014-09-19 08:57:35 -07:00
, xbutton . x
2014-08-24 17:41:41 -07:00
, xbutton . y
, 0
, mb
, event . type = = ButtonPress
) ;
}
2015-03-02 16:54:22 +01:00
else
{
m_eventQueue . postMouseEvent ( handle
, m_mx
, m_my
, m_mz
) ;
}
2014-08-24 17:41:41 -07:00
}
break ;
case MotionNotify :
{
const XMotionEvent & xmotion = event . xmotion ;
2014-10-02 19:52:43 -07:00
WindowHandle handle = findHandle ( xmotion . window ) ;
2015-03-02 16:54:22 +01:00
m_mx = xmotion . x ;
m_my = xmotion . y ;
2014-10-02 19:52:43 -07:00
m_eventQueue . postMouseEvent ( handle
2015-03-02 16:54:22 +01:00
, m_mx
, m_my
, m_mz
2014-08-24 17:41:41 -07:00
) ;
}
break ;
case KeyPress :
case KeyRelease :
{
XKeyEvent & xkey = event . xkey ;
KeySym keysym = XLookupKeysym ( & xkey , 0 ) ;
switch ( keysym )
{
case XK_Meta_L : setModifier ( Modifier : : LeftMeta , KeyPress = = event . type ) ; break ;
case XK_Meta_R : setModifier ( Modifier : : RightMeta , KeyPress = = event . type ) ; break ;
case XK_Control_L : setModifier ( Modifier : : LeftCtrl , KeyPress = = event . type ) ; break ;
case XK_Control_R : setModifier ( Modifier : : RightCtrl , KeyPress = = event . type ) ; break ;
case XK_Shift_L : setModifier ( Modifier : : LeftShift , KeyPress = = event . type ) ; break ;
case XK_Shift_R : setModifier ( Modifier : : RightShift , KeyPress = = event . type ) ; break ;
case XK_Alt_L : setModifier ( Modifier : : LeftAlt , KeyPress = = event . type ) ; break ;
case XK_Alt_R : setModifier ( Modifier : : RightAlt , KeyPress = = event . type ) ; break ;
default :
{
2015-10-03 09:37:09 -07:00
WindowHandle handle = findHandle ( xkey . window ) ;
if ( KeyPress = = event . type )
{
Status status = 0 ;
uint8_t utf8 [ 4 ] ;
int len = Xutf8LookupString ( ic , & xkey , ( char * ) utf8 , sizeof ( utf8 ) , & keysym , & status ) ;
switch ( status )
{
case XLookupChars :
case XLookupBoth :
if ( 0 ! = len )
{
m_eventQueue . postCharEvent ( handle , len , utf8 ) ;
}
break ;
2015-10-03 09:59:01 -07:00
default :
break ;
2015-10-03 09:37:09 -07:00
}
}
2014-08-24 17:41:41 -07:00
Key : : Enum key = fromXk ( keysym ) ;
if ( Key : : None ! = key )
{
2014-10-02 19:52:43 -07:00
m_eventQueue . postKeyEvent ( handle , key , m_modifiers , KeyPress = = event . type ) ;
2014-08-24 17:41:41 -07:00
}
}
break ;
}
}
break ;
2015-04-26 12:42:51 -07:00
case ConfigureNotify :
2014-08-24 17:41:41 -07:00
{
2015-04-26 12:42:51 -07:00
const XConfigureEvent & xev = event . xconfigure ;
WindowHandle handle = findHandle ( xev . window ) ;
2014-10-02 19:52:43 -07:00
if ( isValid ( handle ) )
{
2015-04-26 12:42:51 -07:00
m_eventQueue . postSizeEvent ( handle , xev . width , xev . height ) ;
2014-10-02 19:52:43 -07:00
}
2014-08-24 17:41:41 -07:00
}
break ;
}
}
}
thread . shutdown ( ) ;
2014-12-21 13:35:11 -08:00
s_joystick . shutdown ( ) ;
2015-10-03 09:59:01 -07:00
XDestroyIC ( ic ) ;
XCloseIM ( im ) ;
2014-10-02 19:52:43 -07:00
XUnmapWindow ( m_display , m_window [ 0 ] ) ;
XDestroyWindow ( m_display , m_window [ 0 ] ) ;
2014-08-24 17:41:41 -07:00
2015-06-09 22:24:49 -07:00
return thread . getExitCode ( ) ;
2014-08-24 17:41:41 -07:00
}
void setModifier ( Modifier : : Enum _modifier , bool _set )
{
m_modifiers & = ~ _modifier ;
m_modifiers | = _set ? _modifier : 0 ;
}
2014-10-02 19:52:43 -07:00
void createWindow ( WindowHandle _handle , Msg * msg )
{
Window window = XCreateWindow ( m_display
, m_root
, msg - > m_x
, msg - > m_y
, msg - > m_width
, msg - > m_height
, 0
, m_depth
, InputOutput
, m_visual
, CWBorderPixel | CWEventMask
2015-10-04 14:27:20 -07:00
, & m_windowAttrs
2014-10-02 19:52:43 -07:00
) ;
m_window [ _handle . idx ] = window ;
// Clear window to black.
XSetWindowAttributes attr ;
memset ( & attr , 0 , sizeof ( attr ) ) ;
XChangeWindowAttributes ( m_display , window , CWBackPixel , & attr ) ;
const char * wmDeleteWindowName = " WM_DELETE_WINDOW " ;
Atom wmDeleteWindow ;
XInternAtoms ( m_display , ( char * * ) & wmDeleteWindowName , 1 , False , & wmDeleteWindow ) ;
XSetWMProtocols ( m_display , window , & wmDeleteWindow , 1 ) ;
XMapWindow ( m_display , window ) ;
XStoreName ( m_display , window , msg - > m_title . c_str ( ) ) ;
m_eventQueue . postSizeEvent ( _handle , msg - > m_width , msg - > m_height ) ;
union cast
{
void * p ;
: : Window w ;
} ;
cast c ;
c . w = window ;
m_eventQueue . postWindowEvent ( _handle , c . p ) ;
delete msg ;
}
WindowHandle findHandle ( Window _window )
{
bx : : LwMutexScope scope ( m_lock ) ;
for ( uint32_t ii = 0 , num = m_windowAlloc . getNumHandles ( ) ; ii < num ; + + ii )
{
uint16_t idx = m_windowAlloc . getHandleAt ( ii ) ;
if ( _window = = m_window [ idx ] )
{
WindowHandle handle = { idx } ;
return handle ;
}
}
WindowHandle invalid = { UINT16_MAX } ;
return invalid ;
}
2014-08-24 17:41:41 -07:00
uint8_t m_modifiers ;
bool m_exit ;
2015-03-02 16:54:22 +01:00
int32_t m_mx ;
int32_t m_my ;
int32_t m_mz ;
2014-08-24 17:41:41 -07:00
EventQueue m_eventQueue ;
2014-10-02 19:52:43 -07:00
bx : : LwMutex m_lock ;
bx : : HandleAllocT < ENTRY_CONFIG_MAX_WINDOWS > m_windowAlloc ;
int32_t m_depth ;
Visual * m_visual ;
Window m_root ;
2015-10-04 14:27:20 -07:00
XSetWindowAttributes m_windowAttrs ;
2014-10-02 19:52:43 -07:00
Display * m_display ;
Window m_window [ ENTRY_CONFIG_MAX_WINDOWS ] ;
uint32_t m_flags [ ENTRY_CONFIG_MAX_WINDOWS ] ;
2014-08-24 17:41:41 -07:00
} ;
static Context s_ctx ;
int32_t MainThreadEntry : : threadFunc ( void * _userData )
{
MainThreadEntry * self = ( MainThreadEntry * ) _userData ;
int32_t result = main ( self - > m_argc , self - > m_argv ) ;
s_ctx . m_exit = true ;
return result ;
}
const Event * poll ( )
{
return s_ctx . m_eventQueue . poll ( ) ;
}
2014-09-22 19:34:10 -07:00
const Event * poll ( WindowHandle _handle )
{
return s_ctx . m_eventQueue . poll ( _handle ) ;
}
2014-08-24 17:41:41 -07:00
void release ( const Event * _event )
{
s_ctx . m_eventQueue . release ( _event ) ;
}
2014-09-22 19:34:10 -07:00
WindowHandle createWindow ( int32_t _x , int32_t _y , uint32_t _width , uint32_t _height , uint32_t _flags , const char * _title )
{
2014-10-02 19:52:43 -07:00
bx : : LwMutexScope scope ( s_ctx . m_lock ) ;
WindowHandle handle = { s_ctx . m_windowAlloc . alloc ( ) } ;
if ( isValid ( handle ) )
{
Msg * msg = new Msg ;
msg - > m_x = _x ;
msg - > m_y = _y ;
msg - > m_width = _width ;
msg - > m_height = _height ;
msg - > m_title = _title ;
msg - > m_flags = _flags ;
s_ctx . createWindow ( handle , msg ) ;
}
2014-09-22 19:34:10 -07:00
return handle ;
}
void destroyWindow ( WindowHandle _handle )
{
2014-10-02 20:10:12 -07:00
if ( isValid ( _handle ) )
2014-10-02 19:52:43 -07:00
{
s_ctx . m_eventQueue . postWindowEvent ( _handle , NULL ) ;
XUnmapWindow ( s_ctx . m_display , s_ctx . m_window [ _handle . idx ] ) ;
XDestroyWindow ( s_ctx . m_display , s_ctx . m_window [ _handle . idx ] ) ;
bx : : LwMutexScope scope ( s_ctx . m_lock ) ;
s_ctx . m_windowAlloc . free ( _handle . idx ) ;
}
2014-09-22 19:34:10 -07:00
}
void setWindowPos ( WindowHandle _handle , int32_t _x , int32_t _y )
{
2015-10-04 14:27:20 -07:00
Display * display = s_ctx . m_display ;
Window window = s_ctx . m_window [ _handle . idx ] ;
XMoveWindow ( display , window , _x , _y ) ;
2014-09-22 19:34:10 -07:00
}
2014-09-19 08:57:35 -07:00
void setWindowSize ( WindowHandle _handle , uint32_t _width , uint32_t _height )
2014-08-24 17:41:41 -07:00
{
2015-10-04 14:27:20 -07:00
Display * display = s_ctx . m_display ;
Window window = s_ctx . m_window [ _handle . idx ] ;
XResizeWindow ( display , window , int32_t ( _width ) , int32_t ( _height ) ) ;
2014-08-24 17:41:41 -07:00
}
2014-09-19 08:57:35 -07:00
void setWindowTitle ( WindowHandle _handle , const char * _title )
2014-08-24 17:41:41 -07:00
{
2015-10-04 14:27:20 -07:00
Display * display = s_ctx . m_display ;
Window window = s_ctx . m_window [ _handle . idx ] ;
XStoreName ( display , window , _title ) ;
2014-08-24 17:41:41 -07:00
}
2014-09-19 08:57:35 -07:00
void toggleWindowFrame ( WindowHandle _handle )
2014-08-24 17:41:41 -07:00
{
2014-09-19 08:57:35 -07:00
BX_UNUSED ( _handle ) ;
2014-08-24 17:41:41 -07:00
}
2015-03-07 23:38:48 +01:00
void toggleFullscreen ( WindowHandle _handle )
{
BX_UNUSED ( _handle ) ;
}
2014-09-19 08:57:35 -07:00
void setMouseLock ( WindowHandle _handle , bool _lock )
2014-08-24 17:41:41 -07:00
{
2014-09-19 08:57:35 -07:00
BX_UNUSED ( _handle , _lock ) ;
2014-08-24 17:41:41 -07:00
}
} // namespace entry
int main ( int _argc , char * * _argv )
{
using namespace entry ;
return s_ctx . run ( _argc , _argv ) ;
}
2016-01-04 18:08:46 +01:00
# endif // ENTRY_CONFIG_USE_NATIVE && (BX_PLATFORM_BSD || BX_PLATFORM_LINUX || BX_PLATFORM_RPI)