zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

ui_windows.go (5755B)


      1 // Copyright 2016 Hajime Hoshi
      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 glfw
     16 
     17 import (
     18 	"fmt"
     19 	"runtime"
     20 	"unsafe"
     21 
     22 	"golang.org/x/sys/windows"
     23 
     24 	"github.com/hajimehoshi/ebiten/v2/internal/driver"
     25 	"github.com/hajimehoshi/ebiten/v2/internal/glfw"
     26 )
     27 
     28 const (
     29 	smCyCaption             = 4
     30 	monitorDefaultToNearest = 2
     31 )
     32 
     33 type rect struct {
     34 	left   int32
     35 	top    int32
     36 	right  int32
     37 	bottom int32
     38 }
     39 
     40 type monitorInfo struct {
     41 	cbSize    uint32
     42 	rcMonitor rect
     43 	rcWork    rect
     44 	dwFlags   uint32
     45 }
     46 
     47 var (
     48 	// user32 is defined at hideconsole_windows.go
     49 	procGetSystemMetrics    = user32.NewProc("GetSystemMetrics")
     50 	procGetActiveWindow     = user32.NewProc("GetActiveWindow")
     51 	procGetForegroundWindow = user32.NewProc("GetForegroundWindow")
     52 	procMonitorFromWindow   = user32.NewProc("MonitorFromWindow")
     53 	procGetMonitorInfoW     = user32.NewProc("GetMonitorInfoW")
     54 )
     55 
     56 func getSystemMetrics(nIndex int) (int, error) {
     57 	r, _, e := procGetSystemMetrics.Call(uintptr(nIndex))
     58 	if e != nil && e.(windows.Errno) != 0 {
     59 		return 0, fmt.Errorf("ui: GetSystemMetrics failed: error code: %d", e)
     60 	}
     61 	return int(r), nil
     62 }
     63 
     64 func getActiveWindow() (uintptr, error) {
     65 	r, _, e := procGetActiveWindow.Call()
     66 	if e != nil && e.(windows.Errno) != 0 {
     67 		return 0, fmt.Errorf("ui: GetActiveWindow failed: error code: %d", e)
     68 	}
     69 	return r, nil
     70 }
     71 
     72 func getForegroundWindow() (uintptr, error) {
     73 	r, _, e := procGetForegroundWindow.Call()
     74 	if e != nil && e.(windows.Errno) != 0 {
     75 		return 0, fmt.Errorf("ui: GetForegroundWindow failed: error code: %d", e)
     76 	}
     77 	return r, nil
     78 }
     79 
     80 func monitorFromWindow(hwnd uintptr, dwFlags uint32) (uintptr, error) {
     81 	r, _, e := procMonitorFromWindow.Call(hwnd, uintptr(dwFlags))
     82 	if e != nil && e.(windows.Errno) != 0 {
     83 		return 0, fmt.Errorf("ui: MonitorFromWindow failed: error code: %d", e)
     84 	}
     85 	if r == 0 {
     86 		return 0, fmt.Errorf("ui: MonitorFromWindow failed: returned value: %d", r)
     87 	}
     88 	return r, nil
     89 }
     90 
     91 func getMonitorInfoW(hMonitor uintptr, lpmi *monitorInfo) error {
     92 	r, _, e := procGetMonitorInfoW.Call(hMonitor, uintptr(unsafe.Pointer(lpmi)))
     93 	if e != nil && e.(windows.Errno) != 0 {
     94 		return fmt.Errorf("ui: GetMonitorInfoW failed: error code: %d", e)
     95 	}
     96 	if r == 0 {
     97 		return fmt.Errorf("ui: GetMonitorInfoW failed: returned value: %d", r)
     98 	}
     99 	return nil
    100 }
    101 
    102 // clearVideoModeScaleCache must be called from the main thread.
    103 func clearVideoModeScaleCache() {}
    104 
    105 // videoModeScale must be called from the main thread.
    106 func videoModeScale(m *glfw.Monitor) float64 {
    107 	return 1
    108 }
    109 
    110 // fromGLFWMonitorPixel must be called from the main thread.
    111 func (u *UserInterface) fromGLFWMonitorPixel(x float64, videoModeScale float64) float64 {
    112 	return x / (videoModeScale * u.deviceScaleFactor())
    113 }
    114 
    115 // fromGLFWPixel must be called from the main thread.
    116 func (u *UserInterface) fromGLFWPixel(x float64) float64 {
    117 	return x / u.deviceScaleFactor()
    118 }
    119 
    120 // toGLFWPixel must be called from the main thread.
    121 func (u *UserInterface) toGLFWPixel(x float64) float64 {
    122 	return x * u.deviceScaleFactor()
    123 }
    124 
    125 func (u *UserInterface) adjustWindowPosition(x, y int) (int, int) {
    126 	mx, my := currentMonitor(u.window).GetPos()
    127 	// As the video width/height might be wrong,
    128 	// adjust x/y at least to enable to handle the window (#328)
    129 	if x < mx {
    130 		x = mx
    131 	}
    132 	t, err := getSystemMetrics(smCyCaption)
    133 	if err != nil {
    134 		panic(err)
    135 	}
    136 	if y < my+t {
    137 		y = my + t
    138 	}
    139 	return x, y
    140 }
    141 
    142 func currentMonitorByOS(_ *glfw.Window) *glfw.Monitor {
    143 	// TODO: Why not using the given window?
    144 
    145 	// TODO: Should we return nil here?
    146 	w, err := getActiveWindow()
    147 	if err != nil {
    148 		panic(err)
    149 	}
    150 
    151 	if w == 0 {
    152 		// The active window doesn't exist when launching, or the application is runnable on unfocused.
    153 		// Get the foreground window, that is common among multiple processes.
    154 		w, err = getForegroundWindow()
    155 		if err != nil {
    156 			panic(err)
    157 		}
    158 		if w == 0 {
    159 			// GetForegroundWindow can return null according to the document.
    160 			return nil
    161 		}
    162 	}
    163 
    164 	// Get the current monitor by the window handle instead of the window position. It is because the window
    165 	// position is not relaiable in some cases e.g. when the window is put across multiple monitors.
    166 
    167 	m, err := monitorFromWindow(w, monitorDefaultToNearest)
    168 	if err != nil {
    169 		// monitorFromWindow can return error on Wine. Ignore this.
    170 		return nil
    171 	}
    172 
    173 	mi := monitorInfo{}
    174 	mi.cbSize = uint32(unsafe.Sizeof(mi))
    175 	if err := getMonitorInfoW(m, &mi); err != nil {
    176 		panic(err)
    177 	}
    178 
    179 	x, y := int(mi.rcMonitor.left), int(mi.rcMonitor.top)
    180 	for _, m := range ensureMonitors() {
    181 		if m.x == x && m.y == y {
    182 			return m.m
    183 		}
    184 	}
    185 	return nil
    186 }
    187 
    188 func (u *UserInterface) nativeWindow() uintptr {
    189 	return u.window.GetWin32Window()
    190 }
    191 
    192 func (u *UserInterface) isNativeFullscreen() bool {
    193 	return false
    194 }
    195 
    196 func (u *UserInterface) setNativeCursor(shape driver.CursorShape) {
    197 	// TODO: Use native API in the future (#1571)
    198 	u.window.SetCursor(glfwSystemCursors[shape])
    199 }
    200 
    201 func (u *UserInterface) isNativeFullscreenAvailable() bool {
    202 	return false
    203 }
    204 
    205 func (u *UserInterface) setNativeFullscreen(fullscreen bool) {
    206 	panic(fmt.Sprintf("glfw: setNativeFullscreen is not implemented in this environment: %s", runtime.GOOS))
    207 }
    208 
    209 func (u *UserInterface) adjustViewSize() {
    210 }
    211 
    212 func initializeWindowAfterCreation(w *glfw.Window) {
    213 }