too many changes to list, many regressions were made, master will be UNSTABLE for a few days
This commit is contained in:
		
							parent
							
								
									19eb56997d
								
							
						
					
					
						commit
						f548825faf
					
				| 
						 | 
					@ -5,7 +5,7 @@ PROJECT(otclient)
 | 
				
			||||||
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
 | 
					SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OPTION(USE_PCH "Use precompiled header" ON)
 | 
					OPTION(USE_PCH "Use precompiled header" ON)
 | 
				
			||||||
OPTION(NO_CONSOLE "Disable console window on Windows" OFF)
 | 
					OPTION(NO_CONSOLE "Disable console window on Windows platform" OFF)
 | 
				
			||||||
OPTION(HANDLE_EXCEPTIONS "Generate crash reports" OFF)
 | 
					OPTION(HANDLE_EXCEPTIONS "Generate crash reports" OFF)
 | 
				
			||||||
OPTION(FORBIDDEN_FUNCTIONS "Enable forbidden lua functions" ON)
 | 
					OPTION(FORBIDDEN_FUNCTIONS "Enable forbidden lua functions" ON)
 | 
				
			||||||
OPTION(USE_OPENGLES2 "Use OpenGL ES 2.0 (for mobiles devices)" OFF)
 | 
					OPTION(USE_OPENGLES2 "Use OpenGL ES 2.0 (for mobiles devices)" OFF)
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ MESSAGE(STATUS "BUILD TYPE: " ${CMAKE_BUILD_TYPE})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# setup compiler options
 | 
					# setup compiler options
 | 
				
			||||||
IF(CMAKE_COMPILER_IS_GNUCXX)
 | 
					IF(CMAKE_COMPILER_IS_GNUCXX)
 | 
				
			||||||
    SET(CXX_WARNS "-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-unused-variable -Wno-switch")
 | 
					    SET(CXX_WARNS "-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-unused-variable -Wno-switch -Wno-missing-field-initializers")
 | 
				
			||||||
    SET(CMAKE_CXX_FLAGS "-std=gnu++0x -pipe ${CXX_WARNS}")
 | 
					    SET(CMAKE_CXX_FLAGS "-std=gnu++0x -pipe ${CXX_WARNS}")
 | 
				
			||||||
    SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -ggdb3 -fno-inline")
 | 
					    SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -ggdb3 -fno-inline")
 | 
				
			||||||
    SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
 | 
					    SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
 | 
				
			||||||
