You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
2.8 KiB
Go
143 lines
2.8 KiB
Go
// Package main provides ...
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"syscall"
|
|
"unsafe"
|
|
//"io/ioutil"
|
|
//"github.com/fvbock/endless"
|
|
"github.com/gin-gonic/gin"
|
|
//"log"
|
|
"net/http"
|
|
// "os"
|
|
// "os/exec"
|
|
)
|
|
|
|
const (
|
|
MOUSE_X = 1000
|
|
MOUSE_Y = 1000
|
|
M_POINT = ( MOUSE_X & 0xFFFFFFFF ) | ( MOUSE_Y << 32 )
|
|
VPC_SOURCE_SELECT = '\x60'
|
|
WINDOWS_M = 15
|
|
LINUX_M = 17
|
|
|
|
WINDOWS_PARAM = "windows"
|
|
LINUX_PARAM = "linux"
|
|
)
|
|
|
|
var (
|
|
user32, _ = syscall.LoadLibrary("User32.dll")
|
|
dxva2, _ = syscall.LoadLibrary("dxva2.dll")
|
|
monitorFromPoint, _ = syscall.GetProcAddress(user32, "MonitorFromPoint")
|
|
GetPhysicalMonitorsFromHMONITOR, _ = syscall.GetProcAddress(dxva2, "GetPhysicalMonitorsFromHMONITOR")
|
|
SetVCPFeature, _ = syscall.GetProcAddress(dxva2, "SetVCPFeature")
|
|
DestroyPhysicalMonitor, _ = syscall.GetProcAddress(dxva2, "DestroyPhysicalMonitor")
|
|
)
|
|
|
|
func switchMonitorHandler(c *gin.Context) {
|
|
|
|
os := c.Param("os")
|
|
|
|
switch os {
|
|
case WINDOWS_PARAM:
|
|
go setMonitorInputSource(WINDOWS_M)
|
|
case LINUX_PARAM:
|
|
go setMonitorInputSource(LINUX_M)
|
|
}
|
|
|
|
//fmt.Printf("Received command %s", command)
|
|
c.String(http.StatusOK, fmt.Sprintf("monitor switched to %s!", os))
|
|
}
|
|
|
|
|
|
func getMonitorHandle() (result uintptr) {
|
|
var nargs uintptr = 2
|
|
ret, _, callErr := syscall.Syscall(
|
|
uintptr(monitorFromPoint),
|
|
nargs,
|
|
uintptr(M_POINT),
|
|
uintptr(1),
|
|
0)
|
|
|
|
if callErr != 0 {
|
|
abort("Call getMonitorHandle", callErr)
|
|
}
|
|
|
|
res := uintptr(ret)
|
|
result = getPhysicalMonitor(res)
|
|
return
|
|
}
|
|
|
|
func getPhysicalMonitor(handle uintptr) (result uintptr) {
|
|
b := make([]byte, 256)
|
|
var nargs uintptr = 3
|
|
_, _, callErr := syscall.Syscall(
|
|
uintptr(GetPhysicalMonitorsFromHMONITOR),
|
|
nargs,
|
|
handle,
|
|
uintptr(1),
|
|
uintptr(unsafe.Pointer(&b[0])))
|
|
|
|
if callErr != 0 {
|
|
abort("Call getPhysicalMonitor", callErr)
|
|
}
|
|
result = uintptr(b[0])
|
|
return
|
|
}
|
|
|
|
func setMonitorInputSource(source int) {
|
|
mHandle := getMonitorHandle()
|
|
|
|
var nargs uintptr = 3
|
|
_, _, callErr := syscall.Syscall(
|
|
uintptr(SetVCPFeature),
|
|
nargs,
|
|
uintptr(mHandle),
|
|
VPC_SOURCE_SELECT,
|
|
uintptr(source))
|
|
|
|
if callErr != 0 {
|
|
abort("Call SetVCPFeature", callErr)
|
|
}
|
|
destroyPhysicalMonitor(mHandle)
|
|
}
|
|
|
|
func destroyPhysicalMonitor(monitor uintptr) {
|
|
var nargs uintptr = 1
|
|
_, _, callErr := syscall.Syscall(
|
|
uintptr(DestroyPhysicalMonitor),
|
|
nargs,
|
|
monitor,
|
|
0,
|
|
0)
|
|
|
|
if callErr != 0 {
|
|
abort("Call destroyPhysicalMonitor", callErr)
|
|
}
|
|
}
|
|
|
|
func abort(funcname string, err error) {
|
|
panic(fmt.Sprintf("%s failed: %v", funcname, err))
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
defer syscall.FreeLibrary(user32)
|
|
defer syscall.FreeLibrary(dxva2)
|
|
|
|
router := gin.Default()
|
|
|
|
router.Use(gin.Logger())
|
|
router.Use(gin.Recovery())
|
|
|
|
monitor := router.Group("/monitor")
|
|
{
|
|
monitor.GET("/switch/:os", switchMonitorHandler)
|
|
}
|
|
|
|
router.Run(":7500")
|
|
//endless.ListenAndServe(":7500", router)
|
|
}
|