clipboard: fix build on Windows
parent
6455e57e82
commit
b8f1152408
|
@ -2,45 +2,43 @@ module clipboard
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
#include <windows.h>
|
struct WndClassEx {
|
||||||
|
cbSize u32
|
||||||
type HANDLE voidptr
|
style u32
|
||||||
|
|
||||||
struct C.HWND
|
|
||||||
struct C.WPARAM
|
|
||||||
struct C.LPARAM
|
|
||||||
struct C.LRESULT
|
|
||||||
struct C.HGLOBAL
|
|
||||||
//struct C.HANDLE
|
|
||||||
|
|
||||||
struct C.WNDCLASSEX {
|
|
||||||
cbSize int
|
|
||||||
lpfnWndProc voidptr
|
lpfnWndProc voidptr
|
||||||
|
cbClsExtra int
|
||||||
|
cbWndExtra int
|
||||||
|
hInstance C.HINSTANCE
|
||||||
|
hIcon C.HICON
|
||||||
|
hCursor C.HCURSOR
|
||||||
|
hbrBackground C.HBRUSH
|
||||||
|
lpszMenuName &u16 // LPCWSTR
|
||||||
lpszClassName &u16
|
lpszClassName &u16
|
||||||
|
hIconSm &u16
|
||||||
}
|
}
|
||||||
|
|
||||||
fn C.RegisterClassEx(class WNDCLASSEX) int
|
fn C.RegisterClassEx(class WndClassEx) int
|
||||||
fn C.GetClipboardOwner() &HWND
|
fn C.GetClipboardOwner() &C.HWND
|
||||||
fn C.CreateWindowEx(dwExStyle i64, lpClassName &u16, lpWindowName &u16, dwStyle i64, x int, y int, nWidth int, nHeight int, hWndParent i64, hMenu voidptr, hInstance voidptr, lpParam voidptr) &HWND
|
fn C.CreateWindowEx(dwExStyle i64, lpClassName &u16, lpWindowName &u16, dwStyle i64, x int, y int, nWidth int, nHeight int, hWndParent i64, hMenu voidptr, hInstance voidptr, lpParam voidptr) &C.HWND
|
||||||
//fn C.MultiByteToWideChar(CodePage u32, dwFlags u16, lpMultiByteStr byteptr, cbMultiByte int, lpWideCharStr u16, cchWideChar int) int
|
//fn C.MultiByteToWideChar(CodePage u32, dwFlags u16, lpMultiByteStr byteptr, cbMultiByte int, lpWideCharStr u16, cchWideChar int) int
|
||||||
fn C.EmptyClipboard()
|
fn C.EmptyClipboard()
|
||||||
fn C.CloseClipboard()
|
fn C.CloseClipboard()
|
||||||
fn C.GlobalAlloc(uFlag u32, size i64) HGLOBAL
|
fn C.GlobalAlloc(uFlag u32, size i64) C.HGLOBAL
|
||||||
fn C.GlobalFree(buf HGLOBAL)
|
fn C.GlobalFree(buf C.HGLOBAL)
|
||||||
fn C.GlobalLock(buf HGLOBAL)
|
fn C.GlobalLock(buf C.HGLOBAL)
|
||||||
fn C.GlobalUnlock(buf HGLOBAL)
|
fn C.GlobalUnlock(buf C.HGLOBAL)
|
||||||
fn C.SetClipboardData(uFormat u32, data voidptr) C.HANDLE
|
fn C.SetClipboardData(uFormat u32, data voidptr) C.HANDLE
|
||||||
fn C.GetClipboardData(uFormat u32) C.HANDLE
|
fn C.GetClipboardData(uFormat u32) C.HANDLE
|
||||||
fn C.DefWindowProc(hwnd HWND, msg u32, wParam WPARAM, lParam LPARAM) LRESULT
|
fn C.DefWindowProc(hwnd C.HWND, msg u32, wParam C.WPARAM, lParam C.LPARAM) C.LRESULT
|
||||||
fn C.SetLastError(error i64)
|
fn C.SetLastError(error i64)
|
||||||
fn C.OpenClipboard(hwnd HWND) int
|
fn C.OpenClipboard(hwnd C.HWND) int
|
||||||
fn C.DestroyWindow(hwnd HWND)
|
fn C.DestroyWindow(hwnd C.HWND)
|
||||||
|
|
||||||
pub struct Clipboard {
|
struct Clipboard {
|
||||||
max_retries int
|
max_retries int
|
||||||
retry_delay int
|
retry_delay int
|
||||||
mut:
|
mut:
|
||||||
hwnd HWND
|
hwnd C.HWND
|
||||||
foo int // TODO remove
|
foo int // TODO remove
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +51,8 @@ fn (cb &Clipboard) get_clipboard_lock() bool {
|
||||||
if retries < 0 {
|
if retries < 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
last_error = GetLastError()
|
last_error = C.GetLastError()
|
||||||
if OpenClipboard(cb.hwnd) > 0 {
|
if C.OpenClipboard(cb.hwnd) > 0 {
|
||||||
return true
|
return true
|
||||||
} else if last_error != u32(C.ERROR_ACCESS_DENIED) {
|
} else if last_error != u32(C.ERROR_ACCESS_DENIED) {
|
||||||
return false
|
return false
|
||||||
|
@ -62,7 +60,7 @@ fn (cb &Clipboard) get_clipboard_lock() bool {
|
||||||
|
|
||||||
time.sleep(cb.retry_delay)
|
time.sleep(cb.retry_delay)
|
||||||
}
|
}
|
||||||
SetLastError(last_error)
|
C.SetLastError(last_error)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,15 +69,18 @@ fn new_clipboard() &Clipboard {
|
||||||
max_retries: 5
|
max_retries: 5
|
||||||
retry_delay: 5
|
retry_delay: 5
|
||||||
}
|
}
|
||||||
wndclass := WNDCLASSEX{
|
class_name := "clipboard"
|
||||||
cbSize: sizeof(WNDCLASSEX)
|
wndclass := WndClassEx {
|
||||||
lpfnWndProc: voidptr(&DefWindowProc)
|
cbSize: sizeof(WndClassEx)
|
||||||
lpszClassName: "clipboard".to_wide()
|
lpfnWndProc: voidptr(&C.DefWindowProc)
|
||||||
|
lpszClassName: class_name.to_wide()
|
||||||
|
lpszMenuName: 0
|
||||||
|
hIconSm: 0
|
||||||
}
|
}
|
||||||
if RegisterClassEx(&wndclass) <= 0 && GetLastError() != u32(C.ERROR_CLASS_ALREADY_EXISTS) {
|
if C.RegisterClassEx(&wndclass) == 0 && C.GetLastError() != u32(C.ERROR_CLASS_ALREADY_EXISTS) {
|
||||||
println("Failed registering class.")
|
println("Failed registering class.")
|
||||||
}
|
}
|
||||||
hwnd := CreateWindowEx(0, wndclass.lpszClassName, wndclass.lpszClassName, 0, 0, 0, 0, 0, C.HWND_MESSAGE, C.NULL, C.NULL, C.NULL)
|
hwnd := C.CreateWindowEx(0, wndclass.lpszClassName, wndclass.lpszClassName, 0, 0, 0, 0, 0, C.HWND_MESSAGE, C.NULL, C.NULL, C.NULL)
|
||||||
if hwnd == C.NULL {
|
if hwnd == C.NULL {
|
||||||
println("Error creating window!")
|
println("Error creating window!")
|
||||||
}
|
}
|
||||||
|
@ -88,34 +89,34 @@ fn new_clipboard() &Clipboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (cb &Clipboard) check_availability() bool {
|
fn (cb &Clipboard) check_availability() bool {
|
||||||
return cb.hwnd != HWND(C.NULL)
|
return cb.hwnd != C.HWND(C.NULL)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (cb &Clipboard) has_ownership() bool {
|
fn (cb &Clipboard) has_ownership() bool {
|
||||||
return GetClipboardOwner() == cb.hwnd
|
return C.GetClipboardOwner() == cb.hwnd
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (cb mut Clipboard) clear() {
|
fn (cb mut Clipboard) clear() {
|
||||||
if !cb.get_clipboard_lock() {return}
|
if !cb.get_clipboard_lock() {return}
|
||||||
EmptyClipboard()
|
C.EmptyClipboard()
|
||||||
CloseClipboard()
|
C.CloseClipboard()
|
||||||
cb.foo = 0
|
cb.foo = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (cb mut Clipboard) free(){
|
fn (cb mut Clipboard) free(){
|
||||||
DestroyWindow(cb.hwnd)
|
C.DestroyWindow(cb.hwnd)
|
||||||
cb.foo = 0
|
cb.foo = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// the string.to_wide doesn't work with SetClipboardData, don't know why
|
// the string.to_wide doesn't work with SetClipboardData, don't know why
|
||||||
fn to_wide(text string) &HGLOBAL {
|
fn to_wide(text string) &C.HGLOBAL {
|
||||||
len_required := MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, C.NULL, 0)
|
len_required := C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, C.NULL, 0)
|
||||||
buf := GlobalAlloc(C.GMEM_MOVEABLE, sizeof(u16) * len_required)
|
buf := C.GlobalAlloc(C.GMEM_MOVEABLE, sizeof(u16) * len_required)
|
||||||
if buf != HGLOBAL(C.NULL) {
|
if buf != C.HGLOBAL(C.NULL) {
|
||||||
mut locked := &u16(GlobalLock(buf))
|
mut locked := &u16(C.GlobalLock(buf))
|
||||||
MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, locked, len_required)
|
C.MultiByteToWideChar(C.CP_UTF8, C.MB_ERR_INVALID_CHARS, text.str, text.len + 1, locked, len_required)
|
||||||
locked[len_required - 1] = u16(0)
|
locked[len_required - 1] = u16(0)
|
||||||
GlobalUnlock(buf)
|
C.GlobalUnlock(buf)
|
||||||
}
|
}
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
@ -124,20 +125,20 @@ fn (cb mut Clipboard) set_text(text string) bool {
|
||||||
cb.foo = 0
|
cb.foo = 0
|
||||||
buf := to_wide(text)
|
buf := to_wide(text)
|
||||||
if !cb.get_clipboard_lock() {
|
if !cb.get_clipboard_lock() {
|
||||||
GlobalFree(buf)
|
C.GlobalFree(buf)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
// EmptyClipboard must be called to properly update clipboard ownership
|
// EmptyClipboard must be called to properly update clipboard ownership
|
||||||
EmptyClipboard()
|
C.EmptyClipboard()
|
||||||
if SetClipboardData(C.CF_UNICODETEXT, buf) == HANDLE(C.NULL) {
|
if C.SetClipboardData(C.CF_UNICODETEXT, buf) == C.HANDLE(C.NULL) {
|
||||||
println("SetClipboardData: Failed.")
|
println("SetClipboardData: Failed.")
|
||||||
CloseClipboard()
|
C.CloseClipboard()
|
||||||
GlobalFree(buf)
|
C.GlobalFree(buf)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// CloseClipboard appears to change the sequence number...
|
// CloseClipboard appears to change the sequence number...
|
||||||
CloseClipboard()
|
C.CloseClipboard()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,13 +147,13 @@ fn (cb mut Clipboard) get_text() string {
|
||||||
if !cb.get_clipboard_lock() {
|
if !cb.get_clipboard_lock() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
h_data := GetClipboardData(C.CF_UNICODETEXT)
|
h_data := C.GetClipboardData(C.CF_UNICODETEXT)
|
||||||
if h_data == HANDLE(C.NULL) {
|
if h_data == C.HANDLE(C.NULL) {
|
||||||
CloseClipboard()
|
C.CloseClipboard()
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
str := string_from_wide(&u16(GlobalLock(h_data)))
|
str := string_from_wide(&u16(C.GlobalLock(h_data)))
|
||||||
GlobalUnlock(h_data)
|
C.GlobalUnlock(h_data)
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue