window.go (8703B)
1 // Copyright 2019 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ebiten 16 17 import ( 18 "image" 19 "sync" 20 ) 21 22 const ( 23 maxInt = int(^uint(0) >> 1) 24 minInt = -maxInt - 1 25 invalidPos = minInt 26 ) 27 28 // IsWindowDecorated reports whether the window is decorated. 29 // 30 // IsWindowDecorated is concurrent-safe. 31 func IsWindowDecorated() bool { 32 if w := uiDriver().Window(); w != nil { 33 return w.IsDecorated() 34 } 35 return false 36 } 37 38 // SetWindowDecorated sets the state if the window is decorated. 39 // 40 // The window is decorated by default. 41 // 42 // SetWindowDecorated works only on desktops. 43 // SetWindowDecorated does nothing on other platforms. 44 // 45 // SetWindowDecorated is concurrent-safe. 46 func SetWindowDecorated(decorated bool) { 47 if w := uiDriver().Window(); w != nil { 48 w.SetDecorated(decorated) 49 } 50 } 51 52 // IsWindowResizable reports whether the window is resizable by the user's dragging on desktops. 53 // On the other environments, IsWindowResizable always returns false. 54 // 55 // IsWindowResizable is concurrent-safe. 56 func IsWindowResizable() bool { 57 if w := uiDriver().Window(); w != nil { 58 return w.IsResizable() 59 } 60 return false 61 } 62 63 // SetWindowResizable sets whether the window is resizable by the user's dragging on desktops. 64 // On the other environments, SetWindowResizable does nothing. 65 // 66 // The window is not resizable by default. 67 // 68 // If SetWindowResizable is called with true and Run is used, SetWindowResizable panics. Use RunGame instead. 69 // 70 // SetWindowResizable is concurrent-safe. 71 func SetWindowResizable(resizable bool) { 72 theUIContext.setWindowResizable(resizable) 73 } 74 75 // SetWindowTitle sets the title of the window. 76 // 77 // SetWindowTitle does nothing on browsers or mobiles. 78 // 79 // SetWindowTitle is concurrent-safe. 80 func SetWindowTitle(title string) { 81 if w := uiDriver().Window(); w != nil { 82 w.SetTitle(title) 83 } 84 } 85 86 // SetWindowIcon sets the icon of the game window. 87 // 88 // If len(iconImages) is 0, SetWindowIcon reverts the icon to the default one. 89 // 90 // For desktops, see the document of glfwSetWindowIcon of GLFW 3.2: 91 // 92 // This function sets the icon of the specified window. 93 // If passed an array of candidate images, those of or closest to the sizes 94 // desired by the system are selected. 95 // If no images are specified, the window reverts to its default icon. 96 // 97 // The desired image sizes varies depending on platform and system settings. 98 // The selected images will be rescaled as needed. 99 // Good sizes include 16x16, 32x32 and 48x48. 100 // 101 // As macOS windows don't have icons, SetWindowIcon doesn't work on macOS. 102 // 103 // SetWindowIcon doesn't work on browsers or mobiles. 104 // 105 // SetWindowIcon is concurrent-safe. 106 func SetWindowIcon(iconImages []image.Image) { 107 if w := uiDriver().Window(); w != nil { 108 w.SetIcon(iconImages) 109 } 110 } 111 112 // WindowPosition returns the window position. 113 // The origin position is the left-upper corner of the current monitor. 114 // The unit is device-independent pixels. 115 // 116 // WindowPosition panics if the main loop does not start yet. 117 // 118 // WindowPosition returns the last window position on fullscreen mode. 119 // 120 // WindowPosition returns (0, 0) on browsers and mobiles. 121 // 122 // WindowPosition is concurrent-safe. 123 func WindowPosition() (x, y int) { 124 if x, y, ok := getInitWindowPosition(); ok { 125 return x, y 126 } 127 if w := uiDriver().Window(); w != nil { 128 return w.Position() 129 } 130 return 0, 0 131 } 132 133 // SetWindowPosition sets the window position. 134 // The origin position is the left-upper corner of the current monitor. 135 // The unit is device-independent pixels. 136 // 137 // SetWindowPosition does nothing on fullscreen mode. 138 // 139 // SetWindowPosition does nothing on browsers and mobiles. 140 // 141 // SetWindowPosition is concurrent-safe. 142 func SetWindowPosition(x, y int) { 143 if setInitWindowPosition(x, y) { 144 return 145 } 146 if w := uiDriver().Window(); w != nil { 147 w.SetPosition(x, y) 148 } 149 } 150 151 var ( 152 windowM sync.Mutex 153 initWindowPosition = &struct { 154 x int 155 y int 156 }{ 157 x: invalidPos, 158 y: invalidPos, 159 } 160 ) 161 162 func getInitWindowPosition() (x, y int, ok bool) { 163 windowM.Lock() 164 defer windowM.Unlock() 165 if initWindowPosition == nil { 166 return 0, 0, false 167 } 168 if initWindowPosition.x == invalidPos || initWindowPosition.y == invalidPos { 169 return 0, 0, false 170 } 171 return initWindowPosition.x, initWindowPosition.y, true 172 } 173 174 func setInitWindowPosition(x, y int) bool { 175 windowM.Lock() 176 defer windowM.Unlock() 177 if initWindowPosition == nil { 178 return false 179 } 180 initWindowPosition.x = x 181 initWindowPosition.y = y 182 return true 183 } 184 185 func fixWindowPosition(width, height int) { 186 windowM.Lock() 187 defer windowM.Unlock() 188 189 defer func() { 190 initWindowPosition = nil 191 }() 192 193 w := uiDriver().Window() 194 if w == nil { 195 return 196 } 197 198 if initWindowPosition.x == invalidPos || initWindowPosition.y == invalidPos { 199 sw, sh := uiDriver().ScreenSizeInFullscreen() 200 x := (sw - width) / 2 201 y := (sh - height) / 3 202 w.SetPosition(x, y) 203 } else { 204 w.SetPosition(initWindowPosition.x, initWindowPosition.y) 205 } 206 } 207 208 // WindowSize returns the window size on desktops. 209 // WindowSize returns (0, 0) on other environments. 210 // 211 // On fullscreen mode, WindowSize returns the original window size. 212 // 213 // WindowSize is concurrent-safe. 214 func WindowSize() (int, int) { 215 if w := uiDriver().Window(); w != nil { 216 return w.Size() 217 } 218 return 0, 0 219 } 220 221 // SetWindowSize sets the window size on desktops. 222 // SetWindowSize does nothing on other environments. 223 // 224 // On fullscreen mode, SetWindowSize sets the original window size. 225 // 226 // SetWindowSize panics if width or height is not a positive number. 227 // 228 // SetWindowSize is concurrent-safe. 229 func SetWindowSize(width, height int) { 230 if width <= 0 || height <= 0 { 231 panic("ebiten: width and height must be positive") 232 } 233 if w := uiDriver().Window(); w != nil { 234 w.SetSize(width, height) 235 } 236 } 237 238 // IsWindowFloating reports whether the window is always shown above all the other windows. 239 // 240 // IsWindowFloating returns false on browsers and mobiles. 241 // 242 // IsWindowFloating is concurrent-safe. 243 func IsWindowFloating() bool { 244 if w := uiDriver().Window(); w != nil { 245 return w.IsFloating() 246 } 247 return false 248 } 249 250 // SetWindowFloating sets the state whether the window is always shown above all the other windows. 251 // 252 // SetWindowFloating does nothing on browsers or mobiles. 253 // 254 // SetWindowFloating is concurrent-safe. 255 func SetWindowFloating(float bool) { 256 if w := uiDriver().Window(); w != nil { 257 w.SetFloating(float) 258 } 259 } 260 261 // MaximizeWindow maximizes the window. 262 // 263 // MaximizeWindow panics when the window is not resizable. 264 // 265 // MaximizeWindow does nothing on browsers or mobiles. 266 // 267 // MaximizeWindow is concurrent-safe. 268 func MaximizeWindow() { 269 if !IsWindowResizable() { 270 panic("ebiten: a window to maximize must be resizable") 271 } 272 if w := uiDriver().Window(); w != nil { 273 w.Maximize() 274 } 275 } 276 277 // IsWindowMaximized reports whether the window is maximized or not. 278 // 279 // IsWindowMaximized returns false when the window is not resizable. 280 // 281 // IsWindowMaximized always returns false on browsers and mobiles. 282 // 283 // IsWindowMaximized is concurrent-safe. 284 func IsWindowMaximized() bool { 285 if !IsWindowResizable() { 286 return false 287 } 288 if w := uiDriver().Window(); w != nil { 289 return w.IsMaximized() 290 } 291 return false 292 } 293 294 // MinimizeWindow minimizes the window. 295 // 296 // If the main loop does not start yet, MinimizeWindow does nothing. 297 // 298 // MinimizeWindow does nothing on browsers or mobiles. 299 // 300 // MinimizeWindow is concurrent-safe. 301 func MinimizeWindow() { 302 if w := uiDriver().Window(); w != nil { 303 w.Minimize() 304 } 305 } 306 307 // IsWindowMinimized reports whether the window is minimized or not. 308 // 309 // IsWindowMinimized always returns false on browsers and mobiles. 310 // 311 // IsWindowMinimized is concurrent-safe. 312 func IsWindowMinimized() bool { 313 if w := uiDriver().Window(); w != nil { 314 return w.IsMinimized() 315 } 316 return false 317 } 318 319 // RestoreWindow restores the window from its maximized or minimized state. 320 // 321 // RestoreWindow panics when the window is not maximized nor minimized. 322 // 323 // RestoreWindow is concurrent-safe. 324 func RestoreWindow() { 325 if !IsWindowMaximized() && !IsWindowMinimized() { 326 panic("ebiten: RestoreWindow must be called on a maximized or a minimized window") 327 } 328 if w := uiDriver().Window(); w != nil { 329 w.Restore() 330 } 331 }