windows working

This commit is contained in:
Emil Lerch 2021-11-23 18:58:10 -08:00
parent 70163d4e12
commit 69d7d0611e
Signed by: lobo
GPG Key ID: A7B62D657EF764F8

View File

@ -341,6 +341,7 @@ const WM_INITMENUPOPUP = @as(u32, 279);
const WM_DRAWCLIPBOARD = @as(u32, 776);
const WM_SIZECLIPBOARD = @as(u32, 779);
const WM_CHANGECBCHAIN = @as(u32, 781);
const WM_CLIPBOARDUPDATE = @as(u32, 797);
const WM_USER = @as(u32, 1024);
// USER constants here - not part of Windows headers
@ -492,6 +493,60 @@ extern "USER32" fn UpdateWindow(
hWnd: ?w.HWND,
) callconv(w.WINAPI) BOOL;
const REDRAW_WINDOW_FLAGS = enum(u32) {
INVALIDATE = 1,
INTERNALPAINT = 2,
ERASE = 4,
VALIDATE = 8,
NOINTERNALPAINT = 16,
NOERASE = 32,
NOCHILDREN = 64,
ALLCHILDREN = 128,
UPDATENOW = 256,
ERASENOW = 512,
FRAME = 1024,
NOFRAME = 2048,
_,
pub fn initFlags(o: struct {
INVALIDATE: u1 = 0,
INTERNALPAINT: u1 = 0,
ERASE: u1 = 0,
VALIDATE: u1 = 0,
NOINTERNALPAINT: u1 = 0,
NOERASE: u1 = 0,
NOCHILDREN: u1 = 0,
ALLCHILDREN: u1 = 0,
UPDATENOW: u1 = 0,
ERASENOW: u1 = 0,
FRAME: u1 = 0,
NOFRAME: u1 = 0,
}) REDRAW_WINDOW_FLAGS {
return @intToEnum(REDRAW_WINDOW_FLAGS, (if (o.INVALIDATE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.INVALIDATE) else 0) | (if (o.INTERNALPAINT == 1) @enumToInt(REDRAW_WINDOW_FLAGS.INTERNALPAINT) else 0) | (if (o.ERASE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.ERASE) else 0) | (if (o.VALIDATE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.VALIDATE) else 0) | (if (o.NOINTERNALPAINT == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOINTERNALPAINT) else 0) | (if (o.NOERASE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOERASE) else 0) | (if (o.NOCHILDREN == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOCHILDREN) else 0) | (if (o.ALLCHILDREN == 1) @enumToInt(REDRAW_WINDOW_FLAGS.ALLCHILDREN) else 0) | (if (o.UPDATENOW == 1) @enumToInt(REDRAW_WINDOW_FLAGS.UPDATENOW) else 0) | (if (o.ERASENOW == 1) @enumToInt(REDRAW_WINDOW_FLAGS.ERASENOW) else 0) | (if (o.FRAME == 1) @enumToInt(REDRAW_WINDOW_FLAGS.FRAME) else 0) | (if (o.NOFRAME == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOFRAME) else 0));
}
};
const RDW_INVALIDATE = REDRAW_WINDOW_FLAGS.INVALIDATE;
const RDW_INTERNALPAINT = REDRAW_WINDOW_FLAGS.INTERNALPAINT;
const RDW_ERASE = REDRAW_WINDOW_FLAGS.ERASE;
const RDW_VALIDATE = REDRAW_WINDOW_FLAGS.VALIDATE;
const RDW_NOINTERNALPAINT = REDRAW_WINDOW_FLAGS.NOINTERNALPAINT;
const RDW_NOERASE = REDRAW_WINDOW_FLAGS.NOERASE;
const RDW_NOCHILDREN = REDRAW_WINDOW_FLAGS.NOCHILDREN;
const RDW_ALLCHILDREN = REDRAW_WINDOW_FLAGS.ALLCHILDREN;
const RDW_UPDATENOW = REDRAW_WINDOW_FLAGS.UPDATENOW;
const RDW_ERASENOW = REDRAW_WINDOW_FLAGS.ERASENOW;
const RDW_FRAME = REDRAW_WINDOW_FLAGS.FRAME;
const RDW_NOFRAME = REDRAW_WINDOW_FLAGS.NOFRAME;
const HGDIOBJ = *opaque {};
const HRGN = HGDIOBJ;
extern "USER32" fn RedrawWindow(
hWnd: ?w.HWND,
lprcUpdate: ?*const RECT,
hrgnUpdate: ?HRGN,
flags: REDRAW_WINDOW_FLAGS,
) callconv(w.WINAPI) BOOL;
// Data exchange
extern "USER32" fn GetClipboardData(
uFormat: u32,
@ -499,19 +554,19 @@ extern "USER32" fn GetClipboardData(
extern "USER32" fn GetClipboardOwner() callconv(w.WINAPI) ?w.HWND;
extern "USER32" fn SetClipboardViewer(
hWndNewViewer: ?w.HWND,
) callconv(w.WINAPI) ?w.HWND;
extern "USER32" fn OpenClipboard(
hWndNewOwner: ?w.HWND,
) callconv(w.WINAPI) BOOL;
extern "USER32" fn CloseClipboard() callconv(w.WINAPI) BOOL;
extern "USER32" fn ChangeClipboardChain(
hWndRemove: ?w.HWND,
hWndNewNext: ?w.HWND,
extern "USER32" fn AddClipboardFormatListener(
hwnd: ?w.HWND,
) callconv(w.WINAPI) BOOL;
// TODO: this type is limited to platform 'windows6.0.6000'
extern "USER32" fn RemoveClipboardFormatListener(
hwnd: ?w.HWND,
) callconv(w.WINAPI) BOOL;
extern "USER32" fn GetPriorityClipboardFormat(
@ -833,14 +888,29 @@ fn getWinStyleString(comptime buflen: u32, str: []const u8) [buflen]u8 {
return buf;
}
// Globals
var uFormat: w.UINT = @enumToInt(CF_TEXT);
var fAuto: w.BOOL = w.TRUE;
var icon_data: NOTIFYICONDATAA = undefined;
var window_state: union(enum(u8)) {
INITIAL = 0,
NORMAL = 1,
MINIMIZED = 2,
} = .INITIAL;
var gpa: std.heap.GeneralPurposeAllocator(.{}) = undefined;
var contents: [:0]const u8 = "";
var free_contents = false;
pub export fn wWinMain(hInstance: w.HINSTANCE, hPrevInstance: ?w.HINSTANCE, lpCmdLine: w.PWSTR, nCmdShow: w.INT) w.INT {
_ = hPrevInstance;
_ = lpCmdLine;
_ = nCmdShow;
gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
h_instance = hInstance;
dbg_msg = getWinStyleString(17, "TODO: Send now: x");
// Register the window class.
var wc: WNDCLASSA = .{
.lpszClassName = "Clipboard watcher",
@ -903,33 +973,8 @@ pub export fn wWinMain(hInstance: w.HINSTANCE, hPrevInstance: ?w.HINSTANCE, lpCm
return 0;
}
// Globals
var uFormat: w.UINT = @bitReverse(c_uint, 0);
var fAuto: w.BOOL = w.TRUE;
var hwndNextViewer: ?w.HWND = null;
var icon_data: NOTIFYICONDATAA = undefined;
var dbg_msg: [17]u8 = undefined;
var cnt: u8 = 0;
var window_state: union(enum(u8)) {
INITIAL = 0,
NORMAL = 1,
MINIMIZED = 2,
} = .INITIAL;
fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) callconv(w.WINAPI) w.LRESULT { //APIENTRY {
// static HWND hwndNextViewer;
//
// HDC hdc;
// HDC hdcMem;
// PAINTSTRUCT ps;
// LPPAINTSTRUCT lpps;
// RECT rc;
// LPRECT lprc;
// HGLOBAL hglb;
// LPSTR lpstr;
// HBITMAP hbm;
// HENHMETAFILE hemf;
// HWND hwndOwner;
const allocator = &gpa.allocator;
switch (uMsg) {
WM_PAINT => {
@ -989,21 +1034,9 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
// }
},
@enumToInt(CF_TEXT) => {
if (OpenClipboard(hwnd) > 0) {
var hglb = GetClipboardData(uFormat).?;
const hnd = @intCast(isize, @ptrToInt(hglb));
var lpstr = GlobalLock(hnd).?;
_ = GetClientRect(hwnd, &rc);
// TODO: copy our lpstr and ship it to our common handler
cnt = (cnt + 1) % 10;
dbg_msg[dbg_msg.len - 1] = '0' + cnt;
_ = MessageBoxA(hwnd, @ptrCast([*:0]const u8, &dbg_msg), "Debug", 0);
_ = DrawTextA(hdc, @ptrCast([*:0]const u8, lpstr), -1, &rc, DT_LEFT);
_ = GlobalUnlock(hnd);
_ = CloseClipboard();
}
_ = DrawTextA(hdc, contents, -1, &rc, DT_LEFT);
},
@enumToInt(CF_ENHMETAFILE) => {
@ -1043,6 +1076,7 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
},
WM_SIZE => {
if (uFormat == @enumToInt(CF_OWNERDISPLAY)) {
// I don't believe this will ever execute and can be removed
var hwndOwner = GetClipboardOwner().?;
var hglb = GlobalAlloc(GMEM_MOVEABLE, @sizeOf(RECT));
defer _ = GlobalFree(hglb);
@ -1054,11 +1088,35 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
_ = SendMessageA(hwndOwner, WM_SIZECLIPBOARD, @ptrToInt(hwnd), hglb);
}
},
WM_CLIPBOARDUPDATE => { // Message arrives only after AddClipboardFormatListener
// Get a lock on the clipboard
if (OpenClipboard(hwnd) > 0) {
defer _ = CloseClipboard();
var hglb = GetClipboardData(uFormat).?;
const hnd = @intCast(isize, @ptrToInt(hglb));
var lpstr = GlobalLock(hnd).?;
defer _ = GlobalUnlock(hnd);
if (free_contents) {
allocator.free(contents);
}
free_contents = true;
contents = std.fmt.allocPrintZ(allocator, "{s}", .{@ptrCast([*:0]const u8, lpstr)}) catch blk: {
_ = MessageBoxA(hwnd, "Allocation failed copying clipboard contents", "Error", 0);
free_contents = false;
break :blk "";
};
}
if (RedrawWindow(hwnd, null, null, RDW_INVALIDATE) != w.TRUE) {
_ = MessageBoxA(hwnd, "Redraw failed", "Error", 0);
}
},
WM_CREATE => {
// Add the window to the clipboard viewer chain.
hwndNextViewer = SetClipboardViewer(hwnd);
if (AddClipboardFormatListener(hwnd) != w.TRUE) {
_ = MessageBoxA(hwnd, "Could not add clipboard listener", "Error", 0);
return -1; // oops
}
var tip = getWinStyleString(128, "Clipboard processor");
icon_data = .{
.cbSize = @sizeOf(@TypeOf(icon_data)),
@ -1081,8 +1139,7 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
.guidItem = Guid.initString("3e781b84-3ffd-44a1-b3ab-11d0f90136f9"), // generated from duckduckgo
.hBalloonIcon = null,
};
// stData.hIcon = g_hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_TRAYICON));
// LoadStringSafe(IDS_TIP, stData.szTip, _countof(stData.szTip));
if (Shell_NotifyIconA(NIM_ADD, &icon_data) != w.TRUE) {
_ = MessageBoxA(hwnd, "Notification Icon failed to create", "Error", 0);
return -1; // oops
@ -1110,50 +1167,15 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
else => {},
}
},
WM_CHANGECBCHAIN => {
// If the next window is closing, repair the chain.
// if ((HWND) wParam == hwndNextViewer)
if (wParam == @ptrToInt(hwndNextViewer.?)) {
hwndNextViewer = @intToPtr(w.HWND, @intCast(usize, lParam)); // just a cast
// Otherwise, pass the message to the next link.
} else if (hwndNextViewer) |hnv| {
_ = SendMessageA(hnv, uMsg, wParam, lParam);
}
},
WM_DESTROY => {
_ = ChangeClipboardChain(hwnd, hwndNextViewer);
_ = RemoveClipboardFormatListener(hwnd);
_ = Shell_NotifyIconA(NIM_DELETE, &icon_data);
PostQuitMessage(0);
},
WM_DRAWCLIPBOARD => { // clipboard contents changed.
// Update the window by using Auto clipboard format.
SetAutoView(hwnd);
// Pass the message to the next window in clipboard
// viewer chain.
_ = SendMessageA(hwndNextViewer, uMsg, wParam, lParam);
},
WM_INITMENUPOPUP => {
// if (!HIWORD(lParam))
// if (lParam > 0xffffffff)
// InitMenu(hwnd, wParam); // (HMENU) wParam);
},
WM_COMMAND => {
// switch (LOWORD(wParam)) {
switch (wParam & 0xffffffff) {
IDM_EXIT => _ = DestroyWindow(hwnd),
// IDM_AUTO => SetAutoView(hwnd),
else => {
fAuto = w.FALSE;
uFormat = @intCast(w.UINT, wParam & 0xffffffff); // LOWORD(wParam);
@ -1165,103 +1187,3 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
}
return 0;
}
var auPriorityList: [4]u32 = .{
@enumToInt(CF_OWNERDISPLAY),
@enumToInt(CF_TEXT),
@enumToInt(CF_ENHMETAFILE),
@enumToInt(CF_BITMAP),
};
fn SetAutoView(hwnd: w.HWND) callconv(w.WINAPI) void {
var runtime_zero: usize = 0;
var auPriorityListSlice = auPriorityList[runtime_zero..auPriorityList.len];
uFormat = @intCast(c_uint, GetPriorityClipboardFormat(auPriorityListSlice.ptr, 4));
fAuto = w.TRUE;
_ = InvalidateRect(hwnd, null, w.TRUE);
_ = UpdateWindow(hwnd);
}
// fn InitMenu(hwnd: w.HWND, hmenu: w.HMENU) callconv(w.WINAPI) void {
// // UINT uFormat;
// // char szFormatName[80];
// // LPCSTR lpFormatName;
// // UINT fuFlags;
// // UINT idMenuItem;
//
// // If a menu is not the display menu, no initialization is necessary.
//
// if (GetMenuItemID(hmenu, 0) != IDM_AUTO)
// return;
//
// // Delete all menu items except the first.
//
// while (GetMenuItemCount(hmenu) > 1)
// DeleteMenu(hmenu, 1, MF_BYPOSITION);
//
// // Check or uncheck the Auto menu item.
//
// if (fAuto) {
// fuFlags = MF_BYCOMMAND | MF_CHECKED;
// } else fuFlags = MF_BYCOMMAND | MF_UNCHECKED;
//
// CheckMenuItem(hmenu, IDM_AUTO, fuFlags);
//
// // If there are no clipboard formats, return.
//
// if (CountClipboardFormats() == 0)
// return;
//
// // Open the clipboard.
//
// if (!OpenClipboard(hwnd))
// return;
//
// // Add a separator and then a menu item for each format.
//
// AppendMenu(hmenu, MF_SEPARATOR, 0, null);
// var uFormat = EnumClipboardFormats(0);
//
// while (uFormat) {
// // Call an application-defined function to get the name
// // of the clipboard format.
//
// var lpFormatName = GetPredefinedClipboardFormatName(uFormat);
//
// // For registered formats, get the registered name.
//
// if (lpFormatName == null) {
//
// // Note that, if the format name is larger than the
// // buffer, it is truncated.
// if (GetClipboardFormatName(uFormat, szFormatName, @sizeOf(szFormatName))) {
// lpFormatName = szFormatName;
// } else lpFormatName = "(unknown)";
// }
//
// // Add a menu item for the format. For displayable
// // formats, use the format ID for the menu ID.
//
// if (IsDisplayableFormat(uFormat)) {
// fuFlags = MF_STRING;
// idMenuItem = uFormat;
// } else {
// fuFlags = MF_STRING | MF_GRAYED;
// idMenuItem = 0;
// }
// AppendMenu(hmenu, fuFlags, idMenuItem, lpFormatName);
//
// uFormat = EnumClipboardFormats(uFormat);
// }
// CloseClipboard();
// }
//
// fn IsDisplayableFormat(ufmt: w.UINT) callconv(w.WINAPI) w.BOOL {
// switch (ufmt) {
// CF_OWNERDISPLAY => return true,
// CF_TEXT => return true,
// CF_ENHMETAFILE => return true,
// CF_BITMAP => return true,
// else => return false,
// }
// }