window.monkey2 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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.FromUtf8String( 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 Window event handler.
  134. Called when the window is sent a window event.
  135. #end
  136. Method OnWindowEvent( event:WindowEvent ) Virtual
  137. Select event.Type
  138. Case EventType.WindowClose
  139. App.Terminate()
  140. Case EventType.WindowMoved
  141. Case EventType.WindowResized
  142. App.RequestRender()
  143. Case EventType.WindowGainedFocus
  144. 'Need to do this for KDE on linux...
  145. App.RequestRender()
  146. Case EventType.WindowLostFocus
  147. End
  148. End
  149. Protected
  150. Method OnLayout() Override
  151. If _contentView _contentView.Frame=Rect
  152. End
  153. Private
  154. Field _sdlWindow:SDL_Window Ptr
  155. Field _sdlGLContext:SDL_GLContext
  156. Field _flags:WindowFlags
  157. Field _fullscreen:=False
  158. Field _swapInterval:=1
  159. Field _canvas:Canvas
  160. Field _clearColor:=Color.Grey
  161. Field _clearEnabled:=True
  162. Field _contentView:View
  163. Field _minSize:Vec2i
  164. Field _maxSize:Vec2i
  165. Field _frame:Recti
  166. Field _mouseScale:=New Vec2f( 1,1 )
  167. 'Ok, angles glViewport appears To be 'lagging' by one frame, causing weirdness when resizing.
  168. Field _weirdHack:Bool
  169. Global _allWindows:=New Stack<Window>
  170. Global _visibleWindows:=New Stack<Window>
  171. Global _windowsByID:=New Map<UInt,Window>
  172. Method GetMinSize:Vec2i()
  173. Local w:Int,h:Int
  174. SDL_GetWindowMinimumSize( _sdlWindow,Varptr w,Varptr h )
  175. Return New Vec2i( w,h )
  176. End
  177. Method GetMaxSize:Vec2i()
  178. Local w:Int,h:Int
  179. SDL_GetWindowMaximumSize( _sdlWindow,Varptr w,Varptr h )
  180. Return New Vec2i( w,h )
  181. End
  182. Method GetFrame:Recti()
  183. #If __DESKTOP_TARGET__
  184. Local x:Int,y:Int,w:Int,h:Int
  185. SDL_GetWindowPosition( _sdlWindow,Varptr x,Varptr y )
  186. SDL_GetWindowSize( _sdlWindow,Varptr w,Varptr h )
  187. Return New Recti( x,y,x+w,y+h )
  188. #Else
  189. Local w:Int,h:Int,dw:Int,dh:Int
  190. SDL_GetWindowSize( _sdlWindow,Varptr w,Varptr h )
  191. #If __TARGET__="emscripten"
  192. emscripten_get_canvas_size( Varptr dw,Varptr dh,Null )'Varptr fs )
  193. #Else
  194. SDL_GL_GetDrawableSize( _sdlWindow,Varptr dw,Varptr dh )
  195. #Endif
  196. _mouseScale=New Vec2f( Float(dw)/w,Float(dh)/h )
  197. Return New Recti( 0,0,dw,dh )
  198. #Endif
  199. End
  200. Method LayoutWindow()
  201. 'All this polling is a bit ugly...fixme.
  202. '
  203. #If __DESKTOP_TARGET__
  204. If MinSize<>_minSize
  205. SDL_SetWindowMinimumSize( _sdlWindow,MinSize.x,MinSize.y )
  206. _minSize=GetMinSize()
  207. MinSize=_minSize
  208. Endif
  209. If MaxSize<>_maxSize
  210. SDL_SetWindowMaximumSize( _sdlWindow,MaxSize.x,MaxSize.y )
  211. _maxSize=GetMaxSize()
  212. MaxSize=_maxSize
  213. Endif
  214. If Frame<>_frame
  215. SDL_SetWindowPosition( _sdlWindow,Frame.X,Frame.Y )
  216. SDL_SetWindowSize( _sdlWindow,Frame.Width,Frame.Height )
  217. _frame=GetFrame()
  218. Frame=_frame
  219. _weirdHack=True
  220. Endif
  221. #Else
  222. _frame=GetFrame()
  223. Frame=_frame
  224. #Endif
  225. Measure()
  226. UpdateLayout()
  227. End
  228. #rem monkeydoc @hidden
  229. #end
  230. Method RenderWindow()
  231. SDL_GL_MakeCurrent( _sdlWindow,_sdlGLContext )
  232. SDL_GL_SetSwapInterval( _swapInterval )
  233. #If __TARGET__="windows"
  234. If _weirdHack
  235. _weirdHack=False
  236. SDL_GL_SwapWindow( _sdlWindow )
  237. Endif
  238. #Endif
  239. Local bounds:=New Recti( 0,0,Frame.Size )
  240. _canvas.Resize( bounds.Size )
  241. _canvas.BeginRender( bounds,New AffineMat3f )
  242. If _clearEnabled _canvas.Clear( _clearColor )
  243. Render( _canvas )
  244. _canvas.EndRender()
  245. SDL_GL_SwapWindow( _sdlWindow )
  246. End
  247. Method Init( title:String,rect:Recti,flags:WindowFlags )
  248. Local x:=(flags & WindowFlags.CenterX) ? SDL_WINDOWPOS_CENTERED Else rect.X
  249. Local y:=(flags & WindowFlags.CenterY) ? SDL_WINDOWPOS_CENTERED Else rect.Y
  250. Local sdlFlags:SDL_WindowFlags=SDL_WINDOW_OPENGL
  251. If flags & WindowFlags.Hidden sdlFlags|=SDL_WINDOW_HIDDEN
  252. If flags & WindowFlags.Resizable sdlFlags|=SDL_WINDOW_RESIZABLE
  253. If flags & WindowFlags.Borderless sdlFlags|=SDL_WINDOW_BORDERLESS
  254. If flags & WindowFlags.Fullscreen _fullscreen=True ; sdlFlags|=SDL_WINDOW_FULLSCREEN
  255. If flags & WindowFlags.HighDPI sdlFlags|=SDL_WINDOW_ALLOW_HIGHDPI
  256. _flags=flags
  257. 'Create Window
  258. _sdlWindow=SDL_CreateWindow( title,x,y,rect.Width,rect.Height,sdlFlags )
  259. If Not _sdlWindow
  260. Print "SDL_GetError="+String.FromCString( SDL_GetError() )
  261. Assert( _sdlWindow,"FATAL ERROR: SDL_CreateWindow failed" )
  262. Endif
  263. 'Create GL context
  264. _sdlGLContext=SDL_GL_CreateContext( _sdlWindow )
  265. If Not _sdlGLContext
  266. Print "SDL_GetError="+String.FromCString( SDL_GetError() )
  267. Assert( _sdlGLContext,"FATAL ERROR: SDL_GL_CreateContext failed" )
  268. Endif
  269. SDL_GL_MakeCurrent( _sdlWindow,_sdlGLContext )
  270. _allWindows.Push( Self )
  271. _windowsByID[SDL_GetWindowID( _sdlWindow )]=Self
  272. If Not (flags & WindowFlags.Hidden) _visibleWindows.Push( Self )
  273. _minSize=GetMinSize()
  274. MinSize=_minSize
  275. _maxSize=GetMaxSize()
  276. MaxSize=_maxSize
  277. _frame=GetFrame()
  278. Frame=_frame
  279. _canvas=New Canvas( _frame.Width,_frame.Height )
  280. _clearColor=App.Theme.GetColor( "windowClearColor" )
  281. SetWindow( Self )
  282. UpdateActive()
  283. LayoutWindow()
  284. End
  285. End