| 
						 | 
					@ -68,9 +68,9 @@ SET(SOURCES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # otclient
 | 
					    # otclient
 | 
				
			||||||
    src/otclient/otclient.cpp
 | 
					    src/otclient/otclient.cpp
 | 
				
			||||||
 | 
					    src/otclient/luafunctions.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # otclient luascript
 | 
					    # otclient luascript
 | 
				
			||||||
    src/otclient/luascript/luafunctions.cpp
 | 
					 | 
				
			||||||
    src/otclient/luascript/luavaluecasts.cpp
 | 
					    src/otclient/luascript/luavaluecasts.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # otclient core
 | 
					    # otclient core
 | 
				
			||||||
| 
						 | 
					@ -99,6 +99,10 @@ SET(SOURCES
 | 
				
			||||||
    src/otclient/net/protocolgamesend.cpp
 | 
					    src/otclient/net/protocolgamesend.cpp
 | 
				
			||||||
    src/otclient/net/protocolgameparse.cpp
 | 
					    src/otclient/net/protocolgameparse.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # framework
 | 
				
			||||||
 | 
					    src/framework/application.cpp
 | 
				
			||||||
 | 
					    src/framework/luafunctions.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # framework third party
 | 
					    # framework third party
 | 
				
			||||||
    src/framework/thirdparty/apngloader.cpp
 | 
					    src/framework/thirdparty/apngloader.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,9 +122,11 @@ SET(SOURCES
 | 
				
			||||||
    src/framework/core/eventdispatcher.cpp
 | 
					    src/framework/core/eventdispatcher.cpp
 | 
				
			||||||
    src/framework/core/modulemanager.cpp
 | 
					    src/framework/core/modulemanager.cpp
 | 
				
			||||||
    src/framework/core/module.cpp
 | 
					    src/framework/core/module.cpp
 | 
				
			||||||
    src/framework/core/engine.cpp
 | 
					 | 
				
			||||||
    src/framework/core/clock.cpp
 | 
					    src/framework/core/clock.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # framework platform
 | 
				
			||||||
 | 
					    src/framework/platform/platformwindow.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # framework graphics
 | 
					    # framework graphics
 | 
				
			||||||
    src/framework/graphics/font.cpp
 | 
					    src/framework/graphics/font.cpp
 | 
				
			||||||
    src/framework/graphics/fontmanager.cpp
 | 
					    src/framework/graphics/fontmanager.cpp
 | 
				
			||||||
| 
						 | 
					@ -144,7 +150,6 @@ SET(SOURCES
 | 
				
			||||||
    src/framework/luascript/luainterface.cpp
 | 
					    src/framework/luascript/luainterface.cpp
 | 
				
			||||||
    src/framework/luascript/luaobject.cpp
 | 
					    src/framework/luascript/luaobject.cpp
 | 
				
			||||||
    src/framework/luascript/luaexception.cpp
 | 
					    src/framework/luascript/luaexception.cpp
 | 
				
			||||||
    src/framework/luascript/luafunctions.cpp
 | 
					 | 
				
			||||||
    src/framework/luascript/luavaluecasts.cpp
 | 
					    src/framework/luascript/luavaluecasts.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # framework ui
 | 
					    # framework ui
 | 
				
			||||||
| 
						 | 
					@ -172,7 +177,7 @@ IF(FORBIDDEN_FUNCTIONS)
 | 
				
			||||||
ENDIF(FORBIDDEN_FUNCTIONS)
 | 
					ENDIF(FORBIDDEN_FUNCTIONS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IF(WIN32)
 | 
					IF(WIN32)
 | 
				
			||||||
    SET(SOURCES ${SOURCES} src/framework/platform/win32platform.cpp)
 | 
					    SET(SOURCES ${SOURCES} src/framework/platform/win32window.cpp)
 | 
				
			||||||
    SET(ADDITIONAL_LIBRARIES ws2_32 mswsock)
 | 
					    SET(ADDITIONAL_LIBRARIES ws2_32 mswsock)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IF(CMAKE_COMPILER_IS_GNUCXX)
 | 
					    IF(CMAKE_COMPILER_IS_GNUCXX)
 | 
				
			||||||
| 
						 | 
					@ -180,7 +185,6 @@ IF(WIN32)
 | 
				
			||||||
    ENDIF(CMAKE_COMPILER_IS_GNUCXX)
 | 
					    ENDIF(CMAKE_COMPILER_IS_GNUCXX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IF(NO_CONSOLE)
 | 
					    IF(NO_CONSOLE)
 | 
				
			||||||
        ADD_DEFINITIONS(-DWIN32_NO_CONSOLE)
 | 
					 | 
				
			||||||
        IF(CMAKE_COMPILER_IS_GNUCXX)
 | 
					        IF(CMAKE_COMPILER_IS_GNUCXX)
 | 
				
			||||||
            SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -mwindows")
 | 
					            SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -mwindows")
 | 
				
			||||||
        ENDIF(CMAKE_COMPILER_IS_GNUCXX)
 | 
					        ENDIF(CMAKE_COMPILER_IS_GNUCXX)
 | 
				
			||||||
| 
						 | 
					@ -195,7 +199,7 @@ IF(WIN32)
 | 
				
			||||||
ELSE(WIN32)
 | 
					ELSE(WIN32)
 | 
				
			||||||
    SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -rdynamic")
 | 
					    SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -rdynamic")
 | 
				
			||||||
    SET(ADDITIONAL_LIBRARIES pthread)
 | 
					    SET(ADDITIONAL_LIBRARIES pthread)
 | 
				
			||||||
    SET(SOURCES ${SOURCES} src/framework/platform/x11platform.cpp)
 | 
					    SET(SOURCES ${SOURCES} src/framework/platform/x11window.cpp)
 | 
				
			||||||
ENDIF(WIN32)
 | 
					ENDIF(WIN32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# target executable
 | 
					# target executable
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								TODO
								
								
								
								
							
							
						
						
									
										14
									
								
								TODO
								
								
								
								
							| 
						 | 
					@ -14,3 +14,17 @@ fix moving windows and tooltips conflicts
 | 
				
			||||||
todo display otclient icon in window bar
 | 
					todo display otclient icon in window bar
 | 
				
			||||||
remake otui styles states system
 | 
					remake otui styles states system
 | 
				
			||||||
padding
 | 
					padding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rename Game to g_game, etc
 | 
				
			||||||
 | 
					implement Console key binding
 | 
				
			||||||
 | 
					fatal error if sprite load fails
 | 
				
			||||||
 | 
					impl vertical sync, clipboard
 | 
				
			||||||
 | 
					crash handler
 | 
				
			||||||
 | 
					modify COnnection::poll()
 | 
				
			||||||
 | 
					setOnClose
 | 
				
			||||||
 | 
					review and reenable some warnings
 | 
				
			||||||
 | 
					make lua/c++ logger more friendly
 | 
				
			||||||
 | 
					bind every global lua function in a static class
 | 
				
			||||||
 | 
					use metatable for Point,Rect,Color,Size lua classes
 | 
				
			||||||
 | 
					lua binder generator
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ local function completeCommand()
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function onKeyPress(widget, keyCode, keyChar, keyboardModifiers)
 | 
					local function onKeyPress(widget, keyCode, keyText, keyboardModifiers)
 | 
				
			||||||
  if keyboardModifiers == KeyboardNoModifier then
 | 
					  if keyboardModifiers == KeyboardNoModifier then
 | 
				
			||||||
    -- execute current command
 | 
					    -- execute current command
 | 
				
			||||||
    if keyCode == KeyReturn or keyCode == keyEnter then
 | 
					    if keyCode == KeyReturn or keyCode == keyEnter then
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Color = {}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Point = {}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Rect = {}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Size = {}
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ local loadBox
 | 
				
			||||||
local characterList
 | 
					local characterList
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- private functions
 | 
					-- private functions
 | 
				
			||||||
local function onCharactersWindowKeyPress(self, keyCode, keyChar, keyboardModifiers)
 | 
					local function onCharactersWindowKeyPress(self, keyCode, keyText, keyboardModifiers)
 | 
				
			||||||
  if keyboardModifiers == KeyboardNoModifier then
 | 
					  if keyboardModifiers == KeyboardNoModifier then
 | 
				
			||||||
    if keyCode == KeyUp or keyCode == KeyTab then
 | 
					    if keyCode == KeyUp or keyCode == KeyTab then
 | 
				
			||||||
      characterList:focusPreviousChild(ActiveFocusReason)
 | 
					      characterList:focusPreviousChild(ActiveFocusReason)
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ local function tryLogin(charInfo, tries)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  -- save last used character
 | 
					  -- save last used character
 | 
				
			||||||
  ConfigManager.set('lastUsedCharacter', charInfo.characterName)
 | 
					  g_configs.set('lastUsedCharacter', charInfo.characterName)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- public functions
 | 
					-- public functions
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ function CharacterList.create(characters, premDays)
 | 
				
			||||||
    label.worldHost = worldHost
 | 
					    label.worldHost = worldHost
 | 
				
			||||||
    label.worldPort = worldIp
 | 
					    label.worldPort = worldIp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if i == 1 or ConfigManager.get('lastUsedCharacter') == characterName then
 | 
					    if i == 1 or g_configs.get('lastUsedCharacter') == characterName then
 | 
				
			||||||
      characterList:focusChild(label, ActiveFocusReason)
 | 
					      characterList:focusChild(label, ActiveFocusReason)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,8 +11,8 @@ local function clearAccountFields()
 | 
				
			||||||
  enterGame:getChildById('accountNameLineEdit'):clearText()
 | 
					  enterGame:getChildById('accountNameLineEdit'):clearText()
 | 
				
			||||||
  enterGame:getChildById('accountPasswordLineEdit'):clearText()
 | 
					  enterGame:getChildById('accountPasswordLineEdit'):clearText()
 | 
				
			||||||
  enterGame:getChildById('accountNameLineEdit'):focus()
 | 
					  enterGame:getChildById('accountNameLineEdit'):focus()
 | 
				
			||||||
  ConfigManager.set('account', nil)
 | 
					  g_configs.set('account', nil)
 | 
				
			||||||
  ConfigManager.set('password', nil)
 | 
					  g_configs.set('password', nil)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function onError(protocol, error)
 | 
					local function onError(protocol, error)
 | 
				
			||||||
| 
						 | 
					@ -30,9 +30,9 @@ end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function onCharacterList(protocol, characters, premDays)
 | 
					local function onCharacterList(protocol, characters, premDays)
 | 
				
			||||||
  if enterGame:getChildById('rememberPasswordBox'):isChecked() then
 | 
					  if enterGame:getChildById('rememberPasswordBox'):isChecked() then
 | 
				
			||||||
    ConfigManager.set('account', EnterGame.account)
 | 
					    g_configs.set('account', EnterGame.account)
 | 
				
			||||||
    ConfigManager.set('password', EnterGame.password)
 | 
					    g_configs.set('password', EnterGame.password)
 | 
				
			||||||
    ConfigManager.set('autologin', tostring(enterGame:getChildById('autoLoginBox'):isChecked()))
 | 
					    g_configs.set('autologin', tostring(enterGame:getChildById('autoLoginBox'):isChecked()))
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    clearAccountFields()
 | 
					    clearAccountFields()
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					@ -40,9 +40,9 @@ local function onCharacterList(protocol, characters, premDays)
 | 
				
			||||||
  loadBox:destroy()
 | 
					  loadBox:destroy()
 | 
				
			||||||
  CharacterList.create(characters, premDays)
 | 
					  CharacterList.create(characters, premDays)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local lastMotdNumber = tonumber(ConfigManager.get("motd"))
 | 
					  local lastMotdNumber = tonumber(g_configs.get("motd"))
 | 
				
			||||||
  if motdNumber and motdNumber ~= lastMotdNumber then
 | 
					  if motdNumber and motdNumber ~= lastMotdNumber then
 | 
				
			||||||
    ConfigManager.set("motd", motdNumber)
 | 
					    g_configs.set("motd", motdNumber)
 | 
				
			||||||
    local motdBox = displayInfoBox("Message of the day", motdMessage)
 | 
					    local motdBox = displayInfoBox("Message of the day", motdMessage)
 | 
				
			||||||
    motdBox.onOk = CharacterList.show
 | 
					    motdBox.onOk = CharacterList.show
 | 
				
			||||||
    CharacterList.hide()
 | 
					    CharacterList.hide()
 | 
				
			||||||
| 
						 | 
					@ -53,11 +53,11 @@ end
 | 
				
			||||||
function EnterGame.create()
 | 
					function EnterGame.create()
 | 
				
			||||||
  enterGame = UI.display('entergame.otui')
 | 
					  enterGame = UI.display('entergame.otui')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local account = ConfigManager.get('account')
 | 
					  local account = g_configs.get('account')
 | 
				
			||||||
  local password = ConfigManager.get('password')
 | 
					  local password = g_configs.get('password')
 | 
				
			||||||
  local host = ConfigManager.get('host')
 | 
					  local host = g_configs.get('host')
 | 
				
			||||||
  local port = tonumber(ConfigManager.get('port'))
 | 
					  local port = tonumber(g_configs.get('port'))
 | 
				
			||||||
  local autologin = toboolean(ConfigManager.get('autologin'))
 | 
					  local autologin = toboolean(g_configs.get('autologin'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  enterGame:getChildById('accountNameLineEdit'):setText(account)
 | 
					  enterGame:getChildById('accountNameLineEdit'):setText(account)
 | 
				
			||||||
  enterGame:getChildById('accountPasswordLineEdit'):setText(password)
 | 
					  enterGame:getChildById('accountPasswordLineEdit'):setText(password)
 | 
				
			||||||
| 
						 | 
					@ -93,8 +93,8 @@ function EnterGame.doLogin()
 | 
				
			||||||
  EnterGame.port = enterGame:getChildById('serverPortLineEdit'):getText()
 | 
					  EnterGame.port = enterGame:getChildById('serverPortLineEdit'):getText()
 | 
				
			||||||
  EnterGame.hide()
 | 
					  EnterGame.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ConfigManager.set('host', EnterGame.host)
 | 
					  g_configs.set('host', EnterGame.host)
 | 
				
			||||||
  ConfigManager.set('port', EnterGame.port)
 | 
					  g_configs.set('port', EnterGame.port)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  local protocolLogin = ProtocolLogin.create()
 | 
					  local protocolLogin = ProtocolLogin.create()
 | 
				
			||||||
  protocolLogin.onError = onError
 | 
					  protocolLogin.onError = onError
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
-- private functions
 | 
					-- private functions
 | 
				
			||||||
local function onGameKeyPress(self, keyCode, keyChar, keyboardModifiers)
 | 
					local function onGameKeyPress(self, keyCode, keyText, keyboardModifiers)
 | 
				
			||||||
  if keyboardModifiers == KeyboardCtrlModifier then
 | 
					  if keyboardModifiers == KeyboardCtrlModifier then
 | 
				
			||||||
    if keyCode == KeyG then
 | 
					    if keyCode == KeyG then
 | 
				
			||||||
      CharacterList.show()
 | 
					      CharacterList.show()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,8 +6,8 @@ local fpsEnabled = false
 | 
				
			||||||
local vsyncEnabled = false
 | 
					local vsyncEnabled = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getConfig(name, default)
 | 
					function getConfig(name, default)
 | 
				
			||||||
  if ConfigManager.exists(name) then
 | 
					  if g_configs.exists(name) then
 | 
				
			||||||
    local val = string.trim(ConfigManager.get(name))
 | 
					    local val = string.trim(g_configs.get(name))
 | 
				
			||||||
    if val == 'true' or val == 'false' then
 | 
					    if val == 'true' or val == 'false' then
 | 
				
			||||||
      return toboolean(val)
 | 
					      return toboolean(val)
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ function getConfig(name, default)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    if default ~= nil then
 | 
					    if default ~= nil then
 | 
				
			||||||
      ConfigManager.set(name, default)
 | 
					      g_configs.set(name, default)
 | 
				
			||||||
      return default
 | 
					      return default
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      return nil
 | 
					      return nil
 | 
				
			||||||
| 
						 | 
					@ -24,13 +24,13 @@ function getConfig(name, default)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setConfig(name, value)
 | 
					function setConfig(name, value)
 | 
				
			||||||
  ConfigManager.set(name, tostring(value))
 | 
					  g_configs.set(name, tostring(value))
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- private functions
 | 
					-- private functions
 | 
				
			||||||
function Options.enableVsync(on)
 | 
					function Options.enableVsync(on)
 | 
				
			||||||
  vsyncEnabled = on
 | 
					  vsyncEnabled = on
 | 
				
			||||||
  setVerticalSync(on)
 | 
					  g_window.setVerticalSync(on)
 | 
				
			||||||
  setConfig('vsync', on)
 | 
					  setConfig('vsync', on)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					OTClient = { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- TODO: load and save configurations
 | 
				
			||||||
 | 
					function OTClient.init()
 | 
				
			||||||
 | 
					  g_window.move({ x=220, y=220 })
 | 
				
			||||||
 | 
					  g_window.resize({ width=800, height=600 })
 | 
				
			||||||
 | 
					  g_window.setTitle('OTClient')
 | 
				
			||||||
 | 
					  g_window.setIcon('otcicon.png')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  addEvent(g_window.show)
 | 
				
			||||||
 | 
					  return true
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function OTClient.terminate()
 | 
				
			||||||
 | 
					  g_window.hide()
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,8 @@ Module
 | 
				
			||||||
  description: Load all other otclient modules
 | 
					  description: Load all other otclient modules
 | 
				
			||||||
  author: OTClient team
 | 
					  author: OTClient team
 | 
				
			||||||
  website: https://github.com/edubart/otclient
 | 
					  website: https://github.com/edubart/otclient
 | 
				
			||||||
 | 
					  autoLoad: true
 | 
				
			||||||
 | 
					  autoLoadPriority: 10
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    - core
 | 
					    - core
 | 
				
			||||||
    - background
 | 
					    - background
 | 
				
			||||||
| 
						 | 
					@ -16,3 +18,10 @@ Module
 | 
				
			||||||
    - chat
 | 
					    - chat
 | 
				
			||||||
    - outfit
 | 
					    - outfit
 | 
				
			||||||
    - tibiafiles
 | 
					    - tibiafiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onLoad: |
 | 
				
			||||||
 | 
					    require 'otclient'
 | 
				
			||||||
 | 
					    return OTClient.init()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onUnload: |
 | 
				
			||||||
 | 
					    OTClient.terminate()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,9 +5,9 @@ local currentToolTip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- private functions
 | 
					-- private functions
 | 
				
			||||||
local function moveToolTip(tooltip)
 | 
					local function moveToolTip(tooltip)
 | 
				
			||||||
  local pos = getMouseCursorPos()
 | 
					  local pos = g_window.getMousePos()
 | 
				
			||||||
  pos.y = pos.y + 1
 | 
					  pos.y = pos.y + 1
 | 
				
			||||||
  local xdif = getScreenSize().width - (pos.x + tooltip:getWidth())
 | 
					  local xdif = g_window.getSize().width - (pos.x + tooltip:getWidth())
 | 
				
			||||||
  if xdif < 2 then
 | 
					  if xdif < 2 then
 | 
				
			||||||
    pos.x = pos.x - tooltip:getWidth() - 3
 | 
					    pos.x = pos.x - tooltip:getWidth() - 3
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ Module
 | 
				
			||||||
  author: OTClient team
 | 
					  author: OTClient team
 | 
				
			||||||
  website: https://github.com/edubart/otclient
 | 
					  website: https://github.com/edubart/otclient
 | 
				
			||||||
  autoLoad: true
 | 
					  autoLoad: true
 | 
				
			||||||
 | 
					  autoLoadPriority: 2
 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    - core
 | 
					    - core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,207 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "application.h"
 | 
				
			||||||
 | 
					#include <framework/core/clock.h>
 | 
				
			||||||
 | 
					#include <framework/core/resourcemanager.h>
 | 
				
			||||||
 | 
					#include <framework/core/modulemanager.h>
 | 
				
			||||||
 | 
					#include <framework/core/eventdispatcher.h>
 | 
				
			||||||
 | 
					#include <framework/core/configmanager.h>
 | 
				
			||||||
 | 
					#include <framework/net/connection.h>
 | 
				
			||||||
 | 
					#include <framework/platform/platformwindow.h>
 | 
				
			||||||
 | 
					#include <framework/ui/uimanager.h>
 | 
				
			||||||
 | 
					#include <framework/ui/uiwidget.h>
 | 
				
			||||||
 | 
					#include <framework/graphics/graphics.h>
 | 
				
			||||||
 | 
					#include <framework/luascript/luainterface.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void exitSignalHandler(int sig)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static bool signaled = false;
 | 
				
			||||||
 | 
					    switch(sig) {
 | 
				
			||||||
 | 
					        case SIGTERM:
 | 
				
			||||||
 | 
					        case SIGINT:
 | 
				
			||||||
 | 
					            if(!signaled) {
 | 
				
			||||||
 | 
					                signaled = true;
 | 
				
			||||||
 | 
					                g_dispatcher.addEvent(std::bind(&Application::close, &g_app));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::init(const std::string& appName, const std::vector<std::string>& args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    logInfo("Starting application...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_pollCycleDelay = POLL_CYCLE_DELAY;
 | 
				
			||||||
 | 
					    m_appName = appName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // capture exit signals
 | 
				
			||||||
 | 
					    signal(SIGTERM, exitSignalHandler);
 | 
				
			||||||
 | 
					    signal(SIGINT, exitSignalHandler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initialize lua
 | 
				
			||||||
 | 
					    g_lua.init();
 | 
				
			||||||
 | 
					    registerLuaFunctions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initialize resources
 | 
				
			||||||
 | 
					    g_resources.init(args[0].c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // loads user configuration
 | 
				
			||||||
 | 
					    if(!g_configs.load("config.otml"))
 | 
				
			||||||
 | 
					        logInfo("Using default configurations.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initialize the ui
 | 
				
			||||||
 | 
					    g_ui.init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // setup platform window
 | 
				
			||||||
 | 
					    g_window.init();
 | 
				
			||||||
 | 
					    g_window.setOnResize(std::bind(&Application::resize, this, _1));
 | 
				
			||||||
 | 
					    g_window.setOnInputEvent(std::bind(&Application::inputEvent, this, _1));
 | 
				
			||||||
 | 
					    g_window.setOnClose(std::bind(&Application::close, this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initialize graphics
 | 
				
			||||||
 | 
					    g_graphics.init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // fire first resize
 | 
				
			||||||
 | 
					    resize(g_window.getSize());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // auto load lua modules
 | 
				
			||||||
 | 
					    g_modules.discoverAndLoadModules();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::terminate()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // hide the window because there is no render anymore
 | 
				
			||||||
 | 
					    g_window.hide();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // run modules unload events
 | 
				
			||||||
 | 
					    g_modules.unloadModules();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // release remaining lua object references
 | 
				
			||||||
 | 
					    g_lua.collectGarbage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // poll remaining events
 | 
				
			||||||
 | 
					    poll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // terminate ui
 | 
				
			||||||
 | 
					    g_ui.terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // terminate network
 | 
				
			||||||
 | 
					    Connection::terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // flush remaining dispatcher events
 | 
				
			||||||
 | 
					    g_dispatcher.flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // terminate graphics
 | 
				
			||||||
 | 
					    g_graphics.terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // save configurations
 | 
				
			||||||
 | 
					    g_configs.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // release resources
 | 
				
			||||||
 | 
					    g_resources.terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // terminate script environment
 | 
				
			||||||
 | 
					    g_lua.terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // release platform window
 | 
				
			||||||
 | 
					    g_window.terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    logInfo("Application ended successfully.");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::run()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ticks_t lastPollTicks = g_clock.updateTicks();
 | 
				
			||||||
 | 
					    m_stopping = false;
 | 
				
			||||||
 | 
					    m_running = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // run the first poll
 | 
				
			||||||
 | 
					    poll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(g_ui.getRootWidget()->getChildCount() == 0) {
 | 
				
			||||||
 | 
					        logError("There is no root widgets to display, the app will close");
 | 
				
			||||||
 | 
					        m_stopping = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while(!m_stopping) {
 | 
				
			||||||
 | 
					        g_clock.updateTicks();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // poll events every POLL_CYCLE_DELAY
 | 
				
			||||||
 | 
					        // this delay exists to avoid massive polling thus increasing framerate
 | 
				
			||||||
 | 
					        if(g_clock.ticksElapsed(lastPollTicks) >= m_pollCycleDelay) {
 | 
				
			||||||
 | 
					            poll();
 | 
				
			||||||
 | 
					            lastPollTicks = g_clock.ticks();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(g_window.isVisible()) {
 | 
				
			||||||
 | 
					            g_graphics.beginRender();
 | 
				
			||||||
 | 
					            render();
 | 
				
			||||||
 | 
					            g_graphics.endRender();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // update screen pixels
 | 
				
			||||||
 | 
					            g_window.swapBuffers();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // sleeps until next poll to avoid massive cpu usage
 | 
				
			||||||
 | 
					            g_clock.sleep(POLL_CYCLE_DELAY+1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_stopping = false;
 | 
				
			||||||
 | 
					    m_running = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::exit()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    logInfo("Exiting application..");
 | 
				
			||||||
 | 
					    m_stopping = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::poll()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // poll input events
 | 
				
			||||||
 | 
					    g_window.poll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // poll network events
 | 
				
			||||||
 | 
					    Connection::poll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // poll application genareted events
 | 
				
			||||||
 | 
					    g_dispatcher.poll();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::render()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // everything is rendered by UI components
 | 
				
			||||||
 | 
					    g_ui.render();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::resize(const Size& size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_graphics.resize(size);
 | 
				
			||||||
 | 
					    g_ui.resize(size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Application::inputEvent(const InputEvent& event)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_ui.inputEvent(event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,64 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef APPLICATION_H
 | 
				
			||||||
 | 
					#define APPLICATION_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <framework/core/inputevent.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Application
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    enum {
 | 
				
			||||||
 | 
					        POLL_CYCLE_DELAY = 10
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    virtual void init(const std::string& appName, const std::vector<std::string>& args);
 | 
				
			||||||
 | 
					    virtual void registerLuaFunctions();
 | 
				
			||||||
 | 
					    virtual void terminate();
 | 
				
			||||||
 | 
					    virtual void run();
 | 
				
			||||||
 | 
					    virtual void exit();
 | 
				
			||||||
 | 
					    virtual void poll();
 | 
				
			||||||
 | 
					    virtual void close() { exit(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void setPollCycleDelay(int delay) { m_pollCycleDelay = delay; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool isRunning() { return m_running; }
 | 
				
			||||||
 | 
					    bool isStopping() { return m_stopping; }
 | 
				
			||||||
 | 
					    std::string getAppName() { return m_appName; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					    virtual void render();
 | 
				
			||||||
 | 
					    virtual void resize(const Size& size);
 | 
				
			||||||
 | 
					    virtual void inputEvent(const InputEvent& event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    std::string m_appName;
 | 
				
			||||||
 | 
					    int m_pollCycleDelay;
 | 
				
			||||||
 | 
					    Boolean<false> m_running;
 | 
				
			||||||
 | 
					    Boolean<false> m_stopping;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern Application& g_app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -225,6 +225,16 @@ namespace Fw
 | 
				
			||||||
        OtherFocusReason
 | 
					        OtherFocusReason
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum InputEventType {
 | 
				
			||||||
 | 
					        NoInputEvent = 0,
 | 
				
			||||||
 | 
					        KeyPressInputEvent,
 | 
				
			||||||
 | 
					        KeyReleaseInputEvent,
 | 
				
			||||||
 | 
					        MousePressInputEvent,
 | 
				
			||||||
 | 
					        MouseReleaseInputEvent,
 | 
				
			||||||
 | 
					        MouseMoveInputEvent,
 | 
				
			||||||
 | 
					        MouseWheelInputEvent
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enum MouseButton {
 | 
					    enum MouseButton {
 | 
				
			||||||
        MouseNoButton = 0,
 | 
					        MouseNoButton = 0,
 | 
				
			||||||
        MouseLeftButton,
 | 
					        MouseLeftButton,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,14 +22,18 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "clock.h"
 | 
					#include "clock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// for usleep
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Clock g_clock;
 | 
					Clock g_clock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Clock::Clock()
 | 
					Clock::Clock()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    m_startupTime = std::chrono::high_resolution_clock::now();
 | 
					    m_startupTime = std::chrono::high_resolution_clock::now();
 | 
				
			||||||
 | 
					    m_currentTicks = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int Clock::updateTicks()
 | 
					ticks_t Clock::updateTicks()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto timeNow = std::chrono::high_resolution_clock::now();
 | 
					    auto timeNow = std::chrono::high_resolution_clock::now();
 | 
				
			||||||
    m_currentTicks = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow - m_startupTime).count();
 | 
					    m_currentTicks = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow - m_startupTime).count();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,15 +30,15 @@ class Clock
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    Clock();
 | 
					    Clock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int updateTicks();
 | 
					    ticks_t updateTicks();
 | 
				
			||||||
    void sleep(int ms);
 | 
					    void sleep(int ms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int ticks() { return m_currentTicks; }
 | 
					    ticks_t ticks() { return m_currentTicks; }
 | 
				
			||||||
    int ticksElapsed(int prevTicks) { return ticks() - prevTicks; }
 | 
					    ticks_t ticksElapsed(long prevTicks) { return ticks() - prevTicks; }
 | 
				
			||||||
    int ticksFor(int delay) { return ticks() + delay; }
 | 
					    ticks_t ticksFor(int delay) { return ticks() + delay; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    int m_currentTicks;
 | 
					    ticks_t m_currentTicks;
 | 
				
			||||||
    std::chrono::system_clock::time_point m_startupTime;
 | 
					    std::chrono::system_clock::time_point m_startupTime;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,9 +26,9 @@
 | 
				
			||||||
#include "declarations.h"
 | 
					#include "declarations.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ScheduledEvent {
 | 
					struct ScheduledEvent {
 | 
				
			||||||
    ScheduledEvent(int ticks, const SimpleCallback& callback) : ticks(ticks), callback(callback) { }
 | 
					    ScheduledEvent(ticks_t ticks, const SimpleCallback& callback) : ticks(ticks), callback(callback) { }
 | 
				
			||||||
    bool operator<(const ScheduledEvent& other) const { return ticks > other.ticks; }
 | 
					    bool operator<(const ScheduledEvent& other) const { return ticks > other.ticks; }
 | 
				
			||||||
    int ticks;
 | 
					    ticks_t ticks;
 | 
				
			||||||
    SimpleCallback callback;
 | 
					    SimpleCallback callback;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,20 +20,20 @@
 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef PLATFORMLISTENER_H
 | 
					#ifndef INPUTEVENT_H
 | 
				
			||||||
#define PLATFORMLISTENER_H
 | 
					#define INPUTEVENT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "platformevent.h"
 | 
					#include "declarations.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PlatformListener
 | 
					struct InputEvent {
 | 
				
			||||||
{
 | 
					    Fw::InputEventType type;
 | 
				
			||||||
public:
 | 
					    Fw::MouseWheelDirection wheelDirection;
 | 
				
			||||||
    /// Fired when user tries to close the window
 | 
					    Fw::MouseButton mouseButton;
 | 
				
			||||||
    virtual void onClose() = 0;
 | 
					    int keyboardModifiers;
 | 
				
			||||||
    /// Fired when user resize the window
 | 
					    std::string keyText;
 | 
				
			||||||
    virtual void onResize(const Size& size) = 0;
 | 
					    Fw::Key keyCode;
 | 
				
			||||||
    /// Fired when user press a key or move the mouse
 | 
					    Point mousePos;
 | 
				
			||||||
    virtual void onPlatformEvent(const PlatformEvent& event) = 0;
 | 
					    Point mouseMoved;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "logger.h"
 | 
					#include "logger.h"
 | 
				
			||||||
#include "eventdispatcher.h"
 | 
					#include "eventdispatcher.h"
 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Logger g_logger;
 | 
					Logger g_logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,11 @@
 | 
				
			||||||
#include <framework/otml/otml.h>
 | 
					#include <framework/otml/otml.h>
 | 
				
			||||||
#include <framework/luascript/luainterface.h>
 | 
					#include <framework/luascript/luainterface.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Module::Module(const std::string& name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_name = name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Module::discover(const OTMLNodePtr& moduleNode)
 | 
					void Module::discover(const OTMLNodePtr& moduleNode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const static std::string none = "none";
 | 
					    const static std::string none = "none";
 | 
				
			||||||
| 
						 | 
					@ -34,6 +39,7 @@ void Module::discover(const OTMLNodePtr& moduleNode)
 | 
				
			||||||
    m_website = moduleNode->valueAt("website", none);
 | 
					    m_website = moduleNode->valueAt("website", none);
 | 
				
			||||||
    m_version = moduleNode->valueAt("version", none);
 | 
					    m_version = moduleNode->valueAt("version", none);
 | 
				
			||||||
    m_autoLoad = moduleNode->valueAt<bool>("autoLoad", false);
 | 
					    m_autoLoad = moduleNode->valueAt<bool>("autoLoad", false);
 | 
				
			||||||
 | 
					    m_autoLoadPriority = moduleNode->valueAt<int>("autoLoadPriority", 100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(OTMLNodePtr node = moduleNode->get("dependencies")) {
 | 
					    if(OTMLNodePtr node = moduleNode->get("dependencies")) {
 | 
				
			||||||
        for(const OTMLNodePtr& tmp : node->children())
 | 
					        for(const OTMLNodePtr& tmp : node->children())
 | 
				
			||||||
| 
						 | 
					@ -57,6 +63,9 @@ void Module::discover(const OTMLNodePtr& moduleNode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Module::load()
 | 
					bool Module::load()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    if(m_loaded)
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(const std::string& depName : m_dependencies) {
 | 
					    for(const std::string& depName : m_dependencies) {
 | 
				
			||||||
        ModulePtr dep = g_modules.getModule(depName);
 | 
					        ModulePtr dep = g_modules.getModule(depName);
 | 
				
			||||||
        if(!dep) {
 | 
					        if(!dep) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@
 | 
				
			||||||
class Module
 | 
					class Module
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    Module(const std::string& name) : m_loaded(false), m_autoLoad(false), m_name(name) { }
 | 
					    Module(const std::string& name);
 | 
				
			||||||
    void discover(const OTMLNodePtr& moduleNode);
 | 
					    void discover(const OTMLNodePtr& moduleNode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool load();
 | 
					    bool load();
 | 
				
			||||||
| 
						 | 
					@ -43,11 +43,13 @@ public:
 | 
				
			||||||
    std::string getAuthor() { return m_author; }
 | 
					    std::string getAuthor() { return m_author; }
 | 
				
			||||||
    std::string getWebsite() { return m_website; }
 | 
					    std::string getWebsite() { return m_website; }
 | 
				
			||||||
    std::string getVersion() { return m_version; }
 | 
					    std::string getVersion() { return m_version; }
 | 
				
			||||||
    bool autoLoad() { return m_autoLoad; }
 | 
					    bool isAutoLoad() { return m_autoLoad; }
 | 
				
			||||||
 | 
					    int getAutoLoadPriority() { return m_autoLoadPriority; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    bool m_loaded;
 | 
					    Boolean<false> m_loaded;
 | 
				
			||||||
    bool m_autoLoad;
 | 
					    Boolean<false> m_autoLoad;
 | 
				
			||||||
 | 
					    int m_autoLoadPriority;
 | 
				
			||||||
    std::string m_name;
 | 
					    std::string m_name;
 | 
				
			||||||
    std::string m_description;
 | 
					    std::string m_description;
 | 
				
			||||||
    std::string m_author;
 | 
					    std::string m_author;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,29 +29,32 @@ ModuleManager g_modules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ModuleManager::discoverAndLoadModules()
 | 
					void ModuleManager::discoverAndLoadModules()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    std::multimap<int, ModulePtr> m_autoLoadModules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto moduleDirs = g_resources.listDirectoryFiles("/");
 | 
					    auto moduleDirs = g_resources.listDirectoryFiles("/");
 | 
				
			||||||
    for(const std::string& moduleDir : moduleDirs) {
 | 
					    for(const std::string& moduleDir : moduleDirs) {
 | 
				
			||||||
        auto moduleFiles = g_resources.listDirectoryFiles("/" + moduleDir);
 | 
					        auto moduleFiles = g_resources.listDirectoryFiles("/" + moduleDir);
 | 
				
			||||||
        for(const std::string& file : moduleFiles) {
 | 
					        for(const std::string& moduleFile : moduleFiles) {
 | 
				
			||||||
            if(boost::ends_with(file, ".otmod"))
 | 
					            if(boost::ends_with(moduleFile, ".otmod")) {
 | 
				
			||||||
                discoverModule("/" + moduleDir + "/" + file);
 | 
					                ModulePtr module = discoverModule("/" + moduleDir + "/" + moduleFile);
 | 
				
			||||||
 | 
					                if(module && module->isAutoLoad())
 | 
				
			||||||
 | 
					                    m_autoLoadModules.insert(make_pair(module->getAutoLoadPriority(), module));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // auto load modules
 | 
					    for(auto& pair : m_autoLoadModules) {
 | 
				
			||||||
    for(const ModulePtr& module : m_modules) {
 | 
					        ModulePtr module = pair.second;
 | 
				
			||||||
        if(!module->isLoaded() && module->autoLoad()) {
 | 
					        if(!module->isLoaded() && !module->load())
 | 
				
			||||||
            if(!module->load())
 | 
					 | 
				
			||||||
            logFatal("A required module has failed to load, cannot continue to run.");
 | 
					            logFatal("A required module has failed to load, cannot continue to run.");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ModuleManager::discoverModule(const std::string& file)
 | 
					ModulePtr ModuleManager::discoverModule(const std::string& moduleFile)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ModulePtr module;
 | 
					    ModulePtr module;
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        OTMLDocumentPtr doc = OTMLDocument::parse(file);
 | 
					        OTMLDocumentPtr doc = OTMLDocument::parse(moduleFile);
 | 
				
			||||||
        OTMLNodePtr moduleNode = doc->at("Module");
 | 
					        OTMLNodePtr moduleNode = doc->at("Module");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string name = moduleNode->valueAt("name");
 | 
					        std::string name = moduleNode->valueAt("name");
 | 
				
			||||||
| 
						 | 
					@ -62,10 +65,9 @@ bool ModuleManager::discoverModule(const std::string& file)
 | 
				
			||||||
        module->discover(moduleNode);
 | 
					        module->discover(moduleNode);
 | 
				
			||||||
        m_modules.push_back(module);
 | 
					        m_modules.push_back(module);
 | 
				
			||||||
    } catch(Exception& e) {
 | 
					    } catch(Exception& e) {
 | 
				
			||||||
        logError("Unable to discover module from file '", file, "': ", e.what());
 | 
					        logError("Unable to discover module from file '", moduleFile, "': ", e.what());
 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return true;
 | 
					    return module;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ModuleManager::unloadModules()
 | 
					void ModuleManager::unloadModules()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ class ModuleManager
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    void discoverAndLoadModules();
 | 
					    void discoverAndLoadModules();
 | 
				
			||||||
    bool discoverModule(const std::string& file);
 | 
					    ModulePtr discoverModule(const std::string& moduleFile);
 | 
				
			||||||
    void unloadModules();
 | 
					    void unloadModules();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ModulePtr getModule(const std::string& moduleName);
 | 
					    ModulePtr getModule(const std::string& moduleName);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,24 +22,28 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "resourcemanager.h"
 | 
					#include "resourcemanager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					#include <framework/application.h>
 | 
				
			||||||
#include <framework/luascript/luainterface.h>
 | 
					#include <framework/luascript/luainterface.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <physfs.h>
 | 
					#include <physfs.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ResourceManager g_resources;
 | 
					ResourceManager g_resources;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ResourceManager::init(const char* argv0, const char *appName)
 | 
					void ResourceManager::init(const char *argv0)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PHYSFS_init(argv0);
 | 
					    PHYSFS_init(argv0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // try to find modules directory, all data lives there
 | 
					    // setup write directory
 | 
				
			||||||
    std::string baseDir = PHYSFS_getBaseDir();
 | 
					    if(!g_resources.setupWriteDir())
 | 
				
			||||||
 | 
					        logError("Could not setup write directory");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // try to find modules directory, all data lives there
 | 
				
			||||||
 | 
					    //TODO: move this to Application class
 | 
				
			||||||
 | 
					    std::string baseDir = PHYSFS_getBaseDir();
 | 
				
			||||||
    std::string possibleDirs[] = { "modules",
 | 
					    std::string possibleDirs[] = { "modules",
 | 
				
			||||||
                                   baseDir + "modules",
 | 
					                                   baseDir + "modules",
 | 
				
			||||||
                                   baseDir + "../modules",
 | 
					                                   baseDir + "../modules",
 | 
				
			||||||
                                   baseDir + "../share/" + appName + "/otclient/modules",
 | 
					                                   baseDir + "../share/" + g_app.getAppName() + "/otclient/modules",
 | 
				
			||||||
                                   "" };
 | 
					                                   "" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool found = false;
 | 
					    bool found = false;
 | 
				
			||||||
| 
						 | 
					@ -52,14 +56,7 @@ void ResourceManager::init(const char* argv0, const char *appName)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(!found)
 | 
					    if(!found)
 | 
				
			||||||
        logFatal("Could not find modules directory.");
 | 
					        logFatal("Could not find modules directory");
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // setup write directory
 | 
					 | 
				
			||||||
    std::string dir = g_platform.getAppUserDir();
 | 
					 | 
				
			||||||
    if(g_resources.setWriteDir(dir))
 | 
					 | 
				
			||||||
        g_resources.addToSearchPath(dir);
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        logError("could not setup write directory");
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ResourceManager::terminate()
 | 
					void ResourceManager::terminate()
 | 
				
			||||||
| 
						 | 
					@ -67,10 +64,22 @@ void ResourceManager::terminate()
 | 
				
			||||||
    PHYSFS_deinit();
 | 
					    PHYSFS_deinit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ResourceManager::setWriteDir(const std::string& path)
 | 
					bool ResourceManager::setupWriteDir()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(!PHYSFS_setWriteDir(path.c_str()))
 | 
					    std::string userDir = PHYSFS_getUserDir();
 | 
				
			||||||
 | 
					    std::string dirName = Fw::mkstr(".", g_app.getAppName());
 | 
				
			||||||
 | 
					    std::string writeDir = userDir + dirName;
 | 
				
			||||||
 | 
					    if(!PHYSFS_setWriteDir(writeDir.c_str())) {
 | 
				
			||||||
 | 
					        if(!PHYSFS_setWriteDir(userDir.c_str()))
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					        if(!PHYSFS_mkdir(dirName.c_str())) {
 | 
				
			||||||
 | 
					            PHYSFS_setWriteDir(NULL);
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(!PHYSFS_setWriteDir(writeDir.c_str()))
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    addToSearchPath(writeDir);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,7 +106,7 @@ bool ResourceManager::fileExists(const std::string& fileName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ResourceManager::directoryExists(const std::string& directoryName)
 | 
					bool ResourceManager::directoryExists(const std::string& directoryName)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return (PHYSFS_exists(resolvePath(directoryName).c_str()) && PHYSFS_isDirectory(resolvePath(directoryName).c_str()));
 | 
					    return (PHYSFS_isDirectory(resolvePath(directoryName).c_str()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ResourceManager::loadFile(const std::string& fileName, std::iostream& out)
 | 
					void ResourceManager::loadFile(const std::string& fileName, std::iostream& out)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,11 +28,10 @@
 | 
				
			||||||
class ResourceManager
 | 
					class ResourceManager
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    void init(const char* argv0, const char *appName);
 | 
					    void init(const char *argv0);
 | 
				
			||||||
    void terminate();
 | 
					    void terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Set output files directory
 | 
					    bool setupWriteDir();
 | 
				
			||||||
    bool setWriteDir(const std::string& path);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Add an package or directory to the search path
 | 
					    /// Add an package or directory to the search path
 | 
				
			||||||
    bool addToSearchPath(const std::string& path, bool insertInFront = true);
 | 
					    bool addToSearchPath(const std::string& path, bool insertInFront = true);
 | 
				
			||||||
| 
						 | 
					@ -55,6 +54,7 @@ public:
 | 
				
			||||||
    std::list<std::string> listDirectoryFiles(const std::string& directoryPath = "");
 | 
					    std::list<std::string> listDirectoryFiles(const std::string& directoryPath = "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string resolvePath(const std::string& path);
 | 
					    std::string resolvePath(const std::string& path);
 | 
				
			||||||
 | 
					    std::string getAppUserPath();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern ResourceManager g_resources;
 | 
					extern ResourceManager g_resources;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@
 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
#include <ctime>
 | 
					#include <ctime>
 | 
				
			||||||
#include <cmath>
 | 
					#include <cmath>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <csignal>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// common STL headers
 | 
					// common STL headers
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,11 +23,8 @@
 | 
				
			||||||
#include "animatedtexture.h"
 | 
					#include "animatedtexture.h"
 | 
				
			||||||
#include "graphics.h"
 | 
					#include "graphics.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					 | 
				
			||||||
#include <framework/core/eventdispatcher.h>
 | 
					#include <framework/core/eventdispatcher.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <GL/gl.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay) :
 | 
					AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay) :
 | 
				
			||||||
    Texture(),
 | 
					    Texture(),
 | 
				
			||||||
    m_numFrames(numFrames)
 | 
					    m_numFrames(numFrames)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ private:
 | 
				
			||||||
    std::vector<int> m_framesDelay;
 | 
					    std::vector<int> m_framesDelay;
 | 
				
			||||||
    int m_numFrames;
 | 
					    int m_numFrames;
 | 
				
			||||||
    int m_currentFrame;
 | 
					    int m_currentFrame;
 | 
				
			||||||
    int m_lastAnimCheckTicks;
 | 
					    ticks_t m_lastAnimCheckTicks;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@
 | 
				
			||||||
#define FRAMEWORK_GRAPHICS_DECLARATIONS_H
 | 
					#define FRAMEWORK_GRAPHICS_DECLARATIONS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <framework/global.h>
 | 
					#include <framework/global.h>
 | 
				
			||||||
 | 
					#include "glutil.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Texture;
 | 
					class Texture;
 | 
				
			||||||
class AnimatedTexture;
 | 
					class AnimatedTexture;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,17 +24,6 @@
 | 
				
			||||||
#include "graphics.h"
 | 
					#include "graphics.h"
 | 
				
			||||||
#include "texture.h"
 | 
					#include "texture.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <GL/gl.h>
 | 
					 | 
				
			||||||
#include <GL/glext.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PFNGLGENFRAMEBUFFERSPROC         oglGenFramebuffers = 0;
 | 
					 | 
				
			||||||
PFNGLBINDFRAMEBUFFERPROC         oglBindFramebuffer = 0;
 | 
					 | 
				
			||||||
PFNGLFRAMEBUFFERTEXTURE2DPROC    oglFramebufferTexture2D = 0;
 | 
					 | 
				
			||||||
PFNGLDELETEFRAMEBUFFERSPROC      oglDeleteFramebuffers = 0;
 | 
					 | 
				
			||||||
PFNGLCHECKFRAMEBUFFERSTATUSPROC  oglCheckFramebufferStatus = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FrameBuffer::FrameBuffer(int width, int height)
 | 
					FrameBuffer::FrameBuffer(int width, int height)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    m_fbo = 0;
 | 
					    m_fbo = 0;
 | 
				
			||||||
| 
						 | 
					@ -46,22 +35,15 @@ FrameBuffer::FrameBuffer(int width, int height)
 | 
				
			||||||
    // use FBO ext only if supported
 | 
					    // use FBO ext only if supported
 | 
				
			||||||
    if(g_graphics.isExtensionSupported("GL_ARB_framebuffer_object")) {
 | 
					    if(g_graphics.isExtensionSupported("GL_ARB_framebuffer_object")) {
 | 
				
			||||||
        m_fallbackOldImp = false;
 | 
					        m_fallbackOldImp = false;
 | 
				
			||||||
        if(!oglGenFramebuffers) {
 | 
					 | 
				
			||||||
            oglGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)g_platform.getExtensionProcAddress("glGenFramebuffers");
 | 
					 | 
				
			||||||
            oglBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)g_platform.getExtensionProcAddress("glBindFramebuffer");
 | 
					 | 
				
			||||||
            oglFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)g_platform.getExtensionProcAddress("glFramebufferTexture2D");
 | 
					 | 
				
			||||||
            oglDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)g_platform.getExtensionProcAddress("glDeleteFramebuffers");
 | 
					 | 
				
			||||||
            oglCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)g_platform.getExtensionProcAddress("glCheckFramebufferStatus");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // generate FBO
 | 
					        // generate FBO
 | 
				
			||||||
        oglGenFramebuffers(1, &m_fbo);
 | 
					        glGenFramebuffers(1, &m_fbo);
 | 
				
			||||||
        oglBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
 | 
					        glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // attach 2D texture to this FBO
 | 
					        // attach 2D texture to this FBO
 | 
				
			||||||
        oglFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->getId(), 0);
 | 
					        glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->getId(), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        GLenum status = oglCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
 | 
					        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
 | 
				
			||||||
        switch(status) {
 | 
					        switch(status) {
 | 
				
			||||||
            case GL_FRAMEBUFFER_COMPLETE_EXT:
 | 
					            case GL_FRAMEBUFFER_COMPLETE_EXT:
 | 
				
			||||||
                //ok
 | 
					                //ok
 | 
				
			||||||
| 
						 | 
					@ -72,7 +54,7 @@ FrameBuffer::FrameBuffer(int width, int height)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // restore back buffer
 | 
					        // restore back buffer
 | 
				
			||||||
        oglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
 | 
					        glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
 | 
				
			||||||
        glDrawBuffer(GL_BACK);
 | 
					        glDrawBuffer(GL_BACK);
 | 
				
			||||||
        glReadBuffer(GL_BACK);
 | 
					        glReadBuffer(GL_BACK);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -87,14 +69,14 @@ FrameBuffer::FrameBuffer(int width, int height)
 | 
				
			||||||
FrameBuffer::~FrameBuffer()
 | 
					FrameBuffer::~FrameBuffer()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(m_fbo)
 | 
					    if(m_fbo)
 | 
				
			||||||
        oglDeleteFramebuffers(1, &m_fbo);
 | 
					        glDeleteFramebuffers(1, &m_fbo);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void FrameBuffer::bind()
 | 
					void FrameBuffer::bind()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(!m_fallbackOldImp) {
 | 
					    if(!m_fallbackOldImp) {
 | 
				
			||||||
        // bind framebuffer
 | 
					        // bind framebuffer
 | 
				
			||||||
        oglBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
 | 
					        glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        int screenWidth = g_graphics.getScreenSize().width();
 | 
					        int screenWidth = g_graphics.getScreenSize().width();
 | 
				
			||||||
        int screenHeight = g_graphics.getScreenSize().height();
 | 
					        int screenHeight = g_graphics.getScreenSize().height();
 | 
				
			||||||
| 
						 | 
					@ -126,7 +108,7 @@ void FrameBuffer::unbind()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(!m_fallbackOldImp) {
 | 
					    if(!m_fallbackOldImp) {
 | 
				
			||||||
        // bind back buffer again
 | 
					        // bind back buffer again
 | 
				
			||||||
        oglBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
 | 
					        glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
 | 
				
			||||||
        glDrawBuffer(GL_BACK);
 | 
					        glDrawBuffer(GL_BACK);
 | 
				
			||||||
        glReadBuffer(GL_BACK);
 | 
					        glReadBuffer(GL_BACK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,13 +31,8 @@ public:
 | 
				
			||||||
    FrameBuffer(int width, int height);
 | 
					    FrameBuffer(int width, int height);
 | 
				
			||||||
    virtual ~FrameBuffer();
 | 
					    virtual ~FrameBuffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Binds the framebuffer, by switching render buffer to itself, everything rendered will be draw on it
 | 
					 | 
				
			||||||
    void bind();
 | 
					    void bind();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Unbinds the framebuffer (switch render buffer to back buffer again)
 | 
					 | 
				
			||||||
    void unbind();
 | 
					    void unbind();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Draws framebuffer texture
 | 
					 | 
				
			||||||
    void draw(const Rect& screenCoords, const Rect& framebufferCoords = Rect());
 | 
					    void draw(const Rect& screenCoords, const Rect& framebufferCoords = Rect());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TexturePtr getTexture() { return m_texture; }
 | 
					    TexturePtr getTexture() { return m_texture; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GLUTIL_H
 | 
				
			||||||
 | 
					#define GLUTIL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GL_GLEXT_PROTOTYPES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					#include <GL/gl.h>
 | 
				
			||||||
 | 
					#include <GL/glext.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include <GLES2/gl2.h>
 | 
				
			||||||
 | 
					#include <GLES2/gl2ext.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -25,9 +25,6 @@
 | 
				
			||||||
#include <framework/graphics/graphics.h>
 | 
					#include <framework/graphics/graphics.h>
 | 
				
			||||||
#include <framework/graphics/texture.h>
 | 
					#include <framework/graphics/texture.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <GL/gl.h>
 | 
					 | 
				
			||||||
#include <GL/glext.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Graphics g_graphics;
 | 
					Graphics g_graphics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Graphics::init()
 | 
					void Graphics::init()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,9 +23,6 @@
 | 
				
			||||||
#include "texture.h"
 | 
					#include "texture.h"
 | 
				
			||||||
#include "graphics.h"
 | 
					#include "graphics.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <GL/gl.h>
 | 
					 | 
				
			||||||
#include <GL/glext.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Texture::Texture()
 | 
					Texture::Texture()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    m_textureId = 0;
 | 
					    m_textureId = 0;
 | 
				
			||||||
| 
						 | 
					@ -61,7 +58,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
 | 
				
			||||||
        logError("loading texture with size ", width, "x", height, " failed, "
 | 
					        logError("loading texture with size ", width, "x", height, " failed, "
 | 
				
			||||||
                 "the maximum size allowed by the graphics card is ", maxTexSize, "x", maxTexSize, ",",
 | 
					                 "the maximum size allowed by the graphics card is ", maxTexSize, "x", maxTexSize, ",",
 | 
				
			||||||
                 "to prevent crashes the texture will be displayed as a blank texture");
 | 
					                 "to prevent crashes the texture will be displayed as a blank texture");
 | 
				
			||||||
        //TODO: a workground, like bilinear scaling the texture
 | 
					        //TODO: make a workaround, could be bilinear scaling the texture
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,17 +20,18 @@
 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "luainterface.h"
 | 
					#include <framework/luascript/luainterface.h>
 | 
				
			||||||
 | 
					#include <framework/application.h>
 | 
				
			||||||
#include <framework/graphics/fontmanager.h>
 | 
					#include <framework/graphics/fontmanager.h>
 | 
				
			||||||
#include <framework/ui/ui.h>
 | 
					#include <framework/ui/ui.h>
 | 
				
			||||||
#include <framework/net/protocol.h>
 | 
					#include <framework/net/protocol.h>
 | 
				
			||||||
#include <framework/core/eventdispatcher.h>
 | 
					#include <framework/core/eventdispatcher.h>
 | 
				
			||||||
#include <framework/core/configmanager.h>
 | 
					#include <framework/core/configmanager.h>
 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					 | 
				
			||||||
#include <framework/otml/otml.h>
 | 
					#include <framework/otml/otml.h>
 | 
				
			||||||
#include <framework/graphics/graphics.h>
 | 
					#include <framework/graphics/graphics.h>
 | 
				
			||||||
 | 
					#include <framework/platform/platformwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LuaInterface::registerFunctions()
 | 
					void Application::registerLuaFunctions()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // UIWidget
 | 
					    // UIWidget
 | 
				
			||||||
    g_lua.registerClass<UIWidget>();
 | 
					    g_lua.registerClass<UIWidget>();
 | 
				
			||||||
| 
						 | 
					@ -152,10 +153,21 @@ void LuaInterface::registerFunctions()
 | 
				
			||||||
    g_lua.registerClass<Protocol>();
 | 
					    g_lua.registerClass<Protocol>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // ConfigManager
 | 
					    // ConfigManager
 | 
				
			||||||
    g_lua.registerClass<ConfigManager>();
 | 
					    g_lua.registerStaticClass("g_configs");
 | 
				
			||||||
    g_lua.bindClassStaticFunction<ConfigManager>("set", std::bind(&ConfigManager::set, &g_configs, _1, _2));
 | 
					    g_lua.bindClassStaticFunction("g_configs", "set", std::bind(&ConfigManager::set, &g_configs, _1, _2));
 | 
				
			||||||
    g_lua.bindClassStaticFunction<ConfigManager>("get", std::bind(&ConfigManager::get, &g_configs, _1));
 | 
					    g_lua.bindClassStaticFunction("g_configs", "get", std::bind(&ConfigManager::get, &g_configs, _1));
 | 
				
			||||||
    g_lua.bindClassStaticFunction<ConfigManager>("exists", std::bind(&ConfigManager::exists, &g_configs, _1));
 | 
					    g_lua.bindClassStaticFunction("g_configs", "exists", std::bind(&ConfigManager::exists, &g_configs, _1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_lua.registerStaticClass("g_window");
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "show", std::bind(&PlatformWindow::show, &g_window));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "hide", std::bind(&PlatformWindow::hide, &g_window));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "move", std::bind(&PlatformWindow::move, &g_window, _1));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "resize", std::bind(&PlatformWindow::resize, &g_window, _1));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "setVerticalSync", std::bind(&PlatformWindow::setVerticalSync, &g_window, _1));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "setTitle", std::bind(&PlatformWindow::setTitle, &g_window, _1));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "setIcon", std::bind(&PlatformWindow::setIcon, &g_window, _1));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "getMousePos", std::bind(&PlatformWindow::getMousePos, &g_window));
 | 
				
			||||||
 | 
					    g_lua.bindClassStaticFunction("g_window", "getSize", std::bind(&PlatformWindow::getSize, &g_window));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Logger
 | 
					    // Logger
 | 
				
			||||||
    g_lua.registerClass<Logger>();
 | 
					    g_lua.registerClass<Logger>();
 | 
				
			||||||
| 
						 | 
					@ -171,7 +183,4 @@ void LuaInterface::registerFunctions()
 | 
				
			||||||
    g_lua.bindGlobalFunction("getRootWidget", std::bind(&UIManager::getRootWidget, &g_ui));
 | 
					    g_lua.bindGlobalFunction("getRootWidget", std::bind(&UIManager::getRootWidget, &g_ui));
 | 
				
			||||||
    g_lua.bindGlobalFunction("addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, false));
 | 
					    g_lua.bindGlobalFunction("addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, false));
 | 
				
			||||||
    g_lua.bindGlobalFunction("scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2));
 | 
					    g_lua.bindGlobalFunction("scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2));
 | 
				
			||||||
    g_lua.bindGlobalFunction("getMouseCursorPos", std::bind(&Platform::getMouseCursorPos, &g_platform));
 | 
					 | 
				
			||||||
    g_lua.bindGlobalFunction("setVerticalSync", std::bind(&Platform::setVerticalSync, &g_platform, _1));
 | 
					 | 
				
			||||||
    g_lua.bindGlobalFunction("getScreenSize", std::bind(&Graphics::getScreenSize, &g_graphics));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -47,9 +47,6 @@ void LuaInterface::init()
 | 
				
			||||||
    // register LuaObject, the base of all other objects
 | 
					    // register LuaObject, the base of all other objects
 | 
				
			||||||
    registerClass<LuaObject>();
 | 
					    registerClass<LuaObject>();
 | 
				
			||||||
    bindClassMemberGetField<LuaObject>("use_count", &LuaObject::getUseCount);
 | 
					    bindClassMemberGetField<LuaObject>("use_count", &LuaObject::getUseCount);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // register the real script stuff
 | 
					 | 
				
			||||||
    registerFunctions();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LuaInterface::terminate()
 | 
					void LuaInterface::terminate()
 | 
				
			||||||
| 
						 | 
					@ -58,6 +55,14 @@ void LuaInterface::terminate()
 | 
				
			||||||
    closeLuaState();
 | 
					    closeLuaState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LuaInterface::registerStaticClass(const std::string& className)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    newTable();
 | 
				
			||||||
 | 
					    pushValue();
 | 
				
			||||||
 | 
					    setGlobal(className);
 | 
				
			||||||
 | 
					    pop();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LuaInterface::registerClass(const std::string& className, const std::string& baseClass)
 | 
					void LuaInterface::registerClass(const std::string& className, const std::string& baseClass)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // creates the class table (that it's also the class methods table)
 | 
					    // creates the class table (that it's also the class methods table)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,6 +42,7 @@ public:
 | 
				
			||||||
    void registerFunctions();
 | 
					    void registerFunctions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // functions that will register all script stuff in lua global environment
 | 
					    // functions that will register all script stuff in lua global environment
 | 
				
			||||||
 | 
					    void registerStaticClass(const std::string& className);
 | 
				
			||||||
    void registerClass(const std::string& className, const std::string& baseClass = "LuaObject");
 | 
					    void registerClass(const std::string& className, const std::string& baseClass = "LuaObject");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void registerClassStaticFunction(const std::string& className,
 | 
					    void registerClassStaticFunction(const std::string& className,
 | 
				
			||||||
| 
						 | 
					@ -86,18 +87,28 @@ public:
 | 
				
			||||||
    // methods for binding functions
 | 
					    // methods for binding functions
 | 
				
			||||||
    template<class C, typename F>
 | 
					    template<class C, typename F>
 | 
				
			||||||
    void bindClassStaticFunction(const std::string& functionName, const F& function);
 | 
					    void bindClassStaticFunction(const std::string& functionName, const F& function);
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    void bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<class C, typename F>
 | 
					    template<class C, typename F>
 | 
				
			||||||
    void bindClassMemberFunction(const std::string& functionName, F C::*function);
 | 
					    void bindClassMemberFunction(const std::string& functionName, F C::*function);
 | 
				
			||||||
 | 
					    template<class C, typename F>
 | 
				
			||||||
 | 
					    void bindClassMemberFunction(const std::string& className, const std::string& functionName, F C::*function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<class C, typename F1, typename F2>
 | 
					    template<class C, typename F1, typename F2>
 | 
				
			||||||
    void bindClassMemberField(const std::string& fieldName, F1 C::*getFunction, F2 C::*setFunction);
 | 
					    void bindClassMemberField(const std::string& fieldName, F1 C::*getFunction, F2 C::*setFunction);
 | 
				
			||||||
 | 
					    template<class C, typename F1, typename F2>
 | 
				
			||||||
 | 
					    void bindClassMemberField(const std::string& className, const std::string& fieldName, F1 C::*getFunction, F2 C::*setFunction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<class C, typename F>
 | 
					    template<class C, typename F>
 | 
				
			||||||
    void bindClassMemberGetField(const std::string& fieldName, F C::*getFunction);
 | 
					    void bindClassMemberGetField(const std::string& fieldName, F C::*getFunction);
 | 
				
			||||||
 | 
					    template<class C, typename F>
 | 
				
			||||||
 | 
					    void bindClassMemberGetField(const std::string& className, const std::string& fieldName, F C::*getFunction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<class C, typename F>
 | 
					    template<class C, typename F>
 | 
				
			||||||
    void bindClassMemberSetField(const std::string& fieldName, F C::*setFunction);
 | 
					    void bindClassMemberSetField(const std::string& fieldName, F C::*setFunction);
 | 
				
			||||||
 | 
					    template<class C, typename F>
 | 
				
			||||||
 | 
					    void bindClassMemberSetField(const std::string& className, const std::string& fieldName, F C::*setFunction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename F>
 | 
					    template<typename F>
 | 
				
			||||||
    void bindGlobalFunction(const std::string& functionName, const F& function);
 | 
					    void bindGlobalFunction(const std::string& functionName, const F& function);
 | 
				
			||||||
| 
						 | 
					@ -314,31 +325,45 @@ template<class C, typename F>
 | 
				
			||||||
void LuaInterface::bindClassStaticFunction(const std::string& functionName, const F& function) {
 | 
					void LuaInterface::bindClassStaticFunction(const std::string& functionName, const F& function) {
 | 
				
			||||||
    registerClassStaticFunction<C>(functionName, luabinder::bind_fun(function));
 | 
					    registerClassStaticFunction<C>(functionName, luabinder::bind_fun(function));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					template<typename F>
 | 
				
			||||||
 | 
					void LuaInterface::bindClassStaticFunction(const std::string& className, const std::string& functionName, const F& function) {
 | 
				
			||||||
 | 
					    registerClassStaticFunction(className, functionName, luabinder::bind_fun(function));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<class C, typename F>
 | 
					template<class C, typename F>
 | 
				
			||||||
void LuaInterface::bindClassMemberFunction(const std::string& functionName, F C::*function) {
 | 
					void LuaInterface::bindClassMemberFunction(const std::string& functionName, F C::*function) {
 | 
				
			||||||
    registerClassMemberFunction<C>(functionName, luabinder::bind_mem_fun(function));
 | 
					    registerClassMemberFunction<C>(functionName, luabinder::bind_mem_fun(function));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					template<class C, typename F>
 | 
				
			||||||
 | 
					void LuaInterface::bindClassMemberFunction(const std::string& className, const std::string& functionName, F C::*function) {
 | 
				
			||||||
 | 
					    registerClassMemberFunction(className, functionName, luabinder::bind_mem_fun(function));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<class C, typename F1, typename F2>
 | 
					template<class C, typename F1, typename F2>
 | 
				
			||||||
void LuaInterface::bindClassMemberField(const std::string& fieldName, F1 C::*getFunction, F2 C::*setFunction) {
 | 
					void LuaInterface::bindClassMemberField(const std::string& fieldName, F1 C::*getFunction, F2 C::*setFunction) {
 | 
				
			||||||
    registerClassMemberField<C>(fieldName,
 | 
					    registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun(getFunction), luabinder::bind_mem_fun(setFunction));
 | 
				
			||||||
                                luabinder::bind_mem_fun(getFunction),
 | 
					}
 | 
				
			||||||
                                luabinder::bind_mem_fun(setFunction));
 | 
					template<class C, typename F1, typename F2>
 | 
				
			||||||
 | 
					void LuaInterface::bindClassMemberField(const std::string& className, const std::string& fieldName, F1 C::*getFunction, F2 C::*setFunction) {
 | 
				
			||||||
 | 
					    registerClassMemberField(className, fieldName, luabinder::bind_mem_fun(getFunction), luabinder::bind_mem_fun(setFunction));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<class C, typename F>
 | 
					template<class C, typename F>
 | 
				
			||||||
void LuaInterface::bindClassMemberGetField(const std::string& fieldName, F C::*getFunction) {
 | 
					void LuaInterface::bindClassMemberGetField(const std::string& fieldName, F C::*getFunction) {
 | 
				
			||||||
    registerClassMemberField<C>(fieldName,
 | 
					    registerClassMemberField<C>(fieldName, luabinder::bind_mem_fun(getFunction), LuaCppFunction());
 | 
				
			||||||
                                luabinder::bind_mem_fun(getFunction),
 | 
					}
 | 
				
			||||||
                                LuaCppFunction());
 | 
					template<class C, typename F>
 | 
				
			||||||
 | 
					void LuaInterface::bindClassMemberGetField(const std::string& className, const std::string& fieldName, F C::*getFunction) {
 | 
				
			||||||
 | 
					    registerClassMemberField(className, fieldName, luabinder::bind_mem_fun(getFunction), LuaCppFunction());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<class C, typename F>
 | 
					template<class C, typename F>
 | 
				
			||||||
void LuaInterface::bindClassMemberSetField(const std::string& fieldName, F C::*setFunction) {
 | 
					void LuaInterface::bindClassMemberSetField(const std::string& fieldName, F C::*setFunction) {
 | 
				
			||||||
    registerClassMemberField<C>(fieldName,
 | 
					    registerClassMemberField<C>(fieldName, LuaCppFunction(), luabinder::bind_mem_fun(setFunction));
 | 
				
			||||||
                                LuaCppFunction(),
 | 
					}
 | 
				
			||||||
                                luabinder::bind_mem_fun(setFunction));
 | 
					template<class C, typename F>
 | 
				
			||||||
 | 
					void LuaInterface::bindClassMemberSetField(const std::string& className, const std::string& fieldName, F C::*setFunction) {
 | 
				
			||||||
 | 
					    registerClassMemberField(className, fieldName, LuaCppFunction(), luabinder::bind_mem_fun(setFunction));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template<typename F>
 | 
					template<typename F>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,118 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HANDLE_EXCEPTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <csignal>
 | 
				
			||||||
 | 
					#include <execinfo.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_BACKTRACE_DEPTH 128
 | 
				
			||||||
 | 
					#define DEMANGLE_BACKTRACE_SYMBOLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void crashHandler(int signum, siginfo_t* info, void* secret)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    logError("Application crashed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ucontext_t context = *(ucontext_t*)secret;
 | 
				
			||||||
 | 
					    time_t tnow;
 | 
				
			||||||
 | 
					    char fileName[128];
 | 
				
			||||||
 | 
					    time(&tnow);
 | 
				
			||||||
 | 
					    tm *ts = localtime(&tnow);
 | 
				
			||||||
 | 
					    strftime(fileName, 128, (x11.appName + "-crash_-%d-%m-%Y_%H:%M:%S.txt").c_str(), ts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::stringstream ss;
 | 
				
			||||||
 | 
					    ss.flags(std::ios::hex | std::ios::showbase);
 | 
				
			||||||
 | 
					#if __WORDSIZE == 32
 | 
				
			||||||
 | 
					    ss <<
 | 
				
			||||||
 | 
					    ss << "  at eip = " << context.uc_mcontext.gregs[REG_EIP] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     eax = " << context.uc_mcontext.gregs[REG_EAX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     ebx = " << context.uc_mcontext.gregs[REG_EBX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     ecx = " << context.uc_mcontext.gregs[REG_ECX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     edx = " << context.uc_mcontext.gregs[REG_EDX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     esi = " << context.uc_mcontext.gregs[REG_ESI] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     edi = " << context.uc_mcontext.gregs[REG_EDI] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     ebp = " << context.uc_mcontext.gregs[REG_EBP] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     esp = " << context.uc_mcontext.gregs[REG_ESP] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     efl = " << context.uc_mcontext.gregs[REG_EFL] << std::endl;
 | 
				
			||||||
 | 
					#else // 64-bit
 | 
				
			||||||
 | 
					    ss << "  at rip = " << context.uc_mcontext.gregs[REG_RIP] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rax = " << context.uc_mcontext.gregs[REG_RAX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rbx = " << context.uc_mcontext.gregs[REG_RBX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rcx = " << context.uc_mcontext.gregs[REG_RCX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rdx = " << context.uc_mcontext.gregs[REG_RDX] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rsi = " << context.uc_mcontext.gregs[REG_RSI] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rdi = " << context.uc_mcontext.gregs[REG_RDI] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rbp = " << context.uc_mcontext.gregs[REG_RBP] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     rsp = " << context.uc_mcontext.gregs[REG_RSP] << std::endl;
 | 
				
			||||||
 | 
					    ss << "     efl = " << context.uc_mcontext.gregs[REG_EFL] << std::endl;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    ss << std::endl;
 | 
				
			||||||
 | 
					    ss.flags(std::ios::dec);
 | 
				
			||||||
 | 
					    ss << "  backtrace:" << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void* buffer[MAX_BACKTRACE_DEPTH];
 | 
				
			||||||
 | 
					    int numLevels = backtrace(buffer, MAX_BACKTRACE_DEPTH);
 | 
				
			||||||
 | 
					    char **tracebackBuffer = backtrace_symbols(buffer, numLevels);
 | 
				
			||||||
 | 
					    if(tracebackBuffer) {
 | 
				
			||||||
 | 
					        for(int i = 2; i < numLevels; i++) {
 | 
				
			||||||
 | 
					            std::string line = tracebackBuffer[i];
 | 
				
			||||||
 | 
					            if(line.find("__libc_start_main") != std::string::npos)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					#ifdef DEMANGLE_BACKTRACE_SYMBOLS
 | 
				
			||||||
 | 
					            std::size_t demanglePos = line.find("(_Z");
 | 
				
			||||||
 | 
					            if(demanglePos != std::string::npos) {
 | 
				
			||||||
 | 
					                demanglePos++;
 | 
				
			||||||
 | 
					                int len = std::min(line.find_first_of("+", demanglePos), line.find_first_of(")", demanglePos)) - demanglePos;
 | 
				
			||||||
 | 
					                std::string funcName = line.substr(demanglePos, len);
 | 
				
			||||||
 | 
					                line.replace(demanglePos, len, Fw::demangleName(funcName.c_str()));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					            ss << "    " << i-1 << ": " << line << std::endl;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        free(tracebackBuffer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    logInfo(ss.str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::ofstream out(fileName);
 | 
				
			||||||
 | 
					    out << ss.str();
 | 
				
			||||||
 | 
					    out.close();
 | 
				
			||||||
 | 
					    logInfo("Crash report saved to file ", fileName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    signal(SIGILL, SIG_DFL);
 | 
				
			||||||
 | 
					    signal(SIGSEGV, SIG_DFL);
 | 
				
			||||||
 | 
					    signal(SIGFPE, SIG_DFL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HANDLE_EXCEPTIONS
 | 
				
			||||||
 | 
					    struct sigaction sa;
 | 
				
			||||||
 | 
					    sa.sa_sigaction = &crashHandler;
 | 
				
			||||||
 | 
					    sigemptyset (&sa.sa_mask);
 | 
				
			||||||
 | 
					    sa.sa_flags = SA_RESTART | SA_SIGINFO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sigaction(SIGILL, &sa, NULL);   // illegal instruction
 | 
				
			||||||
 | 
					    sigaction(SIGSEGV, &sa, NULL);  // segmentation fault
 | 
				
			||||||
 | 
					    sigaction(SIGFPE, &sa, NULL);   // floating-point exception
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -1,86 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					 | 
				
			||||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
					 | 
				
			||||||
 * in the Software without restriction, including without limitation the rights
 | 
					 | 
				
			||||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					 | 
				
			||||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
					 | 
				
			||||||
 * furnished to do so, subject to the following conditions:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be included in
 | 
					 | 
				
			||||||
 * all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					 | 
				
			||||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					 | 
				
			||||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					 | 
				
			||||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef PLATFORM_H
 | 
					 | 
				
			||||||
#define PLATFORM_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <framework/global.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class PlatformListener;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Platform
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
    void init(PlatformListener* platformListener, const char* appName);
 | 
					 | 
				
			||||||
    void terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Poll platform input/window events
 | 
					 | 
				
			||||||
    void poll();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Sleep in current thread
 | 
					 | 
				
			||||||
    void sleep(ulong ms);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool createWindow(int x, int y, int width, int height, int minWidth, int minHeight, bool maximized);
 | 
					 | 
				
			||||||
    void setWindowIcon(const std::string& pngIcon);
 | 
					 | 
				
			||||||
    void destroyWindow();
 | 
					 | 
				
			||||||
    void showWindow();
 | 
					 | 
				
			||||||
    void hideWindow();
 | 
					 | 
				
			||||||
    void setWindowTitle(const char* title);
 | 
					 | 
				
			||||||
    bool isWindowFocused();
 | 
					 | 
				
			||||||
    bool isWindowVisible();
 | 
					 | 
				
			||||||
    int getWindowX();
 | 
					 | 
				
			||||||
    int getWindowY();
 | 
					 | 
				
			||||||
    int getWindowWidth();
 | 
					 | 
				
			||||||
    int getWindowHeight();
 | 
					 | 
				
			||||||
    bool isWindowMaximized();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int getDisplayHeight();
 | 
					 | 
				
			||||||
    int getDisplayWidth();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Get GL extension function address
 | 
					 | 
				
			||||||
    void* getExtensionProcAddress(const char* ext);
 | 
					 | 
				
			||||||
    /// Check if GLX/WGL extension is supported
 | 
					 | 
				
			||||||
    bool isExtensionSupported(const char* ext);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Get text from Ctrl+c
 | 
					 | 
				
			||||||
    const char* getClipboardText();
 | 
					 | 
				
			||||||
    /// Set text for Ctrl+v
 | 
					 | 
				
			||||||
    void setClipboardText(const char* text);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void hideMouseCursor();
 | 
					 | 
				
			||||||
    void showMouseCursor();
 | 
					 | 
				
			||||||
    Point getMouseCursorPos();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Enable or disable vertical synchronization
 | 
					 | 
				
			||||||
    void setVerticalSync(bool enable);
 | 
					 | 
				
			||||||
    /// Swap GL buffers
 | 
					 | 
				
			||||||
    void swapBuffers();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Get the app user directory, the place to save files configurations files
 | 
					 | 
				
			||||||
    std::string getAppUserDir();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void displayFatalError(const std::string& message);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern Platform g_platform;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,63 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					 | 
				
			||||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
					 | 
				
			||||||
 * in the Software without restriction, including without limitation the rights
 | 
					 | 
				
			||||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					 | 
				
			||||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
					 | 
				
			||||||
 * furnished to do so, subject to the following conditions:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be included in
 | 
					 | 
				
			||||||
 * all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					 | 
				
			||||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					 | 
				
			||||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					 | 
				
			||||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef INPUTEVENT_H
 | 
					 | 
				
			||||||
#define INPUTEVENT_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <framework/global.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum PlatformEventType {
 | 
					 | 
				
			||||||
    EventNone                    = 0,
 | 
					 | 
				
			||||||
    EventMouseAction             = 1,
 | 
					 | 
				
			||||||
    EventKeyboardAction          = 2,
 | 
					 | 
				
			||||||
    EventDown                    = 4,
 | 
					 | 
				
			||||||
    EventUp                      = 8,
 | 
					 | 
				
			||||||
    EventMouseWheel              = 16,
 | 
					 | 
				
			||||||
    EventMouseLeftButton         = 32,
 | 
					 | 
				
			||||||
    EventMouseRightButton        = 64,
 | 
					 | 
				
			||||||
    EventMouseMidButton          = 128,
 | 
					 | 
				
			||||||
    EventKeyDown                 = EventKeyboardAction | EventDown,
 | 
					 | 
				
			||||||
    EventKeyUp                   = EventKeyboardAction | EventUp,
 | 
					 | 
				
			||||||
    EventMouseMove               = EventMouseAction | 512,
 | 
					 | 
				
			||||||
    EventMouseLeftButtonDown     = EventMouseAction | EventMouseLeftButton | EventDown,
 | 
					 | 
				
			||||||
    EventMouseLeftButtonUp       = EventMouseAction | EventMouseLeftButton | EventUp,
 | 
					 | 
				
			||||||
    EventMouseMiddleButtonDown   = EventMouseAction | EventMouseMidButton | EventDown,
 | 
					 | 
				
			||||||
    EventMouseMiddleButtonUp     = EventMouseAction | EventMouseMidButton | EventUp,
 | 
					 | 
				
			||||||
    EventMouseRightButtonDown    = EventMouseAction | EventMouseRightButton | EventDown,
 | 
					 | 
				
			||||||
    EventMouseRightButtonUp      = EventMouseAction | EventMouseRightButton | EventUp,
 | 
					 | 
				
			||||||
    EventMouseWheelUp            = EventMouseAction | EventMouseWheel | EventUp,
 | 
					 | 
				
			||||||
    EventMouseWheelDown          = EventMouseAction | EventMouseWheel | EventDown
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//TODO: rework platform events, make more compatible with UI events
 | 
					 | 
				
			||||||
struct PlatformEvent {
 | 
					 | 
				
			||||||
    int type;
 | 
					 | 
				
			||||||
    Point mousePos;
 | 
					 | 
				
			||||||
    Point mouseMoved;
 | 
					 | 
				
			||||||
    char keychar;
 | 
					 | 
				
			||||||
    Fw::Key keycode;
 | 
					 | 
				
			||||||
    bool ctrl;
 | 
					 | 
				
			||||||
    bool shift;
 | 
					 | 
				
			||||||
    bool alt;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -20,5 +20,14 @@
 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "engine.h"
 | 
					#include "platformwindow.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef WIN32
 | 
				
			||||||
 | 
					#include "win32window.h"
 | 
				
			||||||
 | 
					WIN32Window window;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include "x11window.h"
 | 
				
			||||||
 | 
					X11Window window;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PlatformWindow& g_window = window;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,95 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef PLATFORMWINDOW_H
 | 
				
			||||||
 | 
					#define PLATFORMWINDOW_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <framework/global.h>
 | 
				
			||||||
 | 
					#include <framework/core/inputevent.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PlatformWindow
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    typedef std::function<void(const Size&)> OnResizeCallback;
 | 
				
			||||||
 | 
					    typedef std::function<void(const InputEvent&)> OnInputEventCallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    virtual void init() = 0;
 | 
				
			||||||
 | 
					    virtual void terminate() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual void move(const Point& pos) = 0;
 | 
				
			||||||
 | 
					    virtual void resize(const Size& size) = 0;
 | 
				
			||||||
 | 
					    virtual void show() = 0;
 | 
				
			||||||
 | 
					    virtual void hide() = 0;
 | 
				
			||||||
 | 
					    virtual void maximize() = 0;
 | 
				
			||||||
 | 
					    virtual void poll() = 0;
 | 
				
			||||||
 | 
					    virtual void swapBuffers() = 0;
 | 
				
			||||||
 | 
					    virtual void showMouse() = 0;
 | 
				
			||||||
 | 
					    virtual void hideMouse() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual void setTitle(const std::string& title) = 0;
 | 
				
			||||||
 | 
					    virtual void setMinimumSize(const Size& minimumSize) = 0;
 | 
				
			||||||
 | 
					    virtual void setFullscreen(bool fullscreen) = 0;
 | 
				
			||||||
 | 
					    virtual void setVerticalSync(bool enable) = 0;
 | 
				
			||||||
 | 
					    virtual void setIcon(const std::string& iconFile) = 0;
 | 
				
			||||||
 | 
					    virtual void setClipboardText(const std::string& text) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual Size getDisplaySize() = 0;
 | 
				
			||||||
 | 
					    virtual std::string getClipboardText() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int getDisplayWidth() { return getDisplaySize().width(); }
 | 
				
			||||||
 | 
					    int getDisplayHeight() { return getDisplaySize().width(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Size getSize() { return m_size; }
 | 
				
			||||||
 | 
					    int getWidth() { return m_size.width(); }
 | 
				
			||||||
 | 
					    int getHeight() { return m_size.height(); }
 | 
				
			||||||
 | 
					    Point getPos() { return m_pos; }
 | 
				
			||||||
 | 
					    int getX() { return m_pos.x; }
 | 
				
			||||||
 | 
					    int getY() { return m_pos.y; }
 | 
				
			||||||
 | 
					    Point getMousePos() { return m_inputEvent.mousePos; }
 | 
				
			||||||
 | 
					    int getKeyboardModifiers() { return m_inputEvent.keyboardModifiers; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool isVisible() { return m_visible; }
 | 
				
			||||||
 | 
					    bool isFullscreen() { return m_fullscreen; }
 | 
				
			||||||
 | 
					    bool hasFocus() { return m_focused; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void setOnClose(const SimpleCallback& onClose) { m_onClose = onClose; }
 | 
				
			||||||
 | 
					    void setOnResize(const OnResizeCallback& onResize) { m_onResize = onResize; }
 | 
				
			||||||
 | 
					    void setOnInputEvent(const OnInputEventCallback& onInputEvent) { m_onInputEvent = onInputEvent; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					    Size m_size;
 | 
				
			||||||
 | 
					    Point m_pos;
 | 
				
			||||||
 | 
					    InputEvent m_inputEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Boolean<false> m_created;
 | 
				
			||||||
 | 
					    Boolean<false> m_visible;
 | 
				
			||||||
 | 
					    Boolean<false> m_focused;
 | 
				
			||||||
 | 
					    Boolean<false> m_fullscreen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SimpleCallback m_onClose;
 | 
				
			||||||
 | 
					    OnResizeCallback m_onResize;
 | 
				
			||||||
 | 
					    OnInputEventCallback m_onInputEvent;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern PlatformWindow& g_window;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,10 @@
 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// disabled for a while
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					#include "win32window.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "platform.h"
 | 
					#include "platform.h"
 | 
				
			||||||
#include "platformlistener.h"
 | 
					#include "platformlistener.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -789,3 +793,4 @@ void Platform::displayFatalError(const std::string& message)
 | 
				
			||||||
    MessageBoxA(NULL, message.c_str(), "Fatal Error", MB_OK | MB_ICONERROR);
 | 
					    MessageBoxA(NULL, message.c_str(), "Fatal Error", MB_OK | MB_ICONERROR);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -20,14 +20,14 @@
 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef ENGINE_H
 | 
					#ifndef WIN32WINDOW_H
 | 
				
			||||||
#define ENGINE_H
 | 
					#define WIN32WINDOW_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "declarations.h"
 | 
					#include "platformwindow.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Engine
 | 
					class WIN32Window : public PlatformWindow
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    //TODO
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,989 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					 | 
				
			||||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
					 | 
				
			||||||
 * in the Software without restriction, including without limitation the rights
 | 
					 | 
				
			||||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					 | 
				
			||||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
					 | 
				
			||||||
 * furnished to do so, subject to the following conditions:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be included in
 | 
					 | 
				
			||||||
 * all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					 | 
				
			||||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					 | 
				
			||||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					 | 
				
			||||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "platform.h"
 | 
					 | 
				
			||||||
#include "platformlistener.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/time.h>
 | 
					 | 
				
			||||||
#include <sys/stat.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <physfs.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <GL/glx.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <X11/Xlib.h>
 | 
					 | 
				
			||||||
#include <X11/Xatom.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <framework/thirdparty/apngloader.h>
 | 
					 | 
				
			||||||
#include <framework/core/resourcemanager.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct X11PlatformPrivate {
 | 
					 | 
				
			||||||
    Display *display;
 | 
					 | 
				
			||||||
    XVisualInfo *visual;
 | 
					 | 
				
			||||||
    GLXContext glxContext;
 | 
					 | 
				
			||||||
    XIM xim;
 | 
					 | 
				
			||||||
    XIC xic;
 | 
					 | 
				
			||||||
    Colormap colormap;
 | 
					 | 
				
			||||||
    Window window;
 | 
					 | 
				
			||||||
    Cursor cursor;
 | 
					 | 
				
			||||||
    Atom atomDeleteWindow;
 | 
					 | 
				
			||||||
    Atom atomClipboard;
 | 
					 | 
				
			||||||
    Atom atomTargets;
 | 
					 | 
				
			||||||
    Atom atomText;
 | 
					 | 
				
			||||||
    Atom atomCompoundText;
 | 
					 | 
				
			||||||
    Atom atomUTF8String;
 | 
					 | 
				
			||||||
    Atom atomWindowState;
 | 
					 | 
				
			||||||
    Atom atomWindowMaximizedVert;
 | 
					 | 
				
			||||||
    Atom atomWindowMaximizedHorz;
 | 
					 | 
				
			||||||
    bool visible;
 | 
					 | 
				
			||||||
    bool focused;
 | 
					 | 
				
			||||||
    bool maximizeOnFirstShow;
 | 
					 | 
				
			||||||
    std::string appName;
 | 
					 | 
				
			||||||
    int width;
 | 
					 | 
				
			||||||
    int height;
 | 
					 | 
				
			||||||
    int x;
 | 
					 | 
				
			||||||
    int y;
 | 
					 | 
				
			||||||
    int lastTicks;
 | 
					 | 
				
			||||||
    std::string clipboardText;
 | 
					 | 
				
			||||||
    std::map<int, Fw::Key> keyMap;
 | 
					 | 
				
			||||||
    PlatformListener* listener;
 | 
					 | 
				
			||||||
    PlatformEvent platformEvent;
 | 
					 | 
				
			||||||
} x11;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Platform g_platform;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef HANDLE_EXCEPTIONS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <csignal>
 | 
					 | 
				
			||||||
#include <execinfo.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MAX_BACKTRACE_DEPTH 128
 | 
					 | 
				
			||||||
#define DEMANGLE_BACKTRACE_SYMBOLS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void crashHandler(int signum, siginfo_t* info, void* secret)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    logError("Application crashed");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ucontext_t context = *(ucontext_t*)secret;
 | 
					 | 
				
			||||||
    time_t tnow;
 | 
					 | 
				
			||||||
    char fileName[128];
 | 
					 | 
				
			||||||
    time(&tnow);
 | 
					 | 
				
			||||||
    tm *ts = localtime(&tnow);
 | 
					 | 
				
			||||||
    strftime(fileName, 128, (x11.appName + "-crash_-%d-%m-%Y_%H:%M:%S.txt").c_str(), ts);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::stringstream ss;
 | 
					 | 
				
			||||||
    ss.flags(std::ios::hex | std::ios::showbase);
 | 
					 | 
				
			||||||
#if __WORDSIZE == 32
 | 
					 | 
				
			||||||
    ss <<
 | 
					 | 
				
			||||||
    ss << "  at eip = " << context.uc_mcontext.gregs[REG_EIP] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     eax = " << context.uc_mcontext.gregs[REG_EAX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     ebx = " << context.uc_mcontext.gregs[REG_EBX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     ecx = " << context.uc_mcontext.gregs[REG_ECX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     edx = " << context.uc_mcontext.gregs[REG_EDX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     esi = " << context.uc_mcontext.gregs[REG_ESI] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     edi = " << context.uc_mcontext.gregs[REG_EDI] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     ebp = " << context.uc_mcontext.gregs[REG_EBP] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     esp = " << context.uc_mcontext.gregs[REG_ESP] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     efl = " << context.uc_mcontext.gregs[REG_EFL] << std::endl;
 | 
					 | 
				
			||||||
#else // 64-bit
 | 
					 | 
				
			||||||
    ss << "  at rip = " << context.uc_mcontext.gregs[REG_RIP] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rax = " << context.uc_mcontext.gregs[REG_RAX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rbx = " << context.uc_mcontext.gregs[REG_RBX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rcx = " << context.uc_mcontext.gregs[REG_RCX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rdx = " << context.uc_mcontext.gregs[REG_RDX] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rsi = " << context.uc_mcontext.gregs[REG_RSI] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rdi = " << context.uc_mcontext.gregs[REG_RDI] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rbp = " << context.uc_mcontext.gregs[REG_RBP] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     rsp = " << context.uc_mcontext.gregs[REG_RSP] << std::endl;
 | 
					 | 
				
			||||||
    ss << "     efl = " << context.uc_mcontext.gregs[REG_EFL] << std::endl;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    ss << std::endl;
 | 
					 | 
				
			||||||
    ss.flags(std::ios::dec);
 | 
					 | 
				
			||||||
    ss << "  backtrace:" << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void* buffer[MAX_BACKTRACE_DEPTH];
 | 
					 | 
				
			||||||
    int numLevels = backtrace(buffer, MAX_BACKTRACE_DEPTH);
 | 
					 | 
				
			||||||
    char **tracebackBuffer = backtrace_symbols(buffer, numLevels);
 | 
					 | 
				
			||||||
    if(tracebackBuffer) {
 | 
					 | 
				
			||||||
        for(int i = 2; i < numLevels; i++) {
 | 
					 | 
				
			||||||
            std::string line = tracebackBuffer[i];
 | 
					 | 
				
			||||||
            if(line.find("__libc_start_main") != std::string::npos)
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
#ifdef DEMANGLE_BACKTRACE_SYMBOLS
 | 
					 | 
				
			||||||
            std::size_t demanglePos = line.find("(_Z");
 | 
					 | 
				
			||||||
            if(demanglePos != std::string::npos) {
 | 
					 | 
				
			||||||
                demanglePos++;
 | 
					 | 
				
			||||||
                int len = std::min(line.find_first_of("+", demanglePos), line.find_first_of(")", demanglePos)) - demanglePos;
 | 
					 | 
				
			||||||
                std::string funcName = line.substr(demanglePos, len);
 | 
					 | 
				
			||||||
                line.replace(demanglePos, len, Fw::demangleName(funcName.c_str()));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
            ss << "    " << i-1 << ": " << line << std::endl;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        free(tracebackBuffer);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    logInfo(ss.str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::ofstream out(fileName);
 | 
					 | 
				
			||||||
    out << ss.str();
 | 
					 | 
				
			||||||
    out.close();
 | 
					 | 
				
			||||||
    logInfo("Crash report saved to file ", fileName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    signal(SIGILL, SIG_DFL);
 | 
					 | 
				
			||||||
    signal(SIGSEGV, SIG_DFL);
 | 
					 | 
				
			||||||
    signal(SIGFPE, SIG_DFL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::init(PlatformListener* platformListener, const char *appName)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#ifdef HANDLE_EXCEPTIONS
 | 
					 | 
				
			||||||
    struct sigaction sa;
 | 
					 | 
				
			||||||
    sa.sa_sigaction = &crashHandler;
 | 
					 | 
				
			||||||
    sigemptyset (&sa.sa_mask);
 | 
					 | 
				
			||||||
    sa.sa_flags = SA_RESTART | SA_SIGINFO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sigaction(SIGILL, &sa, NULL);   // illegal instruction
 | 
					 | 
				
			||||||
    sigaction(SIGSEGV, &sa, NULL);  // segmentation fault
 | 
					 | 
				
			||||||
    sigaction(SIGFPE, &sa, NULL);   // floating-point exception
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // seend random numbers
 | 
					 | 
				
			||||||
    srand(time(NULL));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.appName = appName;
 | 
					 | 
				
			||||||
    x11.display = NULL;
 | 
					 | 
				
			||||||
    x11.visual = NULL;
 | 
					 | 
				
			||||||
    x11.glxContext = NULL;
 | 
					 | 
				
			||||||
    x11.xim = NULL;
 | 
					 | 
				
			||||||
    x11.xic = NULL;
 | 
					 | 
				
			||||||
    x11.colormap = None;
 | 
					 | 
				
			||||||
    x11.window = None;
 | 
					 | 
				
			||||||
    x11.cursor = None;
 | 
					 | 
				
			||||||
    x11.visible = false;
 | 
					 | 
				
			||||||
    x11.focused = false;
 | 
					 | 
				
			||||||
    x11.width = 0;
 | 
					 | 
				
			||||||
    x11.height = 0;
 | 
					 | 
				
			||||||
    x11.maximizeOnFirstShow = false;
 | 
					 | 
				
			||||||
    x11.listener = platformListener;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Escape] = Fw::KeyEscape;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Tab] = Fw::KeyTab;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Return] = Fw::KeyReturn;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_BackSpace] = Fw::KeyBackspace;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Page_Up] = Fw::KeyPageUp;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Page_Down] = Fw::KeyPageDown;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Home] = Fw::KeyHome;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_End] = Fw::KeyEnd;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Insert] = Fw::KeyInsert;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Delete] = Fw::KeyDelete;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Up] = Fw::KeyUp;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Down] = Fw::KeyDown;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Left] = Fw::KeyLeft;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Right] = Fw::KeyRight;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Num_Lock] = Fw::KeyNumLock;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Scroll_Lock] = Fw::KeyScrollLock;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Caps_Lock] = Fw::KeyCapsLock;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Print] = Fw::KeyPrintScreen;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Pause] = Fw::KeyPause;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Control_L] = Fw::KeyCtrl;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Control_R] = Fw::KeyCtrl;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Shift_R] = Fw::KeyShift;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Shift_L] = Fw::KeyShift;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Alt_R] = Fw::KeyAlt;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Alt_L] = Fw::KeyAltGr;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Meta_L] = Fw::KeyMeta;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Meta_R] = Fw::KeyMeta;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_Menu] = Fw::KeyMenu;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // ascii characters
 | 
					 | 
				
			||||||
    x11.keyMap[XK_space] = Fw::KeySpace;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_exclam] = Fw::KeyExclamation;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_quotedbl] = Fw::KeyQuote;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_numbersign] = Fw::KeyNumberSign;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_dollar] = Fw::KeyDollar;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_percent] = Fw::KeyPercent;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_ampersand] = Fw::KeyAmpersand;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_apostrophe] = Fw::KeyApostrophe;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_parenleft] = Fw::KeyLeftParen;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_parenright] = Fw::KeyRightParen;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_asterisk] = Fw::KeyAsterisk;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_plus] = Fw::KeyPlus;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_comma] = Fw::KeyComma;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_minus] = Fw::KeyMinus;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_period] = Fw::KeyPeriod;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_slash] = Fw::KeySlash;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_1] = Fw::Key1;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_2] = Fw::Key2;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_3] = Fw::Key3;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_4] = Fw::Key4;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_5] = Fw::Key5;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_6] = Fw::Key6;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_7] = Fw::Key7;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_8] = Fw::Key8;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_9] = Fw::Key9;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_0] = Fw::Key0;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_colon] = Fw::KeyColon;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_semicolon] = Fw::KeySemicolon;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_less] = Fw::KeyLess;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_equal] = Fw::KeyEqual;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_greater] = Fw::KeyGreater;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_question] = Fw::KeyQuestion;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_at] = Fw::KeyAtSign;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_a] = Fw::KeyA;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_b] = Fw::KeyB;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_c] = Fw::KeyC;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_d] = Fw::KeyD;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_e] = Fw::KeyE;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_f] = Fw::KeyF;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_g] = Fw::KeyG;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_h] = Fw::KeyH;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_i] = Fw::KeyI;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_j] = Fw::KeyJ;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_k] = Fw::KeyK;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_l] = Fw::KeyL;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_m] = Fw::KeyM;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_n] = Fw::KeyN;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_o] = Fw::KeyO;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_p] = Fw::KeyP;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_q] = Fw::KeyQ;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_r] = Fw::KeyR;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_s] = Fw::KeyS;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_t] = Fw::KeyT;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_u] = Fw::KeyU;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_v] = Fw::KeyV;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_w] = Fw::KeyW;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_x] = Fw::KeyX;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_y] = Fw::KeyY;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_z] = Fw::KeyZ;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_bracketleft] = Fw::KeyLeftBracket;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_backslash] = Fw::KeyBackslash;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_bracketright] = Fw::KeyRightBracket;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_asciicircum] = Fw::KeyCaret;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_underscore] = Fw::KeyUnderscore;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_grave] = Fw::KeyGrave;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_braceleft] = Fw::KeyLeftCurly;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_bar] = Fw::KeyBar;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_braceright] = Fw::KeyRightCurly;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_asciitilde] = Fw::KeyTilde;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // keypad
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Add] = Fw::KeyPlus;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Subtract] = Fw::KeyMinus;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Decimal] = Fw::KeyPeriod;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Divide] = Fw::KeySlash;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Multiply] = Fw::KeyAsterisk;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Enter] = Fw::KeyEnter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // keypad with numlock off
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Insert] = Fw::KeyNumpad0;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_End] = Fw::KeyNumpad1;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Down] = Fw::KeyNumpad2;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Page_Down] = Fw::KeyNumpad3;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Left] = Fw::KeyNumpad4;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Begin] = Fw::KeyNumpad5;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Right] = Fw::KeyNumpad6;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Home] = Fw::KeyNumpad7;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Up] = Fw::KeyNumpad8;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Page_Up] = Fw::KeyNumpad9;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_Delete] = Fw::KeyDelete;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // keypad with numlock on
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_0] = Fw::Key0;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_1] = Fw::Key1;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_2] = Fw::Key2;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_3] = Fw::Key3;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_4] = Fw::Key4;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_5] = Fw::Key5;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_6] = Fw::Key6;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_7] = Fw::Key7;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_8] = Fw::Key8;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_KP_9] = Fw::Key9;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F1] = Fw::KeyF1;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F2] = Fw::KeyF2;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F3] = Fw::KeyF3;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F4] = Fw::KeyF4;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F5] = Fw::KeyF5;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F6] = Fw::KeyF6;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F7] = Fw::KeyF7;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F8] = Fw::KeyF8;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F9] = Fw::KeyF9;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F10] = Fw::KeyF10;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F11] = Fw::KeyF11;
 | 
					 | 
				
			||||||
    x11.keyMap[XK_F12] = Fw::KeyF12;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // try to set a latin1 locales otherwise fallback to standard C locale
 | 
					 | 
				
			||||||
    static char locales[][32] = { "en_US.iso88591", "iso88591", "en_US", "C" };
 | 
					 | 
				
			||||||
    for(int i=0;i<4;++i) {
 | 
					 | 
				
			||||||
        if(setlocale(LC_ALL, locales[i]))
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // open display
 | 
					 | 
				
			||||||
    x11.display = XOpenDisplay(0);
 | 
					 | 
				
			||||||
    if(!x11.display)
 | 
					 | 
				
			||||||
        logFatal("Failed to open X display");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // check if GLX is supported on this display
 | 
					 | 
				
			||||||
    if(!glXQueryExtension(x11.display, 0, 0))
 | 
					 | 
				
			||||||
        logFatal("GLX not supported");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // retrieve GLX version
 | 
					 | 
				
			||||||
    int glxMajor;
 | 
					 | 
				
			||||||
    int glxMinor;
 | 
					 | 
				
			||||||
    if(!glXQueryVersion(x11.display, &glxMajor, &glxMinor))
 | 
					 | 
				
			||||||
        logFatal("Unable to query GLX version");
 | 
					 | 
				
			||||||
    logInfo("GLX version ",glxMajor,".",glxMinor);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // clipboard related atoms
 | 
					 | 
				
			||||||
    x11.atomClipboard = XInternAtom(x11.display, "CLIPBOARD", False);
 | 
					 | 
				
			||||||
    x11.atomTargets = XInternAtom(x11.display, "TARGETS", False);
 | 
					 | 
				
			||||||
    x11.atomUTF8String = XInternAtom(x11.display, "UTF8_STRING", False);
 | 
					 | 
				
			||||||
    x11.atomText = XInternAtom(x11.display, "TEXT", False);
 | 
					 | 
				
			||||||
    x11.atomCompoundText = XInternAtom(x11.display, "COMPOUND_TEXT", False);
 | 
					 | 
				
			||||||
    x11.atomWindowState = XInternAtom(x11.display, "_NET_WM_STATE", False);
 | 
					 | 
				
			||||||
    x11.atomWindowMaximizedVert = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
 | 
					 | 
				
			||||||
    x11.atomWindowMaximizedHorz = XInternAtom(x11.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::terminate()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if(x11.window) {
 | 
					 | 
				
			||||||
        destroyWindow();
 | 
					 | 
				
			||||||
        x11.window = None;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // close display
 | 
					 | 
				
			||||||
    if(x11.display) {
 | 
					 | 
				
			||||||
        XCloseDisplay(x11.display);
 | 
					 | 
				
			||||||
        x11.display = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::poll()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    XEvent event, peekevent;
 | 
					 | 
				
			||||||
    PlatformEvent& platformEvent = x11.platformEvent;
 | 
					 | 
				
			||||||
    static int oldWidth = -1;
 | 
					 | 
				
			||||||
    static int oldHeight = -1;
 | 
					 | 
				
			||||||
    while(XPending(x11.display) > 0) {
 | 
					 | 
				
			||||||
        XNextEvent(x11.display, &event);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // call filter because xim will discard KeyPress events when keys still composing
 | 
					 | 
				
			||||||
        if(XFilterEvent(&event, x11.window))
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // discard events of repeated key releases
 | 
					 | 
				
			||||||
        if(event.type == KeyRelease && XPending(x11.display)) {
 | 
					 | 
				
			||||||
            XPeekEvent(x11.display, &peekevent);
 | 
					 | 
				
			||||||
            if((peekevent.type == KeyPress) &&
 | 
					 | 
				
			||||||
              (peekevent.xkey.keycode == event.xkey.keycode) &&
 | 
					 | 
				
			||||||
              ((peekevent.xkey.time-event.xkey.time) < 2))
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch(event.type) {
 | 
					 | 
				
			||||||
            case Expose:
 | 
					 | 
				
			||||||
                // needs redraw
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case ConfigureNotify:
 | 
					 | 
				
			||||||
                // window resize
 | 
					 | 
				
			||||||
                if(oldWidth != event.xconfigure.width || oldHeight != event.xconfigure.height) {
 | 
					 | 
				
			||||||
                    x11.listener->onResize(Size(event.xconfigure.width, event.xconfigure.height));
 | 
					 | 
				
			||||||
                    oldWidth = event.xconfigure.width;
 | 
					 | 
				
			||||||
                    oldHeight = event.xconfigure.height;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if(!isWindowMaximized()) {
 | 
					 | 
				
			||||||
                    x11.width = event.xconfigure.width;
 | 
					 | 
				
			||||||
                    x11.height = event.xconfigure.height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    // hack to fix x11 windows move gaps
 | 
					 | 
				
			||||||
                    static int gap_x = -1, gap_y = -1;
 | 
					 | 
				
			||||||
                    if(gap_x == -1 && gap_y == -1) {
 | 
					 | 
				
			||||||
                        gap_x = event.xconfigure.x;
 | 
					 | 
				
			||||||
                        gap_y = event.xconfigure.y;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    x11.x = event.xconfigure.x - gap_x;
 | 
					 | 
				
			||||||
                    x11.y = event.xconfigure.y - gap_y;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case KeyPress:
 | 
					 | 
				
			||||||
            case KeyRelease: {
 | 
					 | 
				
			||||||
                KeySym keysym;
 | 
					 | 
				
			||||||
                char buf[32];
 | 
					 | 
				
			||||||
                int len;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                platformEvent.ctrl = (event.xkey.state & ControlMask);
 | 
					 | 
				
			||||||
                platformEvent.shift = (event.xkey.state & ShiftMask);
 | 
					 | 
				
			||||||
                platformEvent.alt = (event.xkey.state & Mod1Mask);
 | 
					 | 
				
			||||||
                platformEvent.keychar = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // fire enter text event
 | 
					 | 
				
			||||||
                if(event.type == KeyPress && !platformEvent.ctrl && !platformEvent.alt) {
 | 
					 | 
				
			||||||
                    if(x11.xic) { // with xim we can get latin1 input correctly
 | 
					 | 
				
			||||||
                        Status status;
 | 
					 | 
				
			||||||
                        len = XmbLookupString(x11.xic, &event.xkey, buf, sizeof(buf), &keysym, &status);
 | 
					 | 
				
			||||||
                    } else { // otherwise use XLookupString, but it doesn't work right with dead keys often
 | 
					 | 
				
			||||||
                        static XComposeStatus compose = {NULL, 0};
 | 
					 | 
				
			||||||
                        len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if(len > 0 &&
 | 
					 | 
				
			||||||
                       // these keys produces characters that we don't want to capture
 | 
					 | 
				
			||||||
                       keysym != XK_BackSpace &&
 | 
					 | 
				
			||||||
                       keysym != XK_Return &&
 | 
					 | 
				
			||||||
                       keysym != XK_Delete &&
 | 
					 | 
				
			||||||
                       keysym != XK_Escape &&
 | 
					 | 
				
			||||||
                       (uchar)(buf[0]) >= 32
 | 
					 | 
				
			||||||
                    ) {
 | 
					 | 
				
			||||||
                        //logDebug("char: ", buf[0], " code: ", (uint)buf[0]);
 | 
					 | 
				
			||||||
                        platformEvent.keychar = buf[0];
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    //event.xkey.state &= ~(ShiftMask | LockMask);
 | 
					 | 
				
			||||||
                    len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if(len > 0 && (uchar)platformEvent.keychar >= 32)
 | 
					 | 
				
			||||||
                        platformEvent.keychar = (len > 0) ? buf[0] : 0;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if(x11.keyMap.find(keysym) != x11.keyMap.end())
 | 
					 | 
				
			||||||
                    platformEvent.keycode = x11.keyMap[keysym];
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    platformEvent.keycode = Fw::KeyUnknown;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                platformEvent.keycode = x11.keyMap[keysym];
 | 
					 | 
				
			||||||
                platformEvent.type = (event.type == KeyPress) ? EventKeyDown : EventKeyUp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if(platformEvent.keycode != Fw::KeyUnknown || platformEvent.keychar != 0)
 | 
					 | 
				
			||||||
                    x11.listener->onPlatformEvent(platformEvent);
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            case ButtonPress:
 | 
					 | 
				
			||||||
            case ButtonRelease:
 | 
					 | 
				
			||||||
                switch(event.xbutton.button) {
 | 
					 | 
				
			||||||
                    case Button1:
 | 
					 | 
				
			||||||
                        platformEvent.type = (event.type == ButtonPress) ? EventMouseLeftButtonDown : EventMouseLeftButtonUp;
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    case Button3:
 | 
					 | 
				
			||||||
                        platformEvent.type = (event.type == ButtonPress) ? EventMouseRightButtonDown : EventMouseRightButtonUp;
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    case Button2:
 | 
					 | 
				
			||||||
                        platformEvent.type = (event.type == ButtonPress) ? EventMouseMiddleButtonDown : EventMouseMiddleButtonUp;
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    case Button4:
 | 
					 | 
				
			||||||
                        platformEvent.type = EventMouseWheelUp;
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    case Button5:
 | 
					 | 
				
			||||||
                        platformEvent.type = EventMouseWheelDown;
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                x11.listener->onPlatformEvent(platformEvent);
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case MotionNotify:
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                platformEvent.type = EventMouseMove;
 | 
					 | 
				
			||||||
                Point newMousePos(event.xbutton.x, event.xbutton.y);
 | 
					 | 
				
			||||||
                platformEvent.mouseMoved = newMousePos - platformEvent.mousePos;
 | 
					 | 
				
			||||||
                platformEvent.mousePos = newMousePos;
 | 
					 | 
				
			||||||
                x11.listener->onPlatformEvent(platformEvent);
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case MapNotify:
 | 
					 | 
				
			||||||
                x11.visible = true;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case UnmapNotify:
 | 
					 | 
				
			||||||
                x11.visible = false;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case FocusIn:
 | 
					 | 
				
			||||||
                x11.focused = true;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case FocusOut:
 | 
					 | 
				
			||||||
                x11.focused = false;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // clipboard data request
 | 
					 | 
				
			||||||
            case SelectionRequest:
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                XEvent respond;
 | 
					 | 
				
			||||||
                XSelectionRequestEvent *req = &(event.xselectionrequest);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if(req->target == x11.atomTargets ) {
 | 
					 | 
				
			||||||
                    Atom typeList[] = {x11.atomText, x11.atomCompoundText, x11.atomUTF8String, XA_STRING};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    XChangeProperty(x11.display, req->requestor,
 | 
					 | 
				
			||||||
                                    req->property, req->target,
 | 
					 | 
				
			||||||
                                    8, PropModeReplace,
 | 
					 | 
				
			||||||
                                    (uchar *) &typeList,
 | 
					 | 
				
			||||||
                                    sizeof(typeList));
 | 
					 | 
				
			||||||
                    respond.xselection.property = req->property;
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    XChangeProperty(x11.display,
 | 
					 | 
				
			||||||
                                    req->requestor,
 | 
					 | 
				
			||||||
                                    req->property, req->target,
 | 
					 | 
				
			||||||
                                    8,
 | 
					 | 
				
			||||||
                                    PropModeReplace,
 | 
					 | 
				
			||||||
                                    (uchar*) x11.clipboardText.c_str(),
 | 
					 | 
				
			||||||
                                    x11.clipboardText.size());
 | 
					 | 
				
			||||||
                    respond.xselection.property = req->property;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                respond.xselection.type = SelectionNotify;
 | 
					 | 
				
			||||||
                respond.xselection.display = req->display;
 | 
					 | 
				
			||||||
                respond.xselection.requestor = req->requestor;
 | 
					 | 
				
			||||||
                respond.xselection.selection = req->selection;
 | 
					 | 
				
			||||||
                respond.xselection.target = req->target;
 | 
					 | 
				
			||||||
                respond.xselection.time = req->time;
 | 
					 | 
				
			||||||
                XSendEvent(x11.display, req->requestor, 0, 0, &respond);
 | 
					 | 
				
			||||||
                XFlush(x11.display);
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case ClientMessage:
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if((Atom)event.xclient.data.l[0] == x11.atomDeleteWindow)
 | 
					 | 
				
			||||||
                    x11.listener->onClose();
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Platform::createWindow(int x, int y, int width, int height, int minWidth, int minHeight, bool maximized)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    static int attrList[] = {
 | 
					 | 
				
			||||||
        GLX_USE_GL,
 | 
					 | 
				
			||||||
        GLX_RGBA,
 | 
					 | 
				
			||||||
        GLX_DOUBLEBUFFER,
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // choose OpenGL, RGBA, double buffered, visual
 | 
					 | 
				
			||||||
    x11.visual = glXChooseVisual(x11.display, DefaultScreen(x11.display), attrList);
 | 
					 | 
				
			||||||
    if(!x11.visual)
 | 
					 | 
				
			||||||
        logFatal("RGBA/Double buffered visual not supported");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // create GLX context
 | 
					 | 
				
			||||||
    x11.glxContext = glXCreateContext(x11.display, x11.visual, NULL, True);
 | 
					 | 
				
			||||||
    if(!x11.glxContext)
 | 
					 | 
				
			||||||
        logFatal("Unable to create GLX context");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    logInfo("Direct rendering: ", glXIsDirect(x11.display, x11.glxContext) ? "Yes" : "No");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // color map
 | 
					 | 
				
			||||||
    x11.colormap  = XCreateColormap(x11.display,
 | 
					 | 
				
			||||||
                                    RootWindow(x11.display, x11.visual->screen),
 | 
					 | 
				
			||||||
                                    x11.visual->visual,
 | 
					 | 
				
			||||||
                                    AllocNone);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // setup window type
 | 
					 | 
				
			||||||
    XSetWindowAttributes attr;
 | 
					 | 
				
			||||||
    attr.colormap = x11.colormap;
 | 
					 | 
				
			||||||
    attr.border_pixel = 0;
 | 
					 | 
				
			||||||
    attr.event_mask = KeyPressMask | KeyReleaseMask |
 | 
					 | 
				
			||||||
                         ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
 | 
					 | 
				
			||||||
                         ExposureMask | VisibilityChangeMask |
 | 
					 | 
				
			||||||
                         StructureNotifyMask | FocusChangeMask;
 | 
					 | 
				
			||||||
    unsigned int mask = CWBorderPixel | CWColormap | CWEventMask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.x = x;
 | 
					 | 
				
			||||||
    x11.y = y;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // create the window
 | 
					 | 
				
			||||||
    x11.window = XCreateWindow(x11.display,
 | 
					 | 
				
			||||||
                             RootWindow(x11.display, x11.visual->screen),
 | 
					 | 
				
			||||||
                             0, 0,
 | 
					 | 
				
			||||||
                             width, height,
 | 
					 | 
				
			||||||
                             0,
 | 
					 | 
				
			||||||
                             x11.visual->depth,
 | 
					 | 
				
			||||||
                             InputOutput,
 | 
					 | 
				
			||||||
                             x11.visual->visual,
 | 
					 | 
				
			||||||
                             mask,
 | 
					 | 
				
			||||||
                             &attr);
 | 
					 | 
				
			||||||
    if(!x11.window)
 | 
					 | 
				
			||||||
        logFatal("XCreateWindow failed");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //  create input context (to have better key input handling)
 | 
					 | 
				
			||||||
    if(XSupportsLocale()) {
 | 
					 | 
				
			||||||
        XSetLocaleModifiers("");
 | 
					 | 
				
			||||||
        x11.xim = XOpenIM(x11.display, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
        if(x11.xim) {
 | 
					 | 
				
			||||||
            x11.xic = XCreateIC(x11.xim,
 | 
					 | 
				
			||||||
                                    XNInputStyle,
 | 
					 | 
				
			||||||
                                    XIMPreeditNothing | XIMStatusNothing,
 | 
					 | 
				
			||||||
                                    XNClientWindow, x11.window, NULL);
 | 
					 | 
				
			||||||
            if(!x11.xic)
 | 
					 | 
				
			||||||
                logError("Unable to create the input context");
 | 
					 | 
				
			||||||
        } else
 | 
					 | 
				
			||||||
            logError("Failed to open an input method");
 | 
					 | 
				
			||||||
    } else
 | 
					 | 
				
			||||||
        logError("X11 does not support the current locale");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(!x11.xic)
 | 
					 | 
				
			||||||
        logWarning("Input of special keys maybe messed up because we couldn't create an input context");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // set window minimum size
 | 
					 | 
				
			||||||
    XSizeHints xsizehints;
 | 
					 | 
				
			||||||
    xsizehints.flags = PMinSize;
 | 
					 | 
				
			||||||
    xsizehints.min_width = minWidth;
 | 
					 | 
				
			||||||
    xsizehints.min_height= minHeight;
 | 
					 | 
				
			||||||
    XSetWMSizeHints(x11.display, x11.window, &xsizehints, XA_WM_NORMAL_HINTS);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // handle delete window event
 | 
					 | 
				
			||||||
    x11.atomDeleteWindow = XInternAtom(x11.display, "WM_DELETE_WINDOW", True);
 | 
					 | 
				
			||||||
    XSetWMProtocols(x11.display, x11.window, &x11.atomDeleteWindow , 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // connect the GLX-context to the window
 | 
					 | 
				
			||||||
    if(!glXMakeCurrent(x11.display, x11.window, x11.glxContext))
 | 
					 | 
				
			||||||
        logFatal("glXMakeCurrent failed");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    x11.width = width;
 | 
					 | 
				
			||||||
    x11.height = height;
 | 
					 | 
				
			||||||
    x11.maximizeOnFirstShow = maximized;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // call first onResize
 | 
					 | 
				
			||||||
    x11.listener->onResize(Size(width, height));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::setWindowIcon(const std::string& pngIcon)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    apng_data apng;
 | 
					 | 
				
			||||||
    std::stringstream fin;
 | 
					 | 
				
			||||||
    g_resources.loadFile(pngIcon, fin);
 | 
					 | 
				
			||||||
    if(load_apng(fin, &apng) == 0) {
 | 
					 | 
				
			||||||
        if(apng.bpp != 4) {
 | 
					 | 
				
			||||||
            logError("could not set app icon, icon image must have 4 channels");
 | 
					 | 
				
			||||||
            free_apng(&apng);
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int n = apng.width * apng.height;
 | 
					 | 
				
			||||||
        std::vector<unsigned long int> iconData(n + 2);
 | 
					 | 
				
			||||||
        iconData[0] = apng.width;
 | 
					 | 
				
			||||||
        iconData[1] = apng.height;
 | 
					 | 
				
			||||||
        for(int i=0; i < n;++i) {
 | 
					 | 
				
			||||||
            uint8 *pixel = (uint8*)&iconData[2 + i];
 | 
					 | 
				
			||||||
            pixel[2] = *(apng.pdata + (i * 4) + 0);
 | 
					 | 
				
			||||||
            pixel[1] = *(apng.pdata + (i * 4) + 1);
 | 
					 | 
				
			||||||
            pixel[0] = *(apng.pdata + (i * 4) + 2);
 | 
					 | 
				
			||||||
            pixel[3] = *(apng.pdata + (i * 4) + 3);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Atom property = XInternAtom(x11.display, "_NET_WM_ICON", 0);
 | 
					 | 
				
			||||||
        if(!XChangeProperty(x11.display, x11.window, property, XA_CARDINAL, 32, PropModeReplace, (const unsigned char*)&iconData[0], iconData.size()))
 | 
					 | 
				
			||||||
            logError("Couldn't set app icon");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        free_apng(&apng);
 | 
					 | 
				
			||||||
    } else
 | 
					 | 
				
			||||||
        logError("Couldn't load app icon");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::destroyWindow()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if(x11.glxContext) {
 | 
					 | 
				
			||||||
        glXMakeCurrent(x11.display, None, NULL);
 | 
					 | 
				
			||||||
        glXDestroyContext(x11.display, x11.glxContext);
 | 
					 | 
				
			||||||
        x11.glxContext = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(x11.visual) {
 | 
					 | 
				
			||||||
        XFree(x11.visual);
 | 
					 | 
				
			||||||
        x11.visual = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(x11.colormap != None) {
 | 
					 | 
				
			||||||
        XFreeColormap(x11.display, x11.colormap);
 | 
					 | 
				
			||||||
        x11.colormap = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(x11.window != None) {
 | 
					 | 
				
			||||||
        XDestroyWindow(x11.display, x11.window);
 | 
					 | 
				
			||||||
        x11.window = None;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(x11.xic) {
 | 
					 | 
				
			||||||
        XDestroyIC(x11.xic);
 | 
					 | 
				
			||||||
        x11.xic = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(x11.xim) {
 | 
					 | 
				
			||||||
        XCloseIM(x11.xim);
 | 
					 | 
				
			||||||
        x11.xim = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::showWindow()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    XMapWindow(x11.display, x11.window);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static bool firstShow = true;
 | 
					 | 
				
			||||||
    if(firstShow) {
 | 
					 | 
				
			||||||
        // move window
 | 
					 | 
				
			||||||
        XMoveWindow(x11.display, x11.window, x11.x, x11.y);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // set window maximized if needed
 | 
					 | 
				
			||||||
        if(x11.maximizeOnFirstShow) {
 | 
					 | 
				
			||||||
            XEvent e;
 | 
					 | 
				
			||||||
            memset(&e, 0, sizeof(XEvent));
 | 
					 | 
				
			||||||
            e.xany.type = ClientMessage;
 | 
					 | 
				
			||||||
            e.xclient.message_type = x11.atomWindowState;
 | 
					 | 
				
			||||||
            e.xclient.format = 32;
 | 
					 | 
				
			||||||
            e.xclient.window = x11.window;
 | 
					 | 
				
			||||||
            e.xclient.data.l[0] = 1l;
 | 
					 | 
				
			||||||
            e.xclient.data.l[1] = x11.atomWindowMaximizedVert;
 | 
					 | 
				
			||||||
            e.xclient.data.l[2] = x11.atomWindowMaximizedHorz;
 | 
					 | 
				
			||||||
            e.xclient.data.l[3] = 0l;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            XSendEvent(x11.display, RootWindow(x11.display, x11.visual->screen), 0,
 | 
					 | 
				
			||||||
                    SubstructureNotifyMask | SubstructureRedirectMask, &e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        firstShow = false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::hideWindow()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    XUnmapWindow(x11.display, x11.window);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::setWindowTitle(const char *title)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    XStoreName(x11.display, x11.window, title);
 | 
					 | 
				
			||||||
    XSetIconName(x11.display, x11.window, title);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void *Platform::getExtensionProcAddress(const char *ext)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return (void*)glXGetProcAddressARB((const GLubyte*)ext);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Platform::isExtensionSupported(const char *ext)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    const char *exts = glXQueryExtensionsString(x11.display, DefaultScreen(x11.display));
 | 
					 | 
				
			||||||
    if(strstr(exts, ext))
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const char *Platform::getClipboardText()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    Window ownerWindow = XGetSelectionOwner(x11.display, x11.atomClipboard);
 | 
					 | 
				
			||||||
    if(ownerWindow ==  x11.window)
 | 
					 | 
				
			||||||
        return x11.clipboardText.c_str();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::string clipboard = "";
 | 
					 | 
				
			||||||
    if(ownerWindow != None) {
 | 
					 | 
				
			||||||
        XConvertSelection(x11.display, x11.atomClipboard, XA_STRING, 0, ownerWindow, CurrentTime);
 | 
					 | 
				
			||||||
        XFlush(x11.display);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // hack to wait SelectioNotify event, otherwise we will get wrong clipboard pastes
 | 
					 | 
				
			||||||
        usleep(100 * 1000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // check for data
 | 
					 | 
				
			||||||
        Atom type;
 | 
					 | 
				
			||||||
        int format;
 | 
					 | 
				
			||||||
        ulong numItems, bytesLeft, dummy;
 | 
					 | 
				
			||||||
        uchar *data;
 | 
					 | 
				
			||||||
        XGetWindowProperty(x11.display, ownerWindow,
 | 
					 | 
				
			||||||
                            XA_STRING,
 | 
					 | 
				
			||||||
                            0, 0, 0,
 | 
					 | 
				
			||||||
                            AnyPropertyType,
 | 
					 | 
				
			||||||
                            &type,
 | 
					 | 
				
			||||||
                            &format,
 | 
					 | 
				
			||||||
                            &numItems,
 | 
					 | 
				
			||||||
                            &bytesLeft,
 | 
					 | 
				
			||||||
                            &data);
 | 
					 | 
				
			||||||
        if(bytesLeft > 0)  {
 | 
					 | 
				
			||||||
            // get the data get
 | 
					 | 
				
			||||||
            int result = XGetWindowProperty(x11.display, ownerWindow,
 | 
					 | 
				
			||||||
                                            XA_STRING,
 | 
					 | 
				
			||||||
                                            0,
 | 
					 | 
				
			||||||
                                            bytesLeft,
 | 
					 | 
				
			||||||
                                            0,
 | 
					 | 
				
			||||||
                                            AnyPropertyType,
 | 
					 | 
				
			||||||
                                            &type,
 | 
					 | 
				
			||||||
                                            &format,
 | 
					 | 
				
			||||||
                                            &numItems,
 | 
					 | 
				
			||||||
                                            &dummy,
 | 
					 | 
				
			||||||
                                            &data);
 | 
					 | 
				
			||||||
            if(result == Success)
 | 
					 | 
				
			||||||
                clipboard = (const char*)data;
 | 
					 | 
				
			||||||
            XFree(data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return clipboard.c_str();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::setClipboardText(const char *text)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    x11.clipboardText = text;
 | 
					 | 
				
			||||||
    XSetSelectionOwner(x11.display, x11.atomClipboard, x11.window, CurrentTime);
 | 
					 | 
				
			||||||
    XFlush(x11.display);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::hideMouseCursor()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if(x11.cursor == None) {
 | 
					 | 
				
			||||||
        char bm[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 | 
					 | 
				
			||||||
        Pixmap pix = XCreateBitmapFromData(x11.display, x11.window, bm, 8, 8);
 | 
					 | 
				
			||||||
        XColor black;
 | 
					 | 
				
			||||||
        memset(&black, 0, sizeof(XColor));
 | 
					 | 
				
			||||||
        black.flags = DoRed | DoGreen | DoBlue;
 | 
					 | 
				
			||||||
        x11.cursor = XCreatePixmapCursor(x11.display, pix, pix, &black, &black, 0, 0);
 | 
					 | 
				
			||||||
        XFreePixmap(x11.display, pix);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    XDefineCursor(x11.display, x11.window, x11.cursor);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::showMouseCursor()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    XUndefineCursor(x11.display, x11.window);
 | 
					 | 
				
			||||||
    if(x11.cursor != None) {
 | 
					 | 
				
			||||||
        XFreeCursor(x11.display, x11.cursor);
 | 
					 | 
				
			||||||
        x11.cursor = None;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Point Platform::getMouseCursorPos()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return x11.platformEvent.mousePos;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::setVerticalSync(bool enable)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    typedef GLint (*glSwapIntervalProc)(GLint);
 | 
					 | 
				
			||||||
    glSwapIntervalProc glSwapInterval = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(isExtensionSupported("GLX_MESA_swap_control"))
 | 
					 | 
				
			||||||
        glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalMESA");
 | 
					 | 
				
			||||||
    else if(isExtensionSupported("GLX_SGI_swap_control"))
 | 
					 | 
				
			||||||
        glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalSGI");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(glSwapInterval)
 | 
					 | 
				
			||||||
        glSwapInterval(enable ? 1 : 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::swapBuffers()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    //glFlush();
 | 
					 | 
				
			||||||
    //glFinish();
 | 
					 | 
				
			||||||
    glXSwapBuffers(x11.display, x11.window);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Platform::isWindowFocused()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return x11.focused;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Platform::isWindowVisible()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return x11.visible;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int Platform::getWindowX()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return x11.x;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int Platform::getWindowY()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return x11.y;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int Platform::getWindowWidth()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return x11.width;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int Platform::getWindowHeight()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return x11.height;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int Platform::getDisplayWidth()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return XDisplayWidth(x11.display, DefaultScreen(x11.display));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int Platform::getDisplayHeight()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return XDisplayHeight(x11.display, DefaultScreen(x11.display));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Platform::isWindowMaximized()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    bool ret = false;
 | 
					 | 
				
			||||||
    Atom actualType;
 | 
					 | 
				
			||||||
    int actualFormat;
 | 
					 | 
				
			||||||
    ulong i, numItems, bytesAfter;
 | 
					 | 
				
			||||||
    uchar *propertyValue = NULL;
 | 
					 | 
				
			||||||
    long maxLength = 1024;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(XGetWindowProperty(x11.display, x11.window, x11.atomWindowState,
 | 
					 | 
				
			||||||
                            0l, maxLength, False, XA_ATOM, &actualType,
 | 
					 | 
				
			||||||
                            &actualFormat, &numItems, &bytesAfter,
 | 
					 | 
				
			||||||
                            &propertyValue) == Success) {
 | 
					 | 
				
			||||||
        Atom *atoms = (Atom *)propertyValue;
 | 
					 | 
				
			||||||
        int maximized = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(i=0; i<numItems; ++i) {
 | 
					 | 
				
			||||||
            if(atoms[i] == x11.atomWindowMaximizedVert)
 | 
					 | 
				
			||||||
                maximized |= 1;
 | 
					 | 
				
			||||||
            else if(atoms[i] == x11.atomWindowMaximizedHorz)
 | 
					 | 
				
			||||||
                maximized |= 2;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if(maximized == 3)
 | 
					 | 
				
			||||||
            ret = true;
 | 
					 | 
				
			||||||
        XFree(propertyValue);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string Platform::getAppUserDir()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    std::stringstream sdir;
 | 
					 | 
				
			||||||
    sdir << PHYSFS_getUserDir() << "." << x11.appName;
 | 
					 | 
				
			||||||
    if((mkdir(sdir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) && (errno != EEXIST))
 | 
					 | 
				
			||||||
        logError("Couldn't create directory for saving configuration file. (",sdir.str(),")");
 | 
					 | 
				
			||||||
    return sdir.str();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Platform::displayFatalError(const std::string& message)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // nothing to do
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,887 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "x11window.h"
 | 
				
			||||||
 | 
					#include <framework/core/resourcemanager.h>
 | 
				
			||||||
 | 
					#include <framework/thirdparty/apngloader.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					X11Window::X11Window()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_cursor = None;
 | 
				
			||||||
 | 
					    m_visual = 0;
 | 
				
			||||||
 | 
					    m_colormap = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_keyMap[XK_Escape] = Fw::KeyEscape;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Tab] = Fw::KeyTab;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Return] = Fw::KeyReturn;
 | 
				
			||||||
 | 
					    m_keyMap[XK_BackSpace] = Fw::KeyBackspace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_keyMap[XK_Page_Up] = Fw::KeyPageUp;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Page_Down] = Fw::KeyPageDown;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Home] = Fw::KeyHome;
 | 
				
			||||||
 | 
					    m_keyMap[XK_End] = Fw::KeyEnd;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Insert] = Fw::KeyInsert;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Delete] = Fw::KeyDelete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_keyMap[XK_Up] = Fw::KeyUp;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Down] = Fw::KeyDown;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Left] = Fw::KeyLeft;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Right] = Fw::KeyRight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_keyMap[XK_Num_Lock] = Fw::KeyNumLock;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Scroll_Lock] = Fw::KeyScrollLock;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Caps_Lock] = Fw::KeyCapsLock;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Print] = Fw::KeyPrintScreen;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Pause] = Fw::KeyPause;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_keyMap[XK_Control_L] = Fw::KeyCtrl;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Control_R] = Fw::KeyCtrl;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Shift_R] = Fw::KeyShift;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Shift_L] = Fw::KeyShift;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Alt_R] = Fw::KeyAlt;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Alt_L] = Fw::KeyAltGr;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Meta_L] = Fw::KeyMeta;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Meta_R] = Fw::KeyMeta;
 | 
				
			||||||
 | 
					    m_keyMap[XK_Menu] = Fw::KeyMenu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ascii characters
 | 
				
			||||||
 | 
					    m_keyMap[XK_space] = Fw::KeySpace;
 | 
				
			||||||
 | 
					    m_keyMap[XK_exclam] = Fw::KeyExclamation;
 | 
				
			||||||
 | 
					    m_keyMap[XK_quotedbl] = Fw::KeyQuote;
 | 
				
			||||||
 | 
					    m_keyMap[XK_numbersign] = Fw::KeyNumberSign;
 | 
				
			||||||
 | 
					    m_keyMap[XK_dollar] = Fw::KeyDollar;
 | 
				
			||||||
 | 
					    m_keyMap[XK_percent] = Fw::KeyPercent;
 | 
				
			||||||
 | 
					    m_keyMap[XK_ampersand] = Fw::KeyAmpersand;
 | 
				
			||||||
 | 
					    m_keyMap[XK_apostrophe] = Fw::KeyApostrophe;
 | 
				
			||||||
 | 
					    m_keyMap[XK_parenleft] = Fw::KeyLeftParen;
 | 
				
			||||||
 | 
					    m_keyMap[XK_parenright] = Fw::KeyRightParen;
 | 
				
			||||||
 | 
					    m_keyMap[XK_asterisk] = Fw::KeyAsterisk;
 | 
				
			||||||
 | 
					    m_keyMap[XK_plus] = Fw::KeyPlus;
 | 
				
			||||||
 | 
					    m_keyMap[XK_comma] = Fw::KeyComma;
 | 
				
			||||||
 | 
					    m_keyMap[XK_minus] = Fw::KeyMinus;
 | 
				
			||||||
 | 
					    m_keyMap[XK_period] = Fw::KeyPeriod;
 | 
				
			||||||
 | 
					    m_keyMap[XK_slash] = Fw::KeySlash;
 | 
				
			||||||
 | 
					    m_keyMap[XK_1] = Fw::Key1;
 | 
				
			||||||
 | 
					    m_keyMap[XK_2] = Fw::Key2;
 | 
				
			||||||
 | 
					    m_keyMap[XK_3] = Fw::Key3;
 | 
				
			||||||
 | 
					    m_keyMap[XK_4] = Fw::Key4;
 | 
				
			||||||
 | 
					    m_keyMap[XK_5] = Fw::Key5;
 | 
				
			||||||
 | 
					    m_keyMap[XK_6] = Fw::Key6;
 | 
				
			||||||
 | 
					    m_keyMap[XK_7] = Fw::Key7;
 | 
				
			||||||
 | 
					    m_keyMap[XK_8] = Fw::Key8;
 | 
				
			||||||
 | 
					    m_keyMap[XK_9] = Fw::Key9;
 | 
				
			||||||
 | 
					    m_keyMap[XK_0] = Fw::Key0;
 | 
				
			||||||
 | 
					    m_keyMap[XK_colon] = Fw::KeyColon;
 | 
				
			||||||
 | 
					    m_keyMap[XK_semicolon] = Fw::KeySemicolon;
 | 
				
			||||||
 | 
					    m_keyMap[XK_less] = Fw::KeyLess;
 | 
				
			||||||
 | 
					    m_keyMap[XK_equal] = Fw::KeyEqual;
 | 
				
			||||||
 | 
					    m_keyMap[XK_greater] = Fw::KeyGreater;
 | 
				
			||||||
 | 
					    m_keyMap[XK_question] = Fw::KeyQuestion;
 | 
				
			||||||
 | 
					    m_keyMap[XK_at] = Fw::KeyAtSign;
 | 
				
			||||||
 | 
					    m_keyMap[XK_a] = Fw::KeyA;
 | 
				
			||||||
 | 
					    m_keyMap[XK_b] = Fw::KeyB;
 | 
				
			||||||
 | 
					    m_keyMap[XK_c] = Fw::KeyC;
 | 
				
			||||||
 | 
					    m_keyMap[XK_d] = Fw::KeyD;
 | 
				
			||||||
 | 
					    m_keyMap[XK_e] = Fw::KeyE;
 | 
				
			||||||
 | 
					    m_keyMap[XK_f] = Fw::KeyF;
 | 
				
			||||||
 | 
					    m_keyMap[XK_g] = Fw::KeyG;
 | 
				
			||||||
 | 
					    m_keyMap[XK_h] = Fw::KeyH;
 | 
				
			||||||
 | 
					    m_keyMap[XK_i] = Fw::KeyI;
 | 
				
			||||||
 | 
					    m_keyMap[XK_j] = Fw::KeyJ;
 | 
				
			||||||
 | 
					    m_keyMap[XK_k] = Fw::KeyK;
 | 
				
			||||||
 | 
					    m_keyMap[XK_l] = Fw::KeyL;
 | 
				
			||||||
 | 
					    m_keyMap[XK_m] = Fw::KeyM;
 | 
				
			||||||
 | 
					    m_keyMap[XK_n] = Fw::KeyN;
 | 
				
			||||||
 | 
					    m_keyMap[XK_o] = Fw::KeyO;
 | 
				
			||||||
 | 
					    m_keyMap[XK_p] = Fw::KeyP;
 | 
				
			||||||
 | 
					    m_keyMap[XK_q] = Fw::KeyQ;
 | 
				
			||||||
 | 
					    m_keyMap[XK_r] = Fw::KeyR;
 | 
				
			||||||
 | 
					    m_keyMap[XK_s] = Fw::KeyS;
 | 
				
			||||||
 | 
					    m_keyMap[XK_t] = Fw::KeyT;
 | 
				
			||||||
 | 
					    m_keyMap[XK_u] = Fw::KeyU;
 | 
				
			||||||
 | 
					    m_keyMap[XK_v] = Fw::KeyV;
 | 
				
			||||||
 | 
					    m_keyMap[XK_w] = Fw::KeyW;
 | 
				
			||||||
 | 
					    m_keyMap[XK_x] = Fw::KeyX;
 | 
				
			||||||
 | 
					    m_keyMap[XK_y] = Fw::KeyY;
 | 
				
			||||||
 | 
					    m_keyMap[XK_z] = Fw::KeyZ;
 | 
				
			||||||
 | 
					    m_keyMap[XK_bracketleft] = Fw::KeyLeftBracket;
 | 
				
			||||||
 | 
					    m_keyMap[XK_backslash] = Fw::KeyBackslash;
 | 
				
			||||||
 | 
					    m_keyMap[XK_bracketright] = Fw::KeyRightBracket;
 | 
				
			||||||
 | 
					    m_keyMap[XK_asciicircum] = Fw::KeyCaret;
 | 
				
			||||||
 | 
					    m_keyMap[XK_underscore] = Fw::KeyUnderscore;
 | 
				
			||||||
 | 
					    m_keyMap[XK_grave] = Fw::KeyGrave;
 | 
				
			||||||
 | 
					    m_keyMap[XK_braceleft] = Fw::KeyLeftCurly;
 | 
				
			||||||
 | 
					    m_keyMap[XK_bar] = Fw::KeyBar;
 | 
				
			||||||
 | 
					    m_keyMap[XK_braceright] = Fw::KeyRightCurly;
 | 
				
			||||||
 | 
					    m_keyMap[XK_asciitilde] = Fw::KeyTilde;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // keypad
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Add] = Fw::KeyPlus;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Subtract] = Fw::KeyMinus;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Decimal] = Fw::KeyPeriod;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Divide] = Fw::KeySlash;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Multiply] = Fw::KeyAsterisk;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Enter] = Fw::KeyEnter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // keypad with numlock off
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Insert] = Fw::KeyNumpad0;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_End] = Fw::KeyNumpad1;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Down] = Fw::KeyNumpad2;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Page_Down] = Fw::KeyNumpad3;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Left] = Fw::KeyNumpad4;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Begin] = Fw::KeyNumpad5;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Right] = Fw::KeyNumpad6;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Home] = Fw::KeyNumpad7;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Up] = Fw::KeyNumpad8;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Page_Up] = Fw::KeyNumpad9;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_Delete] = Fw::KeyDelete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // keypad with numlock on
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_0] = Fw::Key0;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_1] = Fw::Key1;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_2] = Fw::Key2;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_3] = Fw::Key3;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_4] = Fw::Key4;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_5] = Fw::Key5;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_6] = Fw::Key6;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_7] = Fw::Key7;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_8] = Fw::Key8;
 | 
				
			||||||
 | 
					    m_keyMap[XK_KP_9] = Fw::Key9;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_keyMap[XK_F1] = Fw::KeyF1;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F2] = Fw::KeyF2;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F3] = Fw::KeyF3;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F4] = Fw::KeyF4;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F5] = Fw::KeyF5;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F6] = Fw::KeyF6;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F7] = Fw::KeyF7;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F8] = Fw::KeyF8;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F9] = Fw::KeyF9;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F10] = Fw::KeyF10;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F11] = Fw::KeyF11;
 | 
				
			||||||
 | 
					    m_keyMap[XK_F12] = Fw::KeyF12;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::init()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_size = Size(200, 200);
 | 
				
			||||||
 | 
					    internalOpenDisplay();
 | 
				
			||||||
 | 
					    internalCheckGL();
 | 
				
			||||||
 | 
					    internalChooseGLVisual();
 | 
				
			||||||
 | 
					    internalCreateGLContext();
 | 
				
			||||||
 | 
					    internalCreateWindow();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::terminate()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XDestroyWindow(m_display, m_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(m_colormap)
 | 
				
			||||||
 | 
					        XFreeColormap(m_display, m_colormap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internalDestroyGLContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(m_visual)
 | 
				
			||||||
 | 
					        XFree(m_visual);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(m_xic)
 | 
				
			||||||
 | 
					        XDestroyIC(m_xic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(m_xim)
 | 
				
			||||||
 | 
					        XCloseIM(m_xim);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XCloseDisplay(m_display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_visible = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::internalOpenDisplay()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_display = XOpenDisplay(NULL);
 | 
				
			||||||
 | 
					    if(!m_display)
 | 
				
			||||||
 | 
					        logFatal("Unable to open X11 display");
 | 
				
			||||||
 | 
					    m_screen = DefaultScreen(m_display);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::internalCreateWindow()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Visual *vis;
 | 
				
			||||||
 | 
					    int depth;
 | 
				
			||||||
 | 
					    unsigned int attrsMask = CWEventMask;
 | 
				
			||||||
 | 
					    XSetWindowAttributes attrs = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    attrs.event_mask = KeyPressMask | KeyReleaseMask |
 | 
				
			||||||
 | 
					                       ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
 | 
				
			||||||
 | 
					                       ExposureMask | VisibilityChangeMask |
 | 
				
			||||||
 | 
					                       StructureNotifyMask | FocusChangeMask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(m_visual) {
 | 
				
			||||||
 | 
					        m_colormap = XCreateColormap(m_display, m_rootWindow, m_visual->visual, AllocNone);
 | 
				
			||||||
 | 
					        attrs.colormap = m_colormap;
 | 
				
			||||||
 | 
					        attrs.border_pixel = 0;
 | 
				
			||||||
 | 
					        attrsMask |= CWBorderPixel | CWColormap;
 | 
				
			||||||
 | 
					        vis = m_visual->visual;
 | 
				
			||||||
 | 
					        depth = m_visual->depth;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        attrs.override_redirect = False;
 | 
				
			||||||
 | 
					        attrsMask |= CWOverrideRedirect;
 | 
				
			||||||
 | 
					        depth = CopyFromParent;
 | 
				
			||||||
 | 
					        vis = CopyFromParent;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_window = XCreateWindow(m_display, m_rootWindow,
 | 
				
			||||||
 | 
					                             m_pos.x, m_pos.y, m_size.width(), m_size.height(),
 | 
				
			||||||
 | 
					                             0,
 | 
				
			||||||
 | 
					                             depth,
 | 
				
			||||||
 | 
					                             InputOutput,
 | 
				
			||||||
 | 
					                             vis,
 | 
				
			||||||
 | 
					                             attrsMask, &attrs);
 | 
				
			||||||
 | 
					    if(!m_window)
 | 
				
			||||||
 | 
					        logFatal("Unable to create X11 window!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ensure window input focus
 | 
				
			||||||
 | 
					    XWMHints hints;
 | 
				
			||||||
 | 
					    hints.input = True;
 | 
				
			||||||
 | 
					    hints.flags = InputHint;
 | 
				
			||||||
 | 
					    XSetWMHints(m_display, m_window, &hints);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ensure window position
 | 
				
			||||||
 | 
					    XMoveWindow(m_display, m_window, m_pos.x, m_pos.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // handle wm_delete events
 | 
				
			||||||
 | 
					    m_wmDelete = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
 | 
				
			||||||
 | 
					    XSetWMProtocols(m_display, m_window, &m_wmDelete , 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!internalSetupWindowInput())
 | 
				
			||||||
 | 
					        logWarning("Input of special keys may be messed up, because window input initialization failed");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    internalConnectGLContext();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool X11Window::internalSetupWindowInput()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // try to set a latin1 locales, otherwise fallback to standard C locale
 | 
				
			||||||
 | 
					    static char locales[4][32] = { "en_US.iso88591", "iso88591", "en_US", "C" };
 | 
				
			||||||
 | 
					    for(int i=0;i<4;++i) {
 | 
				
			||||||
 | 
					        if(setlocale(LC_ALL, locales[i]))
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //  create input context (to have better key input handling)
 | 
				
			||||||
 | 
					    if(!XSupportsLocale()) {
 | 
				
			||||||
 | 
					        logError("X11 doesn't support the current locale");
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XSetLocaleModifiers("");
 | 
				
			||||||
 | 
					    m_xim = XOpenIM(m_display, NULL, NULL, NULL);
 | 
				
			||||||
 | 
					    if(!m_xim) {
 | 
				
			||||||
 | 
					        logError("XOpenIM failed");
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_xic = XCreateIC(m_xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, m_window, NULL);
 | 
				
			||||||
 | 
					    if(!m_xic) {
 | 
				
			||||||
 | 
					        logError("Unable to create the input context");
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::internalCheckGL()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    if(!glXQueryExtension(m_display, NULL, NULL))
 | 
				
			||||||
 | 
					        logFatal("GLX not supported");
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_display);
 | 
				
			||||||
 | 
					    if(m_eglDisplay == EGL_NO_DISPLAY)
 | 
				
			||||||
 | 
					        logFatal("EGL not supported");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!eglInitialize(m_eglDisplay, NULL, NULL))
 | 
				
			||||||
 | 
					        logFatal("Unable to initialize EGL");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::internalChooseGLVisual()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    static int attrList[] = {
 | 
				
			||||||
 | 
					        GLX_USE_GL,
 | 
				
			||||||
 | 
					        GLX_RGBA,
 | 
				
			||||||
 | 
					        GLX_DOUBLEBUFFER,
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_visual = glXChooseVisual(m_display, m_screen, attrList);
 | 
				
			||||||
 | 
					    if(!m_visual)
 | 
				
			||||||
 | 
					        logFatal("Couldn't choose RGBA, double buffered visual");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_rootWindow = RootWindow(m_display, m_visual->screen);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    static int attrList[] = {
 | 
				
			||||||
 | 
					        EGL_BUFFER_SIZE, 16,
 | 
				
			||||||
 | 
					        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
 | 
				
			||||||
 | 
					        EGL_NONE
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EGLint numConfig;
 | 
				
			||||||
 | 
					    if(!eglChooseConfig(m_eglDisplay, attrList, &m_eglConfig, 1, &numConfig))
 | 
				
			||||||
 | 
					        logFatal("Failed to choose EGL config");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(numConfig != 1)
 | 
				
			||||||
 | 
					        logWarning("Didn't got the exact EGL config");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_rootWindow = DefaultRootWindow(m_display);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::internalCreateGLContext()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    m_glxContext = glXCreateContext(m_display, m_visual, NULL, True);
 | 
				
			||||||
 | 
					    if(!m_glxContext)
 | 
				
			||||||
 | 
					        logFatal("Unable to create GLX context");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!glXIsDirect(m_display, m_glxContext))
 | 
				
			||||||
 | 
					        logWarning("GL direct rendering is not possible");
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    EGLint attrList[] = {
 | 
				
			||||||
 | 
					        EGL_CONTEXT_CLIENT_VERSION, 2,
 | 
				
			||||||
 | 
					        EGL_NONE
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attrList);
 | 
				
			||||||
 | 
					    if(m_eglContext == EGL_NO_CONTEXT )
 | 
				
			||||||
 | 
					        logFatal("Unable to create EGL context: ", eglGetError());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::internalDestroyGLContext()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    glXMakeCurrent(m_display, None, NULL);
 | 
				
			||||||
 | 
					    glXDestroyContext(m_display, m_glxContext);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    eglDestroyContext(m_eglDisplay, m_eglContext);
 | 
				
			||||||
 | 
					    eglDestroySurface(m_eglDisplay, m_eglSurface);
 | 
				
			||||||
 | 
					    eglTerminate(m_eglDisplay);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::internalConnectGLContext()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    if(!glXMakeCurrent(m_display, m_window, m_glxContext))
 | 
				
			||||||
 | 
					        logFatal("Unable to set GLX context on X11 window");
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_window, NULL);
 | 
				
			||||||
 | 
					    if(m_eglSurface == EGL_NO_SURFACE)
 | 
				
			||||||
 | 
					        logFatal("Unable to create EGL surface: ", eglGetError());
 | 
				
			||||||
 | 
					    if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
 | 
				
			||||||
 | 
					        logFatal("Unable to connect EGL context into X11 window");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *X11Window::getExtensionProcAddress(const char *ext)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    return (void *)glXGetProcAddressARB((const GLubyte*)ext);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    //TODO
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool X11Window::isExtensionSupported(const char *ext)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    const char *exts = glXQueryExtensionsString(m_display, m_screen);
 | 
				
			||||||
 | 
					    if(strstr(exts, ext))
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    //TODO
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::move(const Point& pos)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XMoveWindow(m_display, m_window, pos.x, pos.y);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::resize(const Size& size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XResizeWindow(m_display, m_window, size.width(), size.height());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::show()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XMapWindow(m_display, m_window);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::hide()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XUnmapWindow(m_display, m_window);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::maximize()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False);
 | 
				
			||||||
 | 
					    Atom wmStateMaximizedVert = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
 | 
				
			||||||
 | 
					    Atom wmStateMaximizedHorz = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XEvent e = {0};
 | 
				
			||||||
 | 
					    e.xany.type = ClientMessage;
 | 
				
			||||||
 | 
					    e.xclient.send_event = True;
 | 
				
			||||||
 | 
					    e.xclient.message_type = wmState;
 | 
				
			||||||
 | 
					    e.xclient.format = 32;
 | 
				
			||||||
 | 
					    e.xclient.window = m_window;
 | 
				
			||||||
 | 
					    e.xclient.data.l[0] = 1;
 | 
				
			||||||
 | 
					    e.xclient.data.l[1] = wmStateMaximizedVert;
 | 
				
			||||||
 | 
					    e.xclient.data.l[2] = wmStateMaximizedHorz;
 | 
				
			||||||
 | 
					    e.xclient.data.l[3] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XSendEvent(m_display, m_rootWindow, 0, SubstructureNotifyMask | SubstructureRedirectMask, &e);
 | 
				
			||||||
 | 
					    XFlush(m_display);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::poll()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool needsResizeUpdate = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XEvent event, peekEvent;
 | 
				
			||||||
 | 
					    while(XPending(m_display) > 0) {
 | 
				
			||||||
 | 
					        XNextEvent(m_display, &event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // call filter because xim will discard KeyPress events when keys still composing
 | 
				
			||||||
 | 
					        if(XFilterEvent(&event, m_window))
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // discard events of repeated key releases
 | 
				
			||||||
 | 
					        if(event.type == KeyRelease && XPending(m_display)) {
 | 
				
			||||||
 | 
					            XPeekEvent(m_display, &peekEvent);
 | 
				
			||||||
 | 
					            if((peekEvent.type == KeyPress) &&
 | 
				
			||||||
 | 
					              (peekEvent.xkey.keycode == event.xkey.keycode) &&
 | 
				
			||||||
 | 
					              ((peekEvent.xkey.time-event.xkey.time) < 2))
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // reset inputEvent values, except keyboardModifiers and mousePos
 | 
				
			||||||
 | 
					        m_inputEvent.type = Fw::NoInputEvent;
 | 
				
			||||||
 | 
					        m_inputEvent.mouseButton = Fw::MouseNoButton;
 | 
				
			||||||
 | 
					        m_inputEvent.keyCode = Fw::KeyUnknown;
 | 
				
			||||||
 | 
					        m_inputEvent.keyText = "";
 | 
				
			||||||
 | 
					        m_inputEvent.mouseMoved = Point();
 | 
				
			||||||
 | 
					        m_inputEvent.wheelDirection = Fw::MouseNoWheel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch(event.type) {
 | 
				
			||||||
 | 
					            case ClientMessage: {
 | 
				
			||||||
 | 
					                // close event
 | 
				
			||||||
 | 
					                if((Atom)event.xclient.data.l[0] == m_wmDelete && m_onClose)
 | 
				
			||||||
 | 
					                    m_onClose();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case ConfigureNotify: {
 | 
				
			||||||
 | 
					                Size newSize(event.xconfigure.width, event.xconfigure.height);
 | 
				
			||||||
 | 
					                Point newPos(event.xconfigure.x, event.xconfigure.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // updates window size
 | 
				
			||||||
 | 
					                if(m_size != newSize) {
 | 
				
			||||||
 | 
					                    m_size = newSize;
 | 
				
			||||||
 | 
					                    needsResizeUpdate = true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // updates window pos
 | 
				
			||||||
 | 
					                if(m_pos != newPos && !isMaximized())
 | 
				
			||||||
 | 
					                    m_pos = newPos;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case SelectionRequest: {
 | 
				
			||||||
 | 
					                XEvent respond;
 | 
				
			||||||
 | 
					                XSelectionRequestEvent *req = &(event.xselectionrequest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Atom targets = XInternAtom(m_display, "TARGETS", False);
 | 
				
			||||||
 | 
					                if(req->target == targets) {
 | 
				
			||||||
 | 
					                    Atom typeList[] = { XInternAtom(m_display, "UTF8_STRING", False),
 | 
				
			||||||
 | 
					                                        XInternAtom(m_display, "TEXT", False),
 | 
				
			||||||
 | 
					                                        XInternAtom(m_display, "COMPOUND_TEXT", False),
 | 
				
			||||||
 | 
					                                        XA_STRING };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    XChangeProperty(m_display, req->requestor,
 | 
				
			||||||
 | 
					                                    req->property, req->target,
 | 
				
			||||||
 | 
					                                    8, PropModeReplace,
 | 
				
			||||||
 | 
					                                    (uchar *)&typeList,
 | 
				
			||||||
 | 
					                                    sizeof(typeList));
 | 
				
			||||||
 | 
					                    respond.xselection.property = req->property;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    XChangeProperty(m_display,
 | 
				
			||||||
 | 
					                                    req->requestor,
 | 
				
			||||||
 | 
					                                    req->property, req->target,
 | 
				
			||||||
 | 
					                                    8,
 | 
				
			||||||
 | 
					                                    PropModeReplace,
 | 
				
			||||||
 | 
					                                    (uchar *)m_clipboardText.c_str(),
 | 
				
			||||||
 | 
					                                    m_clipboardText.length());
 | 
				
			||||||
 | 
					                    respond.xselection.property = req->property;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                respond.xselection.type = SelectionNotify;
 | 
				
			||||||
 | 
					                respond.xselection.display = req->display;
 | 
				
			||||||
 | 
					                respond.xselection.requestor = req->requestor;
 | 
				
			||||||
 | 
					                respond.xselection.selection = req->selection;
 | 
				
			||||||
 | 
					                respond.xselection.target = req->target;
 | 
				
			||||||
 | 
					                respond.xselection.time = req->time;
 | 
				
			||||||
 | 
					                XSendEvent(m_display, req->requestor, 0, 0, &respond);
 | 
				
			||||||
 | 
					                XFlush(m_display);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case KeyPress:
 | 
				
			||||||
 | 
					            case KeyRelease: {
 | 
				
			||||||
 | 
					                KeySym keysym;
 | 
				
			||||||
 | 
					                char buf[32];
 | 
				
			||||||
 | 
					                int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                m_inputEvent.keyboardModifiers = 0;
 | 
				
			||||||
 | 
					                if(event.xkey.state & ControlMask)
 | 
				
			||||||
 | 
					                    m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier;
 | 
				
			||||||
 | 
					                if(event.xkey.state & ShiftMask)
 | 
				
			||||||
 | 
					                    m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier;
 | 
				
			||||||
 | 
					                if(event.xkey.state & Mod1Mask)
 | 
				
			||||||
 | 
					                    m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // lookup for keyText
 | 
				
			||||||
 | 
					                if(event.type == KeyPress && !(event.xkey.state & ControlMask) && !(event.xkey.state & Mod1Mask)) {
 | 
				
			||||||
 | 
					                    if(m_xic) { // with xim we can get latin1 input correctly
 | 
				
			||||||
 | 
					                        Status status;
 | 
				
			||||||
 | 
					                        len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status);
 | 
				
			||||||
 | 
					                    } else { // otherwise use XLookupString, but often it doesn't work right with dead keys
 | 
				
			||||||
 | 
					                        static XComposeStatus compose = {NULL, 0};
 | 
				
			||||||
 | 
					                        len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(len > 0 &&
 | 
				
			||||||
 | 
					                        // these keys produces characters that we don't want to capture
 | 
				
			||||||
 | 
					                        keysym != XK_BackSpace &&
 | 
				
			||||||
 | 
					                        keysym != XK_Return &&
 | 
				
			||||||
 | 
					                        keysym != XK_Delete &&
 | 
				
			||||||
 | 
					                        keysym != XK_Escape &&
 | 
				
			||||||
 | 
					                        (uchar)(buf[0]) >= 32
 | 
				
			||||||
 | 
					                    ) {
 | 
				
			||||||
 | 
					                        //logDebug("char: ", buf[0], " code: ", (uint)buf[0]);
 | 
				
			||||||
 | 
					                        m_inputEvent.keyText = buf;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(m_keyMap.find(keysym) != m_keyMap.end())
 | 
				
			||||||
 | 
					                    m_inputEvent.keyCode = m_keyMap[keysym];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                m_inputEvent.type = (event.type == KeyPress) ? Fw::KeyPressInputEvent : Fw::KeyReleaseInputEvent;
 | 
				
			||||||
 | 
					                if(m_inputEvent.keyCode != Fw::KeyUnknown || !m_inputEvent.keyText.empty())
 | 
				
			||||||
 | 
					                    m_onInputEvent(m_inputEvent);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case ButtonPress:
 | 
				
			||||||
 | 
					            case ButtonRelease: {
 | 
				
			||||||
 | 
					                m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent;
 | 
				
			||||||
 | 
					                switch(event.xbutton.button) {
 | 
				
			||||||
 | 
					                    case Button1:
 | 
				
			||||||
 | 
					                        m_inputEvent.mouseButton = Fw::MouseLeftButton;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case Button3:
 | 
				
			||||||
 | 
					                        m_inputEvent.mouseButton = Fw::MouseRightButton;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case Button2:
 | 
				
			||||||
 | 
					                        m_inputEvent.mouseButton = Fw::MouseMidButton;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case Button4:
 | 
				
			||||||
 | 
					                        m_inputEvent.type = Fw::MouseWheelInputEvent;
 | 
				
			||||||
 | 
					                        m_inputEvent.mouseButton = Fw::MouseMidButton;
 | 
				
			||||||
 | 
					                        m_inputEvent.wheelDirection = Fw::MouseWheelUp;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case Button5:
 | 
				
			||||||
 | 
					                        m_inputEvent.type = Fw::MouseWheelInputEvent;
 | 
				
			||||||
 | 
					                        m_inputEvent.mouseButton = Fw::MouseMidButton;
 | 
				
			||||||
 | 
					                        m_inputEvent.wheelDirection = Fw::MouseWheelDown;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    default:
 | 
				
			||||||
 | 
					                        m_inputEvent.type = Fw::NoInputEvent;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if(m_inputEvent.type != Fw::NoInputEvent && m_onInputEvent)
 | 
				
			||||||
 | 
					                    m_onInputEvent(m_inputEvent);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            case MotionNotify: {
 | 
				
			||||||
 | 
					                m_inputEvent.type = Fw::MouseMoveInputEvent;
 | 
				
			||||||
 | 
					                Point newMousePos(event.xbutton.x, event.xbutton.y);
 | 
				
			||||||
 | 
					                m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
 | 
				
			||||||
 | 
					                m_inputEvent.mousePos = newMousePos;
 | 
				
			||||||
 | 
					                if(m_onInputEvent)
 | 
				
			||||||
 | 
					                    m_onInputEvent(m_inputEvent);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case MapNotify:
 | 
				
			||||||
 | 
					                m_visible = true;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case UnmapNotify:
 | 
				
			||||||
 | 
					                m_visible = false;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case FocusIn:
 | 
				
			||||||
 | 
					                m_focused = true;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case FocusOut:
 | 
				
			||||||
 | 
					                m_focused = false;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case Expose:
 | 
				
			||||||
 | 
					                // window needs redraw
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(needsResizeUpdate && m_onResize)
 | 
				
			||||||
 | 
					        m_onResize(m_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::swapBuffers()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    glXSwapBuffers(m_display, m_window);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    eglSwapBuffers(m_eglDisplay, m_eglSurface);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::showMouse()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XUndefineCursor(m_display, m_window);
 | 
				
			||||||
 | 
					    if(m_cursor != None) {
 | 
				
			||||||
 | 
					        XFreeCursor(m_display, m_cursor);
 | 
				
			||||||
 | 
					        m_cursor = None;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::hideMouse()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(m_cursor == None) {
 | 
				
			||||||
 | 
					        char bm[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 | 
				
			||||||
 | 
					        Pixmap pix = XCreateBitmapFromData(m_display, m_window, bm, 8, 8);
 | 
				
			||||||
 | 
					        XColor black = {0};
 | 
				
			||||||
 | 
					        black.flags = DoRed | DoGreen | DoBlue;
 | 
				
			||||||
 | 
					        m_cursor = XCreatePixmapCursor(m_display, pix, pix, &black, &black, 0, 0);
 | 
				
			||||||
 | 
					        XFreePixmap(m_display, pix);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    XDefineCursor(m_display, m_window, m_cursor);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::setTitle(const std::string& title)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XStoreName(m_display, m_window, title.c_str());
 | 
				
			||||||
 | 
					    XSetIconName(m_display, m_window, title.c_str());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::setMinimumSize(const Size& minimumSize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XSizeHints sizeHints = {0};
 | 
				
			||||||
 | 
					    sizeHints.flags = PMinSize;
 | 
				
			||||||
 | 
					    sizeHints.min_width = minimumSize.width();
 | 
				
			||||||
 | 
					    sizeHints.min_height= minimumSize.height();
 | 
				
			||||||
 | 
					    XSetWMSizeHints(m_display, m_window, &sizeHints, XA_WM_NORMAL_HINTS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::setFullscreen(bool fullscreen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(m_fullscreen != fullscreen) {
 | 
				
			||||||
 | 
					        Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False);
 | 
				
			||||||
 | 
					        Atom wmStateFullscreen = XInternAtom(m_display, "_NET_WM_STATE_FULLSCREEN", False);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        XEvent xev;
 | 
				
			||||||
 | 
					        xev.xclient.type = ClientMessage;
 | 
				
			||||||
 | 
					        xev.xclient.serial = 0;
 | 
				
			||||||
 | 
					        xev.xclient.send_event = True;
 | 
				
			||||||
 | 
					        xev.xclient.window = m_window;
 | 
				
			||||||
 | 
					        xev.xclient.message_type = wmState;
 | 
				
			||||||
 | 
					        xev.xclient.format = 32;
 | 
				
			||||||
 | 
					        xev.xclient.data.l[0] = fullscreen ? 1 : 0;
 | 
				
			||||||
 | 
					        xev.xclient.data.l[1] = wmStateFullscreen;
 | 
				
			||||||
 | 
					        xev.xclient.data.l[2] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        XSendEvent(m_display, m_rootWindow, False,  SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 | 
				
			||||||
 | 
					        XFlush(m_display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        m_fullscreen = fullscreen;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::setVerticalSync(bool enable)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    typedef GLint (*glSwapIntervalProc)(GLint);
 | 
				
			||||||
 | 
					    glSwapIntervalProc glSwapInterval = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(isExtensionSupported("GLX_MESA_swap_control"))
 | 
				
			||||||
 | 
					        glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalMESA");
 | 
				
			||||||
 | 
					    else if(isExtensionSupported("GLX_SGI_swap_control"))
 | 
				
			||||||
 | 
					        glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("glXSwapIntervalSGI");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(glSwapInterval)
 | 
				
			||||||
 | 
					        glSwapInterval(enable ? 1 : 0);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    //TODO
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::setIcon(const std::string& iconFile)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::stringstream fin;
 | 
				
			||||||
 | 
					    g_resources.loadFile(iconFile, fin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    apng_data apng;
 | 
				
			||||||
 | 
					    if(load_apng(fin, &apng) != 0) {
 | 
				
			||||||
 | 
					        logError("Unable to load window icon");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(apng.bpp != 4) {
 | 
				
			||||||
 | 
					        logError("Could not set window icon, icon image must have 4 channels");
 | 
				
			||||||
 | 
					        free_apng(&apng);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int n = apng.width * apng.height;
 | 
				
			||||||
 | 
					    std::vector<unsigned long int> iconData(n + 2);
 | 
				
			||||||
 | 
					    iconData[0] = apng.width;
 | 
				
			||||||
 | 
					    iconData[1] = apng.height;
 | 
				
			||||||
 | 
					    for(int i=0; i < n;++i) {
 | 
				
			||||||
 | 
					        uint8 *pixel = (uint8*)&iconData[2 + i];
 | 
				
			||||||
 | 
					        pixel[2] = *(apng.pdata + (i * 4) + 0);
 | 
				
			||||||
 | 
					        pixel[1] = *(apng.pdata + (i * 4) + 1);
 | 
				
			||||||
 | 
					        pixel[0] = *(apng.pdata + (i * 4) + 2);
 | 
				
			||||||
 | 
					        pixel[3] = *(apng.pdata + (i * 4) + 3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Atom property = XInternAtom(m_display, "_NET_WM_ICON", 0);
 | 
				
			||||||
 | 
					    if(!XChangeProperty(m_display, m_window, property, XA_CARDINAL, 32, PropModeReplace, (const unsigned char*)&iconData[0], iconData.size()))
 | 
				
			||||||
 | 
					        logError("Couldn't set app icon");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free_apng(&apng);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void X11Window::setClipboardText(const std::string& text)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    m_clipboardText = text;
 | 
				
			||||||
 | 
					    Atom clipboard = XInternAtom(m_display, "CLIPBOARD", False);
 | 
				
			||||||
 | 
					    XSetSelectionOwner(m_display, clipboard, m_window, CurrentTime);
 | 
				
			||||||
 | 
					    XFlush(m_display);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Size X11Window::getDisplaySize()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return Size(XDisplayWidth(m_display, m_screen), XDisplayHeight(m_display, m_screen));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string X11Window::getClipboardText()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Atom clipboard = XInternAtom(m_display, "CLIPBOARD", False);
 | 
				
			||||||
 | 
					    Window ownerWindow = XGetSelectionOwner(m_display, clipboard);
 | 
				
			||||||
 | 
					    if(ownerWindow == m_window)
 | 
				
			||||||
 | 
					        return m_clipboardText;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string clipboardText;
 | 
				
			||||||
 | 
					    if(ownerWindow != None) {
 | 
				
			||||||
 | 
					        XConvertSelection(m_display, clipboard, XA_STRING, 0, ownerWindow, CurrentTime);
 | 
				
			||||||
 | 
					        XFlush(m_display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // hack to wait SelectioNotify event, otherwise we will get wrong clipboard pastes
 | 
				
			||||||
 | 
					        // TODO: fix this in a correct way
 | 
				
			||||||
 | 
					        usleep(100 * 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // check for data
 | 
				
			||||||
 | 
					        Atom type;
 | 
				
			||||||
 | 
					        int format;
 | 
				
			||||||
 | 
					        ulong numItems, bytesLeft, dummy;
 | 
				
			||||||
 | 
					        uchar *data;
 | 
				
			||||||
 | 
					        XGetWindowProperty(m_display, ownerWindow,
 | 
				
			||||||
 | 
					                            XA_STRING,
 | 
				
			||||||
 | 
					                            0, 0, 0,
 | 
				
			||||||
 | 
					                            AnyPropertyType,
 | 
				
			||||||
 | 
					                            &type,
 | 
				
			||||||
 | 
					                            &format,
 | 
				
			||||||
 | 
					                            &numItems,
 | 
				
			||||||
 | 
					                            &bytesLeft,
 | 
				
			||||||
 | 
					                            &data);
 | 
				
			||||||
 | 
					        if(bytesLeft > 0)  {
 | 
				
			||||||
 | 
					            // get the data get
 | 
				
			||||||
 | 
					            int result = XGetWindowProperty(m_display, ownerWindow,
 | 
				
			||||||
 | 
					                                            XA_STRING,
 | 
				
			||||||
 | 
					                                            0,
 | 
				
			||||||
 | 
					                                            bytesLeft,
 | 
				
			||||||
 | 
					                                            0,
 | 
				
			||||||
 | 
					                                            AnyPropertyType,
 | 
				
			||||||
 | 
					                                            &type,
 | 
				
			||||||
 | 
					                                            &format,
 | 
				
			||||||
 | 
					                                            &numItems,
 | 
				
			||||||
 | 
					                                            &dummy,
 | 
				
			||||||
 | 
					                                            &data);
 | 
				
			||||||
 | 
					            if(result == Success)
 | 
				
			||||||
 | 
					                clipboardText = (const char*)data;
 | 
				
			||||||
 | 
					            XFree(data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return clipboardText;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool X11Window::isMaximized()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False);
 | 
				
			||||||
 | 
					    Atom wmStateMaximizedVert = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
 | 
				
			||||||
 | 
					    Atom wmStateMaximizedHorz = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
 | 
				
			||||||
 | 
					    Atom actualType;
 | 
				
			||||||
 | 
					    ulong i, numItems, bytesAfter;
 | 
				
			||||||
 | 
					    uchar *propertyValue = NULL;
 | 
				
			||||||
 | 
					    int actualFormat;
 | 
				
			||||||
 | 
					    bool maximized = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(XGetWindowProperty(m_display, m_window, wmState,
 | 
				
			||||||
 | 
					                          0, 1024, False, XA_ATOM, &actualType,
 | 
				
			||||||
 | 
					                          &actualFormat, &numItems, &bytesAfter,
 | 
				
			||||||
 | 
					                          &propertyValue) == Success) {
 | 
				
			||||||
 | 
					        Atom *atoms = (Atom*)propertyValue;
 | 
				
			||||||
 | 
					        int maximizedMask = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(i=0; i<numItems; ++i) {
 | 
				
			||||||
 | 
					            if(atoms[i] == wmStateMaximizedVert)
 | 
				
			||||||
 | 
					                maximizedMask |= 1;
 | 
				
			||||||
 | 
					            else if(atoms[i] == wmStateMaximizedHorz)
 | 
				
			||||||
 | 
					                maximizedMask |= 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(maximizedMask == 3)
 | 
				
			||||||
 | 
					            maximizedMask = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        XFree(propertyValue);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return maximized;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,106 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef X11WINDOW_H
 | 
				
			||||||
 | 
					#define X11WINDOW_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "platformwindow.h"
 | 
				
			||||||
 | 
					#include <framework/graphics/glutil.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <X11/Xlib.h>
 | 
				
			||||||
 | 
					#include <X11/Xatom.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					#include <GL/glx.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include <EGL/egl.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class X11Window : public PlatformWindow
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void internalOpenDisplay();
 | 
				
			||||||
 | 
					    void internalCreateWindow();
 | 
				
			||||||
 | 
					    bool internalSetupWindowInput();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void internalCheckGL();
 | 
				
			||||||
 | 
					    void internalChooseGLVisual();
 | 
				
			||||||
 | 
					    void internalCreateGLContext();
 | 
				
			||||||
 | 
					    void internalDestroyGLContext();
 | 
				
			||||||
 | 
					    void internalConnectGLContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void *getExtensionProcAddress(const char *ext);
 | 
				
			||||||
 | 
					    bool isExtensionSupported(const char *ext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    X11Window();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void init();
 | 
				
			||||||
 | 
					    void terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void move(const Point& pos);
 | 
				
			||||||
 | 
					    void resize(const Size& size);
 | 
				
			||||||
 | 
					    void show();
 | 
				
			||||||
 | 
					    void hide();
 | 
				
			||||||
 | 
					    void maximize();
 | 
				
			||||||
 | 
					    void poll();
 | 
				
			||||||
 | 
					    void swapBuffers();
 | 
				
			||||||
 | 
					    void showMouse();
 | 
				
			||||||
 | 
					    void hideMouse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void setTitle(const std::string& title);
 | 
				
			||||||
 | 
					    void setMinimumSize(const Size& minimumSize);
 | 
				
			||||||
 | 
					    void setFullscreen(bool fullscreen);
 | 
				
			||||||
 | 
					    void setVerticalSync(bool enable);
 | 
				
			||||||
 | 
					    void setIcon(const std::string& iconFile);
 | 
				
			||||||
 | 
					    void setClipboardText(const std::string& text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Size getDisplaySize();
 | 
				
			||||||
 | 
					    std::string getClipboardText();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool isMaximized();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    Display *m_display;
 | 
				
			||||||
 | 
					    XVisualInfo *m_visual;
 | 
				
			||||||
 | 
					    Window m_window;
 | 
				
			||||||
 | 
					    Window m_rootWindow;
 | 
				
			||||||
 | 
					    Colormap m_colormap;
 | 
				
			||||||
 | 
					    Cursor m_cursor;
 | 
				
			||||||
 | 
					    XIM m_xim;
 | 
				
			||||||
 | 
					    XIC m_xic;
 | 
				
			||||||
 | 
					    int m_screen;
 | 
				
			||||||
 | 
					    Atom m_wmDelete;
 | 
				
			||||||
 | 
					    std::string m_clipboardText;
 | 
				
			||||||
 | 
					    std::map<int, Fw::Key> m_keyMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OPENGL_ES2
 | 
				
			||||||
 | 
					    GLXContext m_glxContext;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    EGLConfig m_eglConfig;
 | 
				
			||||||
 | 
					    EGLContext m_eglContext;
 | 
				
			||||||
 | 
					    EGLDisplay m_eglDisplay;
 | 
				
			||||||
 | 
					    EGLSurface m_eglSurface;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,12 +40,11 @@ void UIFrameCounter::render()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    UIWidget::render();
 | 
					    UIWidget::render();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int now = g_clock.ticks();
 | 
					    if(g_clock.ticksElapsed(m_lastFrameTicks) >= 1000) {
 | 
				
			||||||
    if(now - m_lastFrameTicks >= 1000) {
 | 
					 | 
				
			||||||
        m_fpsText = Fw::mkstr("FPS: ", m_frameCount);
 | 
					        m_fpsText = Fw::mkstr("FPS: ", m_frameCount);
 | 
				
			||||||
        m_lastFrameTicks = now;
 | 
					        m_lastFrameTicks = g_clock.ticks();
 | 
				
			||||||
        m_frameCount = 0;
 | 
					        m_frameCount = 0;
 | 
				
			||||||
    } else
 | 
					    }
 | 
				
			||||||
    m_frameCount++;
 | 
					    m_frameCount++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_font->renderText(m_fpsText, m_rect, m_align, Fw::white);
 | 
					    m_font->renderText(m_fpsText, m_rect, m_align, Fw::white);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ protected:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    Fw::AlignmentFlag m_align;
 | 
					    Fw::AlignmentFlag m_align;
 | 
				
			||||||
    int m_frameCount;
 | 
					    int m_frameCount;
 | 
				
			||||||
    int m_lastFrameTicks;
 | 
					    ticks_t m_lastFrameTicks;
 | 
				
			||||||
    std::string m_fpsText;
 | 
					    std::string m_fpsText;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@
 | 
				
			||||||
#include "uilineedit.h"
 | 
					#include "uilineedit.h"
 | 
				
			||||||
#include <framework/graphics/font.h>
 | 
					#include <framework/graphics/font.h>
 | 
				
			||||||
#include <framework/graphics/graphics.h>
 | 
					#include <framework/graphics/graphics.h>
 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					#include <framework/platform/platformwindow.h>
 | 
				
			||||||
#include <framework/core/clock.h>
 | 
					#include <framework/core/clock.h>
 | 
				
			||||||
#include <framework/otml/otmlnode.h>
 | 
					#include <framework/otml/otmlnode.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,8 +56,7 @@ void UILineEdit::render()
 | 
				
			||||||
        assert(m_cursorPos <= textLength);
 | 
					        assert(m_cursorPos <= textLength);
 | 
				
			||||||
        // draw every 333ms
 | 
					        // draw every 333ms
 | 
				
			||||||
        const int delay = 333;
 | 
					        const int delay = 333;
 | 
				
			||||||
        int ticks = g_clock.ticks();
 | 
					        if(g_clock.ticksElapsed(m_cursorTicks) <= delay) {
 | 
				
			||||||
        if(ticks - m_cursorTicks <= delay) {
 | 
					 | 
				
			||||||
            Rect cursorRect;
 | 
					            Rect cursorRect;
 | 
				
			||||||
            // when cursor is at 0 or is the first visible element
 | 
					            // when cursor is at 0 or is the first visible element
 | 
				
			||||||
            if(m_cursorPos == 0 || m_cursorPos == m_startRenderPos)
 | 
					            if(m_cursorPos == 0 || m_cursorPos == m_startRenderPos)
 | 
				
			||||||
| 
						 | 
					@ -65,8 +64,8 @@ void UILineEdit::render()
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight());
 | 
					                cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight());
 | 
				
			||||||
            g_graphics.drawFilledRect(cursorRect);
 | 
					            g_graphics.drawFilledRect(cursorRect);
 | 
				
			||||||
        } else if(ticks - m_cursorTicks >= 2*delay) {
 | 
					        } else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) {
 | 
				
			||||||
            m_cursorTicks = ticks;
 | 
					            m_cursorTicks = g_clock.ticks();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -407,7 +406,7 @@ void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UILineEdit::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
					bool UILineEdit::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(keyCode == Fw::KeyDelete) // erase right character
 | 
					    if(keyCode == Fw::KeyDelete) // erase right character
 | 
				
			||||||
        removeCharacter(true);
 | 
					        removeCharacter(true);
 | 
				
			||||||
| 
						 | 
					@ -422,14 +421,14 @@ bool UILineEdit::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
				
			||||||
    else if(keyCode == Fw::KeyEnd) // move cursor to last character
 | 
					    else if(keyCode == Fw::KeyEnd) // move cursor to last character
 | 
				
			||||||
        setCursorPos(m_text.length());
 | 
					        setCursorPos(m_text.length());
 | 
				
			||||||
    else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier)
 | 
					    else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier)
 | 
				
			||||||
        appendText(g_platform.getClipboardText());
 | 
					        appendText(g_window.getClipboardText());
 | 
				
			||||||
    else if(keyCode == Fw::KeyTab) {
 | 
					    else if(keyCode == Fw::KeyTab) {
 | 
				
			||||||
        if(!m_alwaysActive) {
 | 
					        if(!m_alwaysActive) {
 | 
				
			||||||
            if(UIWidgetPtr parent = getParent())
 | 
					            if(UIWidgetPtr parent = getParent())
 | 
				
			||||||
                parent->focusNextChild(Fw::TabFocusReason);
 | 
					                parent->focusNextChild(Fw::TabFocusReason);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else if(keyChar != 0)
 | 
					    } else if(!keyText.empty())
 | 
				
			||||||
        appendCharacter(keyChar);
 | 
					        appendText(keyText);
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ protected:
 | 
				
			||||||
    virtual void onStyleApply(const OTMLNodePtr& styleNode);
 | 
					    virtual void onStyleApply(const OTMLNodePtr& styleNode);
 | 
				
			||||||
    virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
 | 
					    virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
 | 
				
			||||||
    virtual void onFocusChange(bool focused, Fw::FocusReason reason);
 | 
					    virtual void onFocusChange(bool focused, Fw::FocusReason reason);
 | 
				
			||||||
    virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
 | 
					    virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
 | 
				
			||||||
    virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
 | 
					    virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ private:
 | 
				
			||||||
    int m_cursorPos;
 | 
					    int m_cursorPos;
 | 
				
			||||||
    Point m_startInternalPos;
 | 
					    Point m_startInternalPos;
 | 
				
			||||||
    int m_startRenderPos;
 | 
					    int m_startRenderPos;
 | 
				
			||||||
    int m_cursorTicks;
 | 
					    ticks_t m_cursorTicks;
 | 
				
			||||||
    int m_textHorizontalMargin;
 | 
					    int m_textHorizontalMargin;
 | 
				
			||||||
    bool m_textHidden;
 | 
					    bool m_textHidden;
 | 
				
			||||||
    bool m_alwaysActive;
 | 
					    bool m_alwaysActive;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,56 +50,32 @@ void UIManager::render()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void UIManager::resize(const Size& size)
 | 
					void UIManager::resize(const Size& size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(m_rootWidget)
 | 
					 | 
				
			||||||
    m_rootWidget->resize(g_graphics.getScreenSize());
 | 
					    m_rootWidget->resize(g_graphics.getScreenSize());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void UIManager::inputEvent(const PlatformEvent& event)
 | 
					void UIManager::inputEvent(const InputEvent& event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // translate input event to ui events
 | 
					    switch(event.type) {
 | 
				
			||||||
    if(m_rootWidget) {
 | 
					        case Fw::KeyPressInputEvent:
 | 
				
			||||||
        if(event.type & EventKeyboardAction) {
 | 
					            m_rootWidget->onKeyPress(event.keyCode, event.keyText, event.keyboardModifiers);
 | 
				
			||||||
            int keyboardModifiers = Fw::KeyboardNoModifier;
 | 
					            break;
 | 
				
			||||||
            if(event.ctrl)
 | 
					        case Fw::KeyReleaseInputEvent:
 | 
				
			||||||
                keyboardModifiers |= Fw::KeyboardCtrlModifier;
 | 
					            m_rootWidget->onKeyRelease(event.keyCode, event.keyText, event.keyboardModifiers);
 | 
				
			||||||
            if(event.shift)
 | 
					            break;
 | 
				
			||||||
                keyboardModifiers |= Fw::KeyboardShiftModifier;
 | 
					        case Fw::MousePressInputEvent:
 | 
				
			||||||
            if(event.alt)
 | 
					            m_rootWidget->onMousePress(event.mousePos, event.mouseButton);
 | 
				
			||||||
                keyboardModifiers |= Fw::KeyboardAltModifier;
 | 
					            break;
 | 
				
			||||||
 | 
					        case Fw::MouseReleaseInputEvent:
 | 
				
			||||||
            if(event.type == EventKeyDown)
 | 
					            m_rootWidget->onMouseRelease(event.mousePos, event.mouseButton);
 | 
				
			||||||
                m_rootWidget->onKeyPress(event.keycode, event.keychar, keyboardModifiers);
 | 
					            break;
 | 
				
			||||||
            else
 | 
					        case Fw::MouseMoveInputEvent:
 | 
				
			||||||
                m_rootWidget->onKeyRelease(event.keycode, event.keychar, keyboardModifiers);
 | 
					 | 
				
			||||||
        } else if(event.type & EventMouseAction) {
 | 
					 | 
				
			||||||
            if(event.type == EventMouseMove) {
 | 
					 | 
				
			||||||
            m_rootWidget->updateState(Fw::HoverState);
 | 
					            m_rootWidget->updateState(Fw::HoverState);
 | 
				
			||||||
            m_rootWidget->onMouseMove(event.mousePos, event.mouseMoved);
 | 
					            m_rootWidget->onMouseMove(event.mousePos, event.mouseMoved);
 | 
				
			||||||
            }
 | 
					            break;
 | 
				
			||||||
            else if(event.type & EventMouseWheel) {
 | 
					        case Fw::MouseWheelInputEvent:
 | 
				
			||||||
                Fw::MouseWheelDirection dir = Fw::MouseNoWheel;
 | 
					            m_rootWidget->onMouseWheel(event.mousePos, event.wheelDirection);
 | 
				
			||||||
                if(event.type & EventDown)
 | 
					            break;
 | 
				
			||||||
                    dir = Fw::MouseWheelDown;
 | 
					    };
 | 
				
			||||||
                else if(event.type & EventUp)
 | 
					 | 
				
			||||||
                    dir = Fw::MouseWheelUp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                m_rootWidget->onMouseWheel(event.mousePos, dir);
 | 
					 | 
				
			||||||
            } else  {
 | 
					 | 
				
			||||||
                Fw::MouseButton button = Fw::MouseNoButton;
 | 
					 | 
				
			||||||
                if(event.type & EventMouseLeftButton)
 | 
					 | 
				
			||||||
                    button = Fw::MouseLeftButton;
 | 
					 | 
				
			||||||
                else if(event.type & EventMouseMidButton)
 | 
					 | 
				
			||||||
                    button = Fw::MouseMidButton;
 | 
					 | 
				
			||||||
                else if(event.type & EventMouseRightButton)
 | 
					 | 
				
			||||||
                    button = Fw::MouseRightButton;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if(event.type & EventDown)
 | 
					 | 
				
			||||||
                    m_rootWidget->onMousePress(event.mousePos, button);
 | 
					 | 
				
			||||||
                else if(event.type & EventUp)
 | 
					 | 
				
			||||||
                    m_rootWidget->onMouseRelease(event.mousePos, button);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UIManager::importStyles(const std::string& file)
 | 
					bool UIManager::importStyles(const std::string& file)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@
 | 
				
			||||||
#define UIMANAGER_H
 | 
					#define UIMANAGER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "declarations.h"
 | 
					#include "declarations.h"
 | 
				
			||||||
#include <framework/platform/platformevent.h>
 | 
					#include <framework/core/inputevent.h>
 | 
				
			||||||
#include <framework/otml/declarations.h>
 | 
					#include <framework/otml/declarations.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UIManager
 | 
					class UIManager
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void render();
 | 
					    void render();
 | 
				
			||||||
    void resize(const Size& size);
 | 
					    void resize(const Size& size);
 | 
				
			||||||
    void inputEvent(const PlatformEvent& event);
 | 
					    void inputEvent(const InputEvent& event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool importStyles(const std::string& file);
 | 
					    bool importStyles(const std::string& file);
 | 
				
			||||||
    void importStyleFromOTML(const OTMLNodePtr& styleNode);
 | 
					    void importStyleFromOTML(const OTMLNodePtr& styleNode);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@
 | 
				
			||||||
#include <framework/graphics/fontmanager.h>
 | 
					#include <framework/graphics/fontmanager.h>
 | 
				
			||||||
#include <framework/otml/otmlnode.h>
 | 
					#include <framework/otml/otmlnode.h>
 | 
				
			||||||
#include <framework/graphics/graphics.h>
 | 
					#include <framework/graphics/graphics.h>
 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					#include <framework/platform/platformwindow.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
UIWidget::UIWidget()
 | 
					UIWidget::UIWidget()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -670,7 +670,7 @@ void UIWidget::updateState(Fw::WidgetState state)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if(state == Fw::HoverState) {
 | 
					    else if(state == Fw::HoverState) {
 | 
				
			||||||
        updateChildren = true;
 | 
					        updateChildren = true;
 | 
				
			||||||
        Point mousePos = g_platform.getMouseCursorPos();
 | 
					        Point mousePos = g_window.getMousePos();
 | 
				
			||||||
        UIWidgetPtr widget = asUIWidget();
 | 
					        UIWidgetPtr widget = asUIWidget();
 | 
				
			||||||
        UIWidgetPtr parent;
 | 
					        UIWidgetPtr parent;
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
| 
						 | 
					@ -971,9 +971,9 @@ void UIWidget::onHoverChange(bool hovered)
 | 
				
			||||||
        g_ui.getRootWidget()->updateState(Fw::HoverState);
 | 
					        g_ui.getRootWidget()->updateState(Fw::HoverState);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UIWidget::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
					bool UIWidget::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(callLuaField<bool>("onKeyPress", keyCode, keyChar, keyboardModifiers))
 | 
					    if(callLuaField<bool>("onKeyPress", keyCode, keyText, keyboardModifiers))
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // do a backup of children list, because it may change while looping it
 | 
					    // do a backup of children list, because it may change while looping it
 | 
				
			||||||
| 
						 | 
					@ -989,16 +989,16 @@ bool UIWidget::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(const UIWidgetPtr& child : children) {
 | 
					    for(const UIWidgetPtr& child : children) {
 | 
				
			||||||
        if(child->onKeyPress(keyCode, keyChar, keyboardModifiers))
 | 
					        if(child->onKeyPress(keyCode, keyText, keyboardModifiers))
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UIWidget::onKeyRelease(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
					bool UIWidget::onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(callLuaField<bool>("onKeyRelease", keyCode, keyChar, keyboardModifiers))
 | 
					    if(callLuaField<bool>("onKeyRelease", keyCode, keyText, keyboardModifiers))
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // do a backup of children list, because it may change while looping it
 | 
					    // do a backup of children list, because it may change while looping it
 | 
				
			||||||
| 
						 | 
					@ -1014,7 +1014,7 @@ bool UIWidget::onKeyRelease(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(const UIWidgetPtr& child : children) {
 | 
					    for(const UIWidgetPtr& child : children) {
 | 
				
			||||||
        if(child->onKeyRelease(keyCode, keyChar, keyboardModifiers))
 | 
					        if(child->onKeyRelease(keyCode, keyText, keyboardModifiers))
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -166,9 +166,9 @@ protected:
 | 
				
			||||||
    /// Triggered when the mouse enters or leaves widget area
 | 
					    /// Triggered when the mouse enters or leaves widget area
 | 
				
			||||||
    virtual void onHoverChange(bool hovered);
 | 
					    virtual void onHoverChange(bool hovered);
 | 
				
			||||||
    /// Triggered when user presses key while widget has focus
 | 
					    /// Triggered when user presses key while widget has focus
 | 
				
			||||||
    virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
 | 
					    virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
 | 
				
			||||||
    /// Triggered when user releases key while widget has focus
 | 
					    /// Triggered when user releases key while widget has focus
 | 
				
			||||||
    virtual bool onKeyRelease(uchar keyCode, char keyChar, int keyboardModifiers);
 | 
					    virtual bool onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers);
 | 
				
			||||||
    /// Triggered when a mouse button is pressed down while mouse pointer is inside widget area
 | 
					    /// Triggered when a mouse button is pressed down while mouse pointer is inside widget area
 | 
				
			||||||
    virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
 | 
					    virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
 | 
				
			||||||
    /// Triggered when a mouse button is released
 | 
					    /// Triggered when a mouse button is released
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -146,7 +146,7 @@ bool UIWindow::onMouseMove(const Point& mousePos, const Point& mouseMoved)
 | 
				
			||||||
    return UIWidget::onMouseMove(mousePos, mouseMoved);
 | 
					    return UIWidget::onMouseMove(mousePos, mouseMoved);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UIWindow::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
					bool UIWindow::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(keyboardModifiers == Fw::KeyboardNoModifier) {
 | 
					    if(keyboardModifiers == Fw::KeyboardNoModifier) {
 | 
				
			||||||
        if(keyCode == Fw::KeyReturn || keyCode == Fw::KeyEnter) {
 | 
					        if(keyCode == Fw::KeyReturn || keyCode == Fw::KeyEnter) {
 | 
				
			||||||
| 
						 | 
					@ -157,5 +157,5 @@ bool UIWindow::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return UIWidget::onKeyPress(keyCode, keyChar, keyboardModifiers);
 | 
					    return UIWidget::onKeyPress(keyCode, keyText, keyboardModifiers);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ protected:
 | 
				
			||||||
    virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
 | 
					    virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
 | 
				
			||||||
    virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);
 | 
					    virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);
 | 
				
			||||||
    virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
 | 
					    virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
 | 
				
			||||||
    virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
 | 
					    virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    std::string m_title;
 | 
					    std::string m_title;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,10 +35,13 @@ typedef uint64_t uint64;
 | 
				
			||||||
typedef uint32_t uint32;
 | 
					typedef uint32_t uint32;
 | 
				
			||||||
typedef uint16_t uint16;
 | 
					typedef uint16_t uint16;
 | 
				
			||||||
typedef uint8_t uint8;
 | 
					typedef uint8_t uint8;
 | 
				
			||||||
 | 
					typedef int64_t int64;
 | 
				
			||||||
typedef int32_t int32;
 | 
					typedef int32_t int32;
 | 
				
			||||||
typedef int16_t int16;
 | 
					typedef int16_t int16;
 | 
				
			||||||
typedef int8_t int8;
 | 
					typedef int8_t int8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef int64 ticks_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef std::function<void()> SimpleCallback;
 | 
					typedef std::function<void()> SimpleCallback;
 | 
				
			||||||
typedef std::function<bool()> BooleanCallback;
 | 
					typedef std::function<bool()> BooleanCallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										35
									
								
								src/main.cpp
								
								
								
								
							
							
						
						
									
										35
									
								
								src/main.cpp
								
								
								
								
							| 
						 | 
					@ -21,39 +21,12 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <otclient/otclient.h>
 | 
					#include <otclient/otclient.h>
 | 
				
			||||||
#include <framework/core/eventdispatcher.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <csignal>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void signal_handler(int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    static bool signaled = false;
 | 
					 | 
				
			||||||
    switch(sig) {
 | 
					 | 
				
			||||||
        case SIGTERM:
 | 
					 | 
				
			||||||
        case SIGINT:
 | 
					 | 
				
			||||||
            if(!signaled) {
 | 
					 | 
				
			||||||
                signaled = true;
 | 
					 | 
				
			||||||
                g_dispatcher.addEvent(std::bind(&OTClient::onClose, &g_client));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef WIN32_NO_CONSOLE
 | 
					 | 
				
			||||||
#include <windows.h>
 | 
					 | 
				
			||||||
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    std::vector<std::string> args;
 | 
					 | 
				
			||||||
    boost::split(args, lpszArgument, boost::is_any_of(std::string(" ")));
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
int main(int argc, const char* argv[])
 | 
					int main(int argc, const char* argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::vector<std::string> args;
 | 
					    std::vector<std::string> args(argv, argv + argc);
 | 
				
			||||||
    for(int i=0; i<argc; ++i)
 | 
					    g_otclient.init(args);
 | 
				
			||||||
        args.push_back(argv[i]);
 | 
					    g_otclient.run();
 | 
				
			||||||
#endif
 | 
					    g_otclient.terminate();
 | 
				
			||||||
    g_client.init(args);
 | 
					 | 
				
			||||||
    g_client.run();
 | 
					 | 
				
			||||||
    g_client.terminate();
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@
 | 
				
			||||||
namespace Otc
 | 
					namespace Otc
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static const char* AppName = "OTClient";
 | 
					    static const char* AppName = "OTClient";
 | 
				
			||||||
    static const char* AppPathName = "otclient";
 | 
					    static const char* AppIdentifierName = "otclient";
 | 
				
			||||||
    static const char* AppVersion = "0.4.0";
 | 
					    static const char* AppVersion = "0.4.0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static const char* CipsoftPublicRSA = "1321277432058722840622950990822933849527763264961655079678763618"
 | 
					    static const char* CipsoftPublicRSA = "1321277432058722840622950990822933849527763264961655079678763618"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -207,7 +207,7 @@ void Creature::walk(const Position& position, bool inverse)
 | 
				
			||||||
void Creature::updateWalk()
 | 
					void Creature::updateWalk()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(m_walking) {
 | 
					    if(m_walking) {
 | 
				
			||||||
        int elapsedTicks = g_clock.ticks() - m_walkStartTicks;
 | 
					        int elapsedTicks = g_clock.ticksElapsed(m_walkStartTicks);
 | 
				
			||||||
        int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32);
 | 
					        int totalPixelsWalked = std::min((int)round(elapsedTicks / m_walkTimePerPixel), 32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(m_inverseWalking) {
 | 
					        if(m_inverseWalking) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,7 @@ protected:
 | 
				
			||||||
    FontPtr m_informationFont;
 | 
					    FontPtr m_informationFont;
 | 
				
			||||||
    Color m_informationColor;
 | 
					    Color m_informationColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int m_walkStartTicks;
 | 
					    ticks_t m_walkStartTicks;
 | 
				
			||||||
    bool m_walking, m_inverseWalking;
 | 
					    bool m_walking, m_inverseWalking;
 | 
				
			||||||
    float m_walkTimePerPixel;
 | 
					    float m_walkTimePerPixel;
 | 
				
			||||||
    Position m_walkingFromPosition;
 | 
					    Position m_walkingFromPosition;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ public:
 | 
				
			||||||
    EffectPtr asEffect() { return std::static_pointer_cast<Effect>(shared_from_this()); }
 | 
					    EffectPtr asEffect() { return std::static_pointer_cast<Effect>(shared_from_this()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    int m_animationStartTicks;
 | 
					    ticks_t m_animationStartTicks;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,17 +27,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Game g_game;
 | 
					Game g_game;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Game::init()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    m_online = false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Game::terminate()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if(m_online)
 | 
					 | 
				
			||||||
        logout(true);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Game::loginWorld(const std::string& account, const std::string& password, const std::string& worldHost, int worldPort, const std::string& characterName)
 | 
					void Game::loginWorld(const std::string& account, const std::string& password, const std::string& worldHost, int worldPort, const std::string& characterName)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    m_protocolGame = ProtocolGamePtr(new ProtocolGame);
 | 
					    m_protocolGame = ProtocolGamePtr(new ProtocolGame);
 | 
				
			||||||
| 
						 | 
					@ -51,13 +40,14 @@ void Game::cancelLogin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Game::logout(bool force)
 | 
					void Game::logout(bool force)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(m_protocolGame) {
 | 
					    if(!m_protocolGame || !m_online)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_protocolGame->sendLogout();
 | 
					    m_protocolGame->sendLogout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(force)
 | 
					    if(force)
 | 
				
			||||||
        processLogout();
 | 
					        processLogout();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Game::processLoginError(const std::string& error)
 | 
					void Game::processLoginError(const std::string& error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,9 +31,6 @@
 | 
				
			||||||
class Game
 | 
					class Game
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    void init();
 | 
					 | 
				
			||||||
    void terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // login/logout related
 | 
					    // login/logout related
 | 
				
			||||||
    void loginWorld(const std::string& account,
 | 
					    void loginWorld(const std::string& account,
 | 
				
			||||||
                    const std::string& password,
 | 
					                    const std::string& password,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    int m_data;
 | 
					    int m_data;
 | 
				
			||||||
    int m_lastTicks;
 | 
					    ticks_t m_lastTicks;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ public:
 | 
				
			||||||
    MissilePtr asMissile() { return std::static_pointer_cast<Missile>(shared_from_this()); }
 | 
					    MissilePtr asMissile() { return std::static_pointer_cast<Missile>(shared_from_this()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    int m_startTicks;
 | 
					    ticks_t m_startTicks;
 | 
				
			||||||
    Position m_positionDelta;
 | 
					    Position m_positionDelta;
 | 
				
			||||||
    float m_duration;
 | 
					    float m_duration;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,27 +1,6 @@
 | 
				
			||||||
/*
 | 
					#include "otclient.h"
 | 
				
			||||||
 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					 | 
				
			||||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
					 | 
				
			||||||
 * in the Software without restriction, including without limitation the rights
 | 
					 | 
				
			||||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					 | 
				
			||||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
					 | 
				
			||||||
 * furnished to do so, subject to the following conditions:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be included in
 | 
					 | 
				
			||||||
 * all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					 | 
				
			||||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					 | 
				
			||||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					 | 
				
			||||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <otclient/otclient.h>
 | 
					 | 
				
			||||||
#include <framework/luascript/luainterface.h>
 | 
					#include <framework/luascript/luainterface.h>
 | 
				
			||||||
 | 
					#include <otclient/luascript/luavaluecasts.h>
 | 
				
			||||||
#include <otclient/core/game.h>
 | 
					#include <otclient/core/game.h>
 | 
				
			||||||
#include <otclient/core/tile.h>
 | 
					#include <otclient/core/tile.h>
 | 
				
			||||||
#include <otclient/core/item.h>
 | 
					#include <otclient/core/item.h>
 | 
				
			||||||
| 
						 | 
					@ -39,12 +18,11 @@
 | 
				
			||||||
#include <otclient/ui/uigame.h>
 | 
					#include <otclient/ui/uigame.h>
 | 
				
			||||||
#include <otclient/core/outfit.h>
 | 
					#include <otclient/core/outfit.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "luavaluecasts.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::registerLuaFunctions()
 | 
					void OTClient::registerLuaFunctions()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    g_lua.bindGlobalFunction("exit", std::bind(&OTClient::exit, &g_client));
 | 
					    Application::registerLuaFunctions();
 | 
				
			||||||
    g_lua.bindGlobalFunction("setOnClose", std::bind(&OTClient::setOnClose, &g_client, _1));
 | 
					
 | 
				
			||||||
 | 
					    g_lua.bindGlobalFunction("exit", std::bind(&Application::exit, &g_app));
 | 
				
			||||||
    g_lua.bindGlobalFunction("importDat", std::bind(&ThingsType::load, &g_thingsType, _1));
 | 
					    g_lua.bindGlobalFunction("importDat", std::bind(&ThingsType::load, &g_thingsType, _1));
 | 
				
			||||||
    g_lua.bindGlobalFunction("importSpr", std::bind(&SpriteManager::load, &g_sprites, _1));
 | 
					    g_lua.bindGlobalFunction("importSpr", std::bind(&SpriteManager::load, &g_sprites, _1));
 | 
				
			||||||
    g_lua.bindGlobalFunction("getOufitColor", Outfit::getColor);
 | 
					    g_lua.bindGlobalFunction("getOufitColor", Outfit::getColor);
 | 
				
			||||||
| 
						 | 
					@ -35,5 +35,4 @@ bool luavalue_cast(int index, Outfit& outfit);
 | 
				
			||||||
void push_luavalue(const Position& pos);
 | 
					void push_luavalue(const Position& pos);
 | 
				
			||||||
bool luavalue_cast(int index, Position& pos);
 | 
					bool luavalue_cast(int index, Position& pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -251,7 +251,7 @@ void ProtocolGame::parseMessage(InputMessage& msg)
 | 
				
			||||||
            //case Otc::GameServerObjectInfo:
 | 
					            //case Otc::GameServerObjectInfo:
 | 
				
			||||||
            //case Otc::GameServerPlayerInventory:
 | 
					            //case Otc::GameServerPlayerInventory:
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                Fw::throwException("unknown opt byte ", opt);
 | 
					                Fw::throwException("unknown opt byte ", (int)opt);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,304 +1,10 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					 | 
				
			||||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
					 | 
				
			||||||
 * in the Software without restriction, including without limitation the rights
 | 
					 | 
				
			||||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					 | 
				
			||||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
					 | 
				
			||||||
 * furnished to do so, subject to the following conditions:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be included in
 | 
					 | 
				
			||||||
 * all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					 | 
				
			||||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					 | 
				
			||||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					 | 
				
			||||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "otclient.h"
 | 
					#include "otclient.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <framework/core/modulemanager.h>
 | 
					OTClient g_otclient;
 | 
				
			||||||
#include <framework/core/configmanager.h>
 | 
					Application& g_app = g_otclient;
 | 
				
			||||||
#include <framework/core/resourcemanager.h>
 | 
					 | 
				
			||||||
#include <framework/core/eventdispatcher.h>
 | 
					 | 
				
			||||||
#include <framework/core/clock.h>
 | 
					 | 
				
			||||||
#include <framework/luascript/luainterface.h>
 | 
					 | 
				
			||||||
#include <framework/graphics/graphics.h>
 | 
					 | 
				
			||||||
#include <framework/graphics/fontmanager.h>
 | 
					 | 
				
			||||||
#include <framework/ui/uimanager.h>
 | 
					 | 
				
			||||||
#include <framework/ui/uiwidget.h>
 | 
					 | 
				
			||||||
#include <framework/net/connection.h>
 | 
					 | 
				
			||||||
#include <framework/platform/platform.h>
 | 
					 | 
				
			||||||
#include <otclient/net/protocolgame.h>
 | 
					 | 
				
			||||||
#include <otclient/core/game.h>
 | 
					 | 
				
			||||||
#include <otclient/core/map.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
OTClient g_client;
 | 
					void OTClient::init(const std::vector<std::string>& args)
 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::init(std::vector<std::string> args)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    m_running = false;
 | 
					 | 
				
			||||||
    m_stopping = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // print client information
 | 
					 | 
				
			||||||
    logInfo(Otc::AppName, " ", Otc::AppVersion);
 | 
					    logInfo(Otc::AppName, " ", Otc::AppVersion);
 | 
				
			||||||
 | 
					    Application::init(Otc::AppName, args);
 | 
				
			||||||
    // initialize platform related stuff
 | 
					 | 
				
			||||||
    g_platform.init(this, Otc::AppName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // initialize script environment
 | 
					 | 
				
			||||||
    g_lua.init();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // register otclient lua functions
 | 
					 | 
				
			||||||
    registerLuaFunctions();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // initialize resources
 | 
					 | 
				
			||||||
    g_resources.init(args[0].c_str(), Otc::AppPathName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // load configurations
 | 
					 | 
				
			||||||
    loadConfigurations();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // create the client window
 | 
					 | 
				
			||||||
    //TODO: bind these functions and move to otclient module
 | 
					 | 
				
			||||||
    int minWidth = 550;
 | 
					 | 
				
			||||||
    int minHeight = 450;
 | 
					 | 
				
			||||||
    int windowX = Fw::fromstring(g_configs.get("window x"), 0);
 | 
					 | 
				
			||||||
    int windowY = Fw::fromstring(g_configs.get("window y"), 0);
 | 
					 | 
				
			||||||
    int windowWidth = Fw::fromstring(g_configs.get("window width"), minWidth);
 | 
					 | 
				
			||||||
    int windowHeight = Fw::fromstring(g_configs.get("window height"), minHeight);
 | 
					 | 
				
			||||||
    bool maximized = Fw::fromstring(g_configs.get("window maximized"), false);
 | 
					 | 
				
			||||||
    g_platform.createWindow(windowX, windowY, windowWidth, windowHeight, minWidth, minHeight, maximized);
 | 
					 | 
				
			||||||
    g_platform.setWindowTitle(Otc::AppName);
 | 
					 | 
				
			||||||
    g_platform.setWindowIcon("otclient/otcicon.png");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // initialize graphics
 | 
					 | 
				
			||||||
    g_graphics.init();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // initialize the ui
 | 
					 | 
				
			||||||
    g_ui.init();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_game.init();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // discover and load modules
 | 
					 | 
				
			||||||
    g_modules.discoverAndLoadModules();
 | 
					 | 
				
			||||||
    g_modules.getModule("otclient")->load();
 | 
					 | 
				
			||||||
    ModulePtr tibiaFilesModule = g_modules.getModule("tibiafiles");
 | 
					 | 
				
			||||||
    if(!tibiaFilesModule || !tibiaFilesModule->isLoaded()) {
 | 
					 | 
				
			||||||
        logFatal("Could not find or load 'tibiafiles' module, this module contains SPR and DAT files.\n"
 | 
					 | 
				
			||||||
                 "Please download it and place in modules directory, then try running again.");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // now that everything is initialized, setup configurations
 | 
					 | 
				
			||||||
    setupConfigurations();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // now that everything is loaded, show the window
 | 
					 | 
				
			||||||
    g_platform.showWindow();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::run()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int frameTicks = g_clock.ticks();
 | 
					 | 
				
			||||||
    int lastPollTicks = frameTicks;
 | 
					 | 
				
			||||||
    int frameCount = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    m_stopping = false;
 | 
					 | 
				
			||||||
    m_running = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(g_ui.getRootWidget()->getChildCount() == 0) {
 | 
					 | 
				
			||||||
        logError("There is no root widgets to display, the app will close");
 | 
					 | 
				
			||||||
        m_stopping = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // run the first poll
 | 
					 | 
				
			||||||
    poll();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while(!m_stopping) {
 | 
					 | 
				
			||||||
        //g_platform.sleep(150);
 | 
					 | 
				
			||||||
        frameTicks = g_clock.updateTicks();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // poll events every POLL_CYCLE_DELAY
 | 
					 | 
				
			||||||
        // this delay exists to avoid massive polling thus increasing framerate
 | 
					 | 
				
			||||||
        if(frameTicks - lastPollTicks >= POLL_CYCLE_DELAY) {
 | 
					 | 
				
			||||||
            poll();
 | 
					 | 
				
			||||||
            lastPollTicks = frameTicks;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // only render when the windows is visible
 | 
					 | 
				
			||||||
        if(g_platform.isWindowVisible()) {
 | 
					 | 
				
			||||||
            // render begin
 | 
					 | 
				
			||||||
            g_graphics.beginRender();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // render everything
 | 
					 | 
				
			||||||
            render();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // render end
 | 
					 | 
				
			||||||
            g_graphics.endRender();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // swap the old buffer with the new rendered
 | 
					 | 
				
			||||||
            g_platform.swapBuffers();
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // sleeps until next poll to avoid massive cpu usage
 | 
					 | 
				
			||||||
            g_clock.sleep(POLL_CYCLE_DELAY+1);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    m_stopping = false;
 | 
					 | 
				
			||||||
    m_running = false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::terminate()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // hide the window because there is no render anymore
 | 
					 | 
				
			||||||
    g_platform.hideWindow();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_game.terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // run modules unload event
 | 
					 | 
				
			||||||
    g_modules.unloadModules();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // terminate ui
 | 
					 | 
				
			||||||
    g_ui.terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // release remaining lua object references
 | 
					 | 
				
			||||||
    g_lua.collectGarbage();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // poll remaining events
 | 
					 | 
				
			||||||
    poll();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // terminate network
 | 
					 | 
				
			||||||
    Connection::terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // flush remaining dispatcher events
 | 
					 | 
				
			||||||
    g_dispatcher.flush();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // terminate graphics
 | 
					 | 
				
			||||||
    g_graphics.terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // save configurations
 | 
					 | 
				
			||||||
    saveConfigurations();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // release resources
 | 
					 | 
				
			||||||
    g_resources.terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // terminate script environment
 | 
					 | 
				
			||||||
    g_lua.terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // end platform related stuff
 | 
					 | 
				
			||||||
    g_platform.terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::exit()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // stops the main loop
 | 
					 | 
				
			||||||
    m_stopping = true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::poll()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // poll platform events
 | 
					 | 
				
			||||||
    g_platform.poll();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // poll network events
 | 
					 | 
				
			||||||
    Connection::poll();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // poll dispatcher events
 | 
					 | 
				
			||||||
    g_dispatcher.poll();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::render()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // everything is rendered by UI components
 | 
					 | 
				
			||||||
    g_ui.render();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::loadConfigurations()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // default window size
 | 
					 | 
				
			||||||
    int defWidth = 550;
 | 
					 | 
				
			||||||
    int defHeight = 450;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // sets default window configuration
 | 
					 | 
				
			||||||
    g_configs.set("window x", Fw::tostring((g_platform.getDisplayWidth() - defWidth)/2));
 | 
					 | 
				
			||||||
    g_configs.set("window y", Fw::tostring((g_platform.getDisplayHeight() - defHeight)/2));
 | 
					 | 
				
			||||||
    g_configs.set("window width", Fw::tostring(defWidth));
 | 
					 | 
				
			||||||
    g_configs.set("window height", Fw::tostring(defHeight));
 | 
					 | 
				
			||||||
    g_configs.set("window maximized", Fw::tostring(false));
 | 
					 | 
				
			||||||
    g_configs.set("vsync", Fw::tostring(true));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // loads user configuration
 | 
					 | 
				
			||||||
    if(!g_configs.load("config.otml"))
 | 
					 | 
				
			||||||
        logInfo("Using default configurations.");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::setupConfigurations()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // activate vertical synchronization?
 | 
					 | 
				
			||||||
    bool vsync = Fw::fromstring(g_configs.get("vsync"), true);
 | 
					 | 
				
			||||||
    g_platform.setVerticalSync(vsync);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::saveConfigurations()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    g_configs.set("window x", Fw::tostring(g_platform.getWindowX()));
 | 
					 | 
				
			||||||
    g_configs.set("window y", Fw::tostring(g_platform.getWindowY()));
 | 
					 | 
				
			||||||
    g_configs.set("window width", Fw::tostring(g_platform.getWindowWidth()));
 | 
					 | 
				
			||||||
    g_configs.set("window height", Fw::tostring(g_platform.getWindowHeight()));
 | 
					 | 
				
			||||||
    g_configs.set("window maximized", Fw::tostring(g_platform.isWindowMaximized()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // saves user configuration
 | 
					 | 
				
			||||||
    if(!g_configs.save())
 | 
					 | 
				
			||||||
        logError("Configurations are lost because it couldn't be saved");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::onClose()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    //TODO: make and use g_lua.callGlobalField
 | 
					 | 
				
			||||||
    if(m_onCloseCallback)
 | 
					 | 
				
			||||||
       m_onCloseCallback();
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        exit();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::onResize(const Size& size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    static bool eventScheduled = false;
 | 
					 | 
				
			||||||
    static Size newSize;
 | 
					 | 
				
			||||||
    newSize = size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // avoid massive resize updates
 | 
					 | 
				
			||||||
    if(!eventScheduled) {
 | 
					 | 
				
			||||||
        g_dispatcher.addEvent([&] {
 | 
					 | 
				
			||||||
            g_graphics.resize(newSize);
 | 
					 | 
				
			||||||
            g_ui.resize(newSize);
 | 
					 | 
				
			||||||
            eventScheduled = false;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        eventScheduled = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void OTClient::onPlatformEvent(const PlatformEvent& event)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    bool fireUi = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(event.type == EventKeyDown && event.ctrl && !event.alt && !event.shift && event.keycode == Fw::KeyF8) {
 | 
					 | 
				
			||||||
        // TODO: move this events to lua
 | 
					 | 
				
			||||||
        UIWidgetPtr console = g_ui.getRootWidget()->getChildById("consolePanel");
 | 
					 | 
				
			||||||
        if(!console->isExplicitlyVisible()) {
 | 
					 | 
				
			||||||
            console->lock();
 | 
					 | 
				
			||||||
            console->show();
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            console->unlock();
 | 
					 | 
				
			||||||
            console->hide();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fireUi = false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(fireUi)
 | 
					 | 
				
			||||||
        g_ui.inputEvent(event);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,79 +1,16 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (c) 2010-2011 OTClient <https://github.com/edubart/otclient>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					 | 
				
			||||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
					 | 
				
			||||||
 * in the Software without restriction, including without limitation the rights
 | 
					 | 
				
			||||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					 | 
				
			||||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
					 | 
				
			||||||
 * furnished to do so, subject to the following conditions:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be included in
 | 
					 | 
				
			||||||
 * all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					 | 
				
			||||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					 | 
				
			||||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					 | 
				
			||||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					 | 
				
			||||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					 | 
				
			||||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					 | 
				
			||||||
 * THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef OTCLIENT_H
 | 
					#ifndef OTCLIENT_H
 | 
				
			||||||
#define OTCLIENT_H
 | 
					#define OTCLIENT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <framework/ui/declarations.h>
 | 
					#include <framework/application.h>
 | 
				
			||||||
#include <framework/platform/platformlistener.h>
 | 
					#include <otclient/global.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OTClient : public PlatformListener
 | 
					class OTClient : public Application
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    enum {
 | 
					 | 
				
			||||||
        POLL_CYCLE_DELAY = 10
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    /// Where everything begins...
 | 
					    void init(const std::vector<std::string>& args);
 | 
				
			||||||
    void init(std::vector<std::string> args);
 | 
					    void registerLuaFunctions();
 | 
				
			||||||
    /// Main loop
 | 
					 | 
				
			||||||
    void run();
 | 
					 | 
				
			||||||
    /// Called when the client is terminating
 | 
					 | 
				
			||||||
    void terminate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Stop running
 | 
					 | 
				
			||||||
    void exit();
 | 
					 | 
				
			||||||
    /// Poll platform, dispatcher and network events
 | 
					 | 
				
			||||||
    void poll();
 | 
					 | 
				
			||||||
    /// Render each frame
 | 
					 | 
				
			||||||
    void render();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Fired when user tryes to close the window
 | 
					 | 
				
			||||||
    void onClose();
 | 
					 | 
				
			||||||
    /// Fired when user resize the window
 | 
					 | 
				
			||||||
    void onResize(const Size& size);
 | 
					 | 
				
			||||||
    /// Fired on an user input event
 | 
					 | 
				
			||||||
    void onPlatformEvent(const PlatformEvent& event);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool isRunning() const { return m_running; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void setOnClose(const SimpleCallback& onCloseCallback) { m_onCloseCallback = onCloseCallback; }
 | 
					 | 
				
			||||||
    SimpleCallback getOnClose() const { return m_onCloseCallback; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static void registerLuaFunctions();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
    /// Set default configurations and load the user configurations
 | 
					 | 
				
			||||||
    void loadConfigurations();
 | 
					 | 
				
			||||||
    /// Use the loaded configurations to setup other classes
 | 
					 | 
				
			||||||
    void setupConfigurations();
 | 
					 | 
				
			||||||
    void saveConfigurations();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool m_running;
 | 
					 | 
				
			||||||
    bool m_stopping;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    SimpleCallback m_onCloseCallback;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern OTClient g_client;
 | 
					extern OTClient g_otclient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@
 | 
				
			||||||
#include <otclient/core/game.h>
 | 
					#include <otclient/core/game.h>
 | 
				
			||||||
#include <framework/ui/uilineedit.h>
 | 
					#include <framework/ui/uilineedit.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool UIGame::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
					bool UIGame::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    UILineEditPtr chatLineEdit = std::dynamic_pointer_cast<UILineEdit>(getParent()->recursiveGetChildById("chatLineEdit"));
 | 
					    UILineEditPtr chatLineEdit = std::dynamic_pointer_cast<UILineEdit>(getParent()->recursiveGetChildById("chatLineEdit"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,10 +100,10 @@ bool UIGame::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(keyChar != 0) {
 | 
					    if(!keyText.empty()) {
 | 
				
			||||||
        chatLineEdit->appendText(std::string(1, keyChar));
 | 
					        chatLineEdit->appendText(keyText);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return UIWidget::onKeyPress(keyCode, keyChar, keyboardModifiers);
 | 
					    return UIWidget::onKeyPress(keyCode, keyText, keyboardModifiers);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@
 | 
				
			||||||
class UIGame : public UIWidget
 | 
					class UIGame : public UIWidget
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
    virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
 | 
					    virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue