window.monkey2 11 KB

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