@@ -103,7 +103,6 @@ fun registerClassW(wc WindowClass) Atom {
103103 // TODO still bad idea cause pointers to strings (aka wide chars)
104104
105105 tail.next = list
106- tail = tail.next
107106
108107 // TODO handle that proc can be null
109108 tofitaDebugLog("registerClassW done".utf16())
@@ -178,11 +177,19 @@ fun createWindowExW(
178177 // TODO test zero-width
179178 // TODO Hexa: encode as `enum WindowSize { CW_USE_DEFAULT = 123 Custom = .../_ } case Custom(value):`
180179 // TODO respect CW_USE_DEFAULT etc for pos and size
181- payload.nWidth = nWidth <= 0? 316 : nWidth
182- payload.nHeight = nHeight <= 0? 163 : nHeight
180+ payload.nWidth = nWidth <= 0? 640 : nWidth
181+ payload.nHeight = nHeight <= 0? 400 : nHeight
183182 tofitaDebugLog("> CreateWindowExW requested size %d x %d".utf16(), nWidth as! UInt64, nHeight as! UInt64)
184183 // TODO pass params as tags? are all those params even needed in server?
185184
185+ // if hWndParent != null and nWidth <= 0 {
186+ // // TODO If CW_USEDEFAULT is specified for a pop-up or child window, nWidth and nHeight are set to zero.
187+ // if let parent = handleToWindow(hWndParent) {
188+ // payload.nWidth = 0 // parent.width
189+ // payload.nHeight = 0 // parent.height
190+ // }
191+ // }
192+
186193 // Create local window counterpart
187194 let window = Window()
188195 tofitaDebugLog("> window = {%8}".utf16(), window as! UInt64)
@@ -213,8 +220,38 @@ fun createWindowExW(
213220 // TODO `payload.x` must be updated in the syscall instead
214221 window.x = x
215222 window.y = y
223+
224+ // `CW_USE_DEFAULT`
225+ if window.x < 0 {
226+ window.x = 0 // NOTE currently non-zero breaks `miceTarget`
227+ }
228+
229+ if window.y < 0 {
230+ window.y = 0 // NOTE currently non-zero breaks `miceTarget`
231+ }
232+
216233 window.width = payload.nWidth
234+ window.width = nWidth
235+
217236 window.height = payload.nHeight
237+ window.height = nHeight
238+
239+ if nWidth < 0 {
240+ if hWndParent != null {
241+ window.width = 0
242+ } else {
243+ window.width = payload.nWidth
244+ }
245+ }
246+
247+ if nHeight < 0 {
248+ if hWndParent != null {
249+ window.height = 0
250+ } else {
251+ window.height = payload.nHeight
252+ }
253+ }
254+
218255 // TODO null should produce `"null"`
219256 // TODO window name limit?
220257 window.title = isAtom(lpWindowName as! UInt64) ? '#' + (lpWindowName as! UInt64) : String.fromUTF16zUpTo(lpWindowName as! ConstArrayPointer<UInt16>, 4096)
@@ -223,6 +260,9 @@ fun createWindowExW(
223260 window.style = dwStyle
224261 window.exStyle = dwExStyle
225262
263+ // TODO some template parsing is unclear
264+ // window.style = window.style | window.exStyle
265+
226266 // TODO change to a helper `isDesktopWindow()` or `isDesktopOwnedWindow()`
227267 if windowId != 0 {
228268 // Whole framebuffer
@@ -452,9 +492,25 @@ fun render(window Window, msg Msg) LResult? {
452492 child.clipWidth = child.width
453493 child.clipHeight = child.height
454494
455- render(child, msg)
456495 // TODO Hexa: `render(child, {...msg, hwnd: child as! HWnd})` + ensure its on stack
457496 // let childMsg = Msg() // TODO ensure allocated on stack
497+ let childMsg = ByValue<Msg>()
498+ let childMsg = childMsg.ref
499+ childMsg.hwnd = child as! HWnd
500+ childMsg.message = msg.message
501+ childMsg.message = Message.WM_PAINT
502+ childMsg.wParam = msg.wParam // TODO
503+ childMsg.lParam = msg.lParam // TODO
504+
505+ child.clipX = 0
506+ child.clipY = 0
507+ child.clipWidth = child.width
508+ child.clipHeight = child.height
509+
510+ childMsg.wParam = 0 as! WParam
511+ childMsg.lParam = 0 as! LParam
512+ // render(child, childMsg)
513+ postMessageW(childMsg.hwnd, childMsg.message, childMsg.wParam, childMsg.lParam)
458514
459515 /*
460516 TODO Probably adding local message queue for speed makes sense (for messages produced within the app like this one)
@@ -544,6 +600,10 @@ fun dispatchMessageW(msg Msg) LResult? {
544600 let y Int32 = LParam.hiWord(lParam) - frameHeight // Tofita sends non-client mouse
545601 tofitaDebugLog(">> x = %d, y = %d".utf16(), x as! UInt64, y as! UInt64)
546602
603+ // TODO screen coordinates should come from the DWM
604+ msg.pt.ref.x = x
605+ msg.pt.ref.y = y
606+
547607 // Find the target window (parent or child) under the cursor
548608 let targetWindow = miceTarget(window, x, y)
549609 if let targetWindow = targetWindow {
@@ -556,7 +616,10 @@ fun dispatchMessageW(msg Msg) LResult? {
556616 result = targetWindow.proc(targetWindow as! HWnd, msg.message, msg.wParam, translatedLParam)
557617 } else {
558618 tofitaDebugLog("> No window found under cursor".utf16())
559- result = window.proc(msg.hwnd, msg.message, msg.wParam, msg.lParam)
619+ let translatedX = x
620+ let translatedY = y
621+ let translatedLParam = LParam.makeULong(translatedX as! UInt16, translatedY as! UInt16) as! LParam
622+ result = window.proc(msg.hwnd, msg.message, msg.wParam, translatedLParam)
560623 }
561624 } else if msg.message == Message.WM_TIMER, msg.lParam != null {
562625 // TODO capture exceptions and flag for non-capturing
@@ -597,14 +660,18 @@ fun postQuitMessage(nExitCode Int32) Void {
597660
598661@dllExport('BeginPaint')
599662fun beginPaint(hWnd HWnd, ps PaintStruct) HDc {
600- let window = handleToWindow(hWnd)
601663 tofitaDebugLog("beginPaint called HWnd = %8".utf16(), hWnd as! UInt64)
664+ var window = handleToWindow(hWnd)
602665 // TODO guard `let window = window ?? return null`
603666 if window == null {
604667 tofitaDebugLog("> window == null, cancelling".utf16())
605668 return null
606669 }
607670
671+ while window.parent != null {
672+ window = window.parent
673+ }
674+
608675 let dc = window.dc
609676 let fb = dc.fb.ref
610677 if fb == null {
@@ -626,6 +693,12 @@ fun beginPaint(hWnd HWnd, ps PaintStruct) HDc {
626693 rcPaint.bottom = fb.height as! Int32
627694 rcPaint.bottom = window.clipY + window.clipHeight // TODO MIN(fb.height)
628695
696+ // Default to entire *client* area
697+ rcPaint.left = 0
698+ rcPaint.top = 0
699+ rcPaint.right = fb.width as! Int32
700+ rcPaint.bottom = fb.height as! Int32
701+
629702 // Set fErase (assume true if no WM_ERASEBKGND handler)
630703 ps.fErase = Bool32.True // TODO Check if background was erased
631704
@@ -900,11 +973,20 @@ fun endPaint(hWnd HWnd, ps PaintStruct) Bool32 {
900973 // TODO respect ps
901974 tofitaDebugLog("endPaint called with hWnd %8 lpps %8".utf16(), hWnd as! UInt64, ps as! UInt64)
902975 // TODO `?? return 0` (hardcoded `return\throw` for now)
903- let window = handleToWindow(hWnd)
976+ var window = handleToWindow(hWnd)
904977 if window == null {
905978 return Bool32.False
906979 }
980+
981+ // TODO unify this somehow, into function/method or logically
982+ while window.parent != null {
983+ window = window.parent
984+ }
985+
907986 let dc = window.dc
987+ if dc == null {
988+ return Bool32.False
989+ }
908990 let fb = dc.fb.ref
909991 njraaSwapWindowFramebuffer(fb)
910992 // TODO ^ could be there multiple End Paint event? Probably swap after primary WM_PAINT
@@ -1238,6 +1320,19 @@ fun invalidateRect(hWnd HWnd?, lprc Rect, bErase Bool32) Bool32 {
12381320 // TODO Mark rectangle for repainting
12391321 tofitaDebugLog("invalidateRect called with hWnd %8".utf16(), hWnd as! UInt64)
12401322 tofitaDebugLog("> lprc %8 bErase %u".utf16(), lprc as! UInt64, bErase as! UInt64)
1323+
1324+ // TODO Hexa: BTW .True may defined as `1 or _` on the `enum` instead of hack described somewehre in the comments
1325+ // ^ so then it will *require* to do `case True:` and *disallow* `== True` or `!= True` due to ambiguity
1326+ // ^ also another option is simple `case _` and have only `False` but this disallow to have `var value = Bool32.True`
1327+ if bErase != Bool32.False {
1328+ postMessage(hWnd, Message.WM_ERASE_BACKGROUND, null, null)
1329+ }
1330+
1331+ // NOTE paint goes after erase bg
1332+ // TODO coalesce multiple `WM_PAINT` requests in the single queue
1333+ postMessage(hWnd, Message.WM_PAINT, null, null)
1334+
1335+ // TODO better call `redrawWindow` instead of direct message passing
12411336 return Bool32.True
12421337}
12431338
@@ -1403,16 +1498,18 @@ fun moveWindow(hwnd HWnd, x Int32, y Int32, width Int32, height Int32, repaint B
14031498 window.y = y
14041499 window.width = width
14051500 window.height = height
1406-
1407- // NOTE check `windowId != 0`
1408- // let payload = ShowWindowPayload()
1409- // payload.windowId = window.windowId
1410- // payload.nCmdShow = CmdShow.SW_UNCHANGED
1411- // payload.x = x
1412- // payload.y = y
1413- // payload.width = width
1414- // payload.height = height
1415- // tofitaShowWindow(payload)
1501+ tofitaDebugLog("> triggering WM_SIZE".utf16())
1502+
1503+ // 1 x 0
1504+ // TODO check `windowId != 0` i.e. overlapped and non-desktop?
1505+ let payload = ShowWindowPayload()
1506+ payload.windowId = window.windowId
1507+ payload.nCmdShow = CmdShow.SW_UNCHANGED
1508+ payload.x = -1 // TODO window.x
1509+ payload.y = -1 // TODO window.y
1510+ payload.width = window.width
1511+ payload.height = window.height
1512+ tofitaShowWindow(payload)
14161513
14171514 let lParam = LParam.makeULong(window.width as! UInt16, window.height as! UInt16) as! LParam
14181515 sendMessageW(hwnd, Message.WM_SIZE, null, lParam)
0 commit comments