window.monkey2 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. Namespace mojo.app
  2. #rem monkeydoc Window creation flags.
  3. | WindowFlags | Description
  4. |:--------------|:-----------
  5. | CenterX | Center window horizontally.
  6. | CenterY | Center window vertically.
  7. | Center | Center window.
  8. | Hidden | Window is initally hidden.
  9. | Resizable | Window is resizable.
  10. | Fullscreen | Window is a fullscreen window.
  11. #end
  12. Enum WindowFlags
  13. CenterX=1
  14. CenterY=2
  15. Hidden=4
  16. Resizable=8
  17. Borderless=16
  18. Fullscreen=32
  19. HighDPI=64
  20. Center=CenterX|CenterY
  21. End
  22. #rem monkeydoc The Window class.
  23. #end
  24. Class Window Extends View
  25. Method New()
  26. Init( "Window",New Recti( 0,0,640,480 ),WindowFlags.Center )
  27. End
  28. Method New( title:String="Window",width:Int=640,height:Int=480,flags:WindowFlags=Null )
  29. Init( title,New Recti( 0,0,width,height ),flags|WindowFlags.Center )
  30. End
  31. Method New( title:String,rect:Recti,flags:WindowFlags=Null )
  32. Init( title,rect,flags )
  33. End
  34. #rem monkeydoc The window title text.
  35. #end
  36. Property Title:String()
  37. Return String.FromCString( SDL_GetWindowTitle( _sdlWindow ) )
  38. Setter( title:String )
  39. SDL_SetWindowTitle( _sdlWindow,title )
  40. End
  41. #rem monkeydoc The window clear color.
  42. #end
  43. Property ClearColor:Color()
  44. Return _clearColor
  45. Setter( clearColor:Color )
  46. _clearColor=clearColor
  47. End
  48. #rem monkeydoc True if window clearing is enabled.
  49. #end
  50. Property ClearEnabled:Bool()
  51. Return _clearEnabled
  52. Setter( clearEnabled:Bool )
  53. _clearEnabled=clearEnabled
  54. End
  55. #rem monkeydoc The window swap interval.
  56. #end
  57. Property SwapInterval:Int()
  58. Return _swapInterval
  59. Setter( swapInterval:Int )
  60. _swapInterval=swapInterval
  61. End
  62. #rem monkeydoc @hidden.
  63. #end
  64. Property Fullscreen:Bool()
  65. Return _fullscreen
  66. Setter( fullscreen:Bool )
  67. If fullscreen=_fullscreen Return
  68. _fullscreen=fullscreen
  69. If _fullscreen
  70. Local mode:SDL_DisplayMode
  71. mode.w=Width
  72. mode.h=Height
  73. SDL_SetWindowDisplayMode( _sdlWindow,Varptr mode )
  74. SDL_SetWindowFullscreen( _sdlWindow,SDL_WINDOW_FULLSCREEN )
  75. Else
  76. SDL_SetWindowFullscreen( _sdlWindow,0 )
  77. Endif
  78. End
  79. Property ContentView:View()
  80. Return _contentView
  81. Setter( contentView:View )
  82. If _contentView RemoveChildView( _contentView )
  83. _contentView=contentView
  84. If _contentView AddChildView( _contentView )
  85. End
  86. Method UpdateWindow( render:Bool )
  87. LayoutWindow()
  88. If render RenderWindow()
  89. End
  90. '***** INTERNAL *****
  91. #rem monkeydoc @hidden Mouse scale for ios retina devices.
  92. #end
  93. Property MouseScale:Vec2f()
  94. Return _mouseScale
  95. End
  96. #rem monkeydoc @hidden The internal SDL_Window used by this window.
  97. #end
  98. Property SDLWindow:SDL_Window Ptr()
  99. Return _sdlWindow
  100. End
  101. #rem monkeydoc @hidden The internal SDL_GLContext used by this window.
  102. #end
  103. Property SDLGLContext:SDL_GLContext()
  104. Return _sdlGLContext
  105. End
  106. #rem monkeydoc @hidden
  107. #end
  108. Function AllWindows:Window[]()
  109. Return _allWindows.ToArray()
  110. End
  111. #rem monkeydoc @hidden
  112. #end
  113. Function VisibleWindows:Window[]()
  114. Return _visibleWindows.ToArray()
  115. End
  116. #rem monkeydoc @hidden
  117. #end
  118. Function WindowForID:Window( id:UInt )
  119. Return _windowsByID[id]
  120. End
  121. #rem monkeydoc @hidden
  122. #end
  123. Method SendWindowEvent( event:WindowEvent )
  124. Select event.Type
  125. Case EventType.WindowMoved,EventType.WindowResized
  126. _frame=GetFrame()
  127. Frame=_frame
  128. _weirdHack=true
  129. End
  130. OnWindowEvent( event )
  131. End
  132. Protected
  133. #rem monkeydoc @hidden
  134. #end
  135. Method OnThemeChanged() override
  136. _clearColor=App.Theme.GetColor( "windowClearColor" )
  137. End
  138. #rem monkeydoc Window event handler.
  139. Called when the window is sent a window event.
  140. #end
  141. Method OnWindowEvent( event:WindowEvent ) Virtual
  142. Select event.Type
  143. Case EventType.WindowClose
  144. App.Terminate()
  145. Case EventType.WindowMoved
  146. Case EventType.WindowResized
  147. App.RequestRender()
  148. Case EventType.WindowGainedFocus
  149. 'Need to do this for KDE on linux...
  150. App.RequestRender()
  151. Case EventType.WindowLostFocus
  152. End
  153. End
  154. Protected
  155. Method OnLayout() Override
  156. If _contentView _contentView.Frame=Rect
  157. End
  158. Private
  159. Field _sdlWindow:SDL_Window Ptr
  160. Field _sdlGLContext:SDL_GLContext
  161. Field _flags:WindowFlags
  162. Field _fullscreen:=False
  163. Field _swapInterval:=1
  164. Field _canvas:Canvas
  165. Field _clearColor:=Color.Grey
  166. Field _clearEnabled:=True
  167. Field _contentView:View
  168. Field _minSize:Vec2i
  169. Field _maxSize:Vec2i
  170. Field _frame:Recti
  171. Field _mouseScale:=New Vec2f( 1,1 )
  172. 'Ok, angles glViewport appears To be 'lagging' by one frame, causing weirdness when resizing.
  173. Field _weirdHack:Bool
  174. Global _allWindows:=New Stack<Window>
  175. Global _visibleWindows:=New Stack<Window>
  176. Global _windowsByID:=New Map<UInt,Window>
  177. Method UpdateMouseScale()
  178. Local w:Int,h:Int,dw:Int,dh:Int
  179. SDL_GetWindowSize( _sdlWindow,Varptr w,Varptr h )
  180. #If __TARGET__="emscripten"
  181. emscripten_get_canvas_size( Varptr dw,Varptr dh,Null )'Varptr fs )
  182. #Else
  183. SDL_GL_GetDrawableSize( _sdlWindow,Varptr dw,Varptr dh )
  184. #Endif
  185. _mouseScale=New Vec2f( Float(dw)/w,Float(dh)/h )
  186. End
  187. Method SetMinSize( size:Vec2i )
  188. size/=_mouseScale
  189. SDL_SetWindowMinimumSize( _sdlWindow,size.x,size.y )
  190. End
  191. Method SetMaxSize( size:Vec2i )
  192. size/=_mouseScale
  193. SDL_SetWindowMaximumSize( _sdlWindow,size.x,size.y )
  194. End
  195. Method SetFrame( rect:Recti )
  196. rect/=_mouseScale
  197. SDL_SetWindowPosition( _sdlWindow,rect.X,rect.Y )
  198. SDL_SetWindowSize( _sdlWindow,rect.Width,rect.Height )
  199. End
  200. Method GetMinSize:Vec2i()
  201. Local w:Int,h:Int
  202. SDL_GetWindowMinimumSize( _sdlWindow,Varptr w,Varptr h )
  203. Return New Vec2i( w,h ) * _mouseScale
  204. End
  205. Method GetMaxSize:Vec2i()
  206. Local w:Int,h:Int
  207. SDL_GetWindowMaximumSize( _sdlWindow,Varptr w,Varptr h )
  208. Return New Vec2i( w,h ) * _mouseScale
  209. End
  210. Method GetFrame:Recti()
  211. Local x:Int,y:Int,w:Int,h:Int
  212. SDL_GetWindowPosition( _sdlWindow,Varptr x,Varptr y )
  213. SDL_GetWindowSize( _sdlWindow,Varptr w,Varptr h )
  214. Return New Recti( x,y,x+w,y+h ) * _mouseScale
  215. End
  216. Method LayoutWindow()
  217. 'All this polling is a bit ugly...fixme.
  218. '
  219. #If __DESKTOP_TARGET__
  220. If MinSize<>_minSize
  221. SetMinSize( MinSize )
  222. MinSize=GetMinSize()
  223. _minSize=MinSize
  224. Endif
  225. If MaxSize<>_maxSize
  226. SetMaxSize( MaxSize )
  227. MaxSize=GetMaxSize()
  228. _maxSize=MaxSize
  229. Endif
  230. If Frame<>_frame
  231. SetFrame( Frame )
  232. Frame=GetFrame()
  233. _frame=Frame
  234. _weirdHack=True
  235. Endif
  236. #Else
  237. _frame=GetFrame()
  238. Frame=_frame
  239. #Endif
  240. Measure()
  241. UpdateLayout()
  242. End
  243. #rem monkeydoc @hidden
  244. #end
  245. Method RenderWindow()
  246. SDL_GL_MakeCurrent( _sdlWindow,_sdlGLContext )
  247. SDL_GL_SetSwapInterval( _swapInterval )
  248. #If __TARGET__="windows"
  249. If _weirdHack
  250. _weirdHack=False
  251. SDL_GL_SwapWindow( _sdlWindow )
  252. Endif
  253. #Endif
  254. Local bounds:=New Recti( 0,0,Frame.Size )
  255. _canvas.Resize( bounds.Size )
  256. _canvas.BeginRender( bounds,New AffineMat3f )
  257. If _clearEnabled _canvas.Clear( _clearColor )
  258. Render( _canvas )
  259. _canvas.EndRender()
  260. SDL_GL_SwapWindow( _sdlWindow )
  261. End
  262. Method Init( title:String,rect:Recti,flags:WindowFlags )
  263. Style=GetStyle( "Window" )
  264. Local x:=(flags & WindowFlags.CenterX) ? SDL_WINDOWPOS_CENTERED Else rect.X
  265. Local y:=(flags & WindowFlags.CenterY) ? SDL_WINDOWPOS_CENTERED Else rect.Y
  266. Local sdlFlags:SDL_WindowFlags=SDL_WINDOW_OPENGL
  267. If flags & WindowFlags.Hidden sdlFlags|=SDL_WINDOW_HIDDEN
  268. If flags & WindowFlags.Resizable sdlFlags|=SDL_WINDOW_RESIZABLE
  269. If flags & WindowFlags.Borderless sdlFlags|=SDL_WINDOW_BORDERLESS
  270. If flags & WindowFlags.Fullscreen _fullscreen=True ; sdlFlags|=SDL_WINDOW_FULLSCREEN
  271. If flags & WindowFlags.HighDPI sdlFlags|=SDL_WINDOW_ALLOW_HIGHDPI
  272. _flags=flags
  273. 'Create Window
  274. _sdlWindow=SDL_CreateWindow( title,x,y,rect.Width,rect.Height,sdlFlags )
  275. If Not _sdlWindow
  276. Print "SDL_GetError="+String.FromCString( SDL_GetError() )
  277. Assert( _sdlWindow,"FATAL ERROR: SDL_CreateWindow failed" )
  278. Endif
  279. 'Create GL context
  280. _sdlGLContext=SDL_GL_CreateContext( _sdlWindow )
  281. If Not _sdlGLContext
  282. Print "SDL_GetError="+String.FromCString( SDL_GetError() )
  283. Assert( _sdlGLContext,"FATAL ERROR: SDL_GL_CreateContext failed" )
  284. Endif
  285. SDL_GL_MakeCurrent( _sdlWindow,_sdlGLContext )
  286. _allWindows.Push( Self )
  287. _windowsByID[SDL_GetWindowID( _sdlWindow )]=Self
  288. If Not (flags & WindowFlags.Hidden) _visibleWindows.Push( Self )
  289. 'Would much rather know this *before* we open the window!
  290. UpdateMouseScale()
  291. 'UGLY!!!!!
  292. If _mouseScale.x<>1 Or _mouseScale.y<>1
  293. Local x:=(flags & WindowFlags.CenterX) ? SDL_WINDOWPOS_CENTERED Else rect.X/_mouseScale.x
  294. Local y:=(flags & WindowFlags.CenterY) ? SDL_WINDOWPOS_CENTERED Else rect.Y/_mouseScale.y
  295. Local w:=rect.Width/_mouseScale.x
  296. Local h:=rect.Height/_mouseScale.y
  297. SDL_SetWindowPosition( _sdlWindow,x,y )
  298. SDL_SetWindowSize( _sdlWindow,w,h )
  299. Endif
  300. MinSize=GetMinSize()
  301. _minSize=MinSize
  302. MaxSize=GetMaxSize()
  303. _maxSize=MaxSize
  304. Frame=GetFrame()
  305. _frame=Frame
  306. _clearColor=App.Theme.GetColor( "windowClearColor" )
  307. _canvas=New Canvas( _frame.Width,_frame.Height )
  308. SetWindow( Self )
  309. UpdateActive()
  310. LayoutWindow()
  311. End
  312. End