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

// 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)
}