clipboard: fix build on Windows

pull/4237/head
Alexey 2020-04-04 16:37:13 +03:00 committed by GitHub
parent 6455e57e82
commit b8f1152408
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 58 additions and 57 deletions

View File

@ -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
} }