Skip to content

Commit d838549

Browse files
committed
[U32] Update window sizing & position logic
1 parent cc2e485 commit d838549

File tree

1 file changed

+114
-17
lines changed

1 file changed

+114
-17
lines changed

dlls/user32/user32.hexa

Lines changed: 114 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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')
599662
fun 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

Comments
 (0)