@@ -296,109 +296,114 @@ int sys_video_c::Apply(sys_vidSet_s* set)
296296 }
297297 priMon = 0 ;
298298
299+ struct WindowRect {
300+ int left, top;
301+ int right, bottom;
302+ };
303+
299304 // Determine which monitor to create window on
300- if (cur.display >= numMon) {
301- sys->con ->Warning (" display #%d doesn't exist (max display number is %d)" , cur.display , numMon - 1 );
302- cur.display = 0 ;
303- }
304- else if (cur.display < 0 ) {
305- // Use monitor containing the mouse cursor if available, otherwise primary monitor
306- cur.display = 0 ;
307- if (auto curPos = PlatformGetCursorPos ()) {
308- auto [curX, curY] = *curPos;
309- for (int m = 0 ; m < numMon; ++m) {
310- int right = mon[m].left + mon[m].width ;
311- int bottom = mon[m].top + mon[m].height ;
312- if (curX >= mon[m].left && curY >= mon[m].top && curX < right && curY < bottom) {
313- cur.display = m;
314- break ;
315- }
305+ // Use monitor containing the mouse cursor if available, otherwise primary monitor
306+ int display = 0 ;
307+ if (auto curPos = PlatformGetCursorPos ()) {
308+ auto [curX, curY] = *curPos;
309+ for (int m = 0 ; m < numMon; ++m) {
310+ int right = mon[m].left + mon[m].width ;
311+ int bottom = mon[m].top + mon[m].height ;
312+ if (curX >= mon[m].left && curY >= mon[m].top && curX < right && curY < bottom) {
313+ display = m;
314+ break ;
316315 }
317316 }
318317 }
319- defRes[0 ] = mon[cur. display ].width ;
320- defRes[1 ] = mon[cur. display ].height ;
318+ defRes[0 ] = mon[display].width ;
319+ defRes[1 ] = mon[display].height ;
321320
322321 minSize[0 ] = minSize[1 ] = 0 ;
323322
324- if (sys->debuggerRunning ) {
325- // Force topmost off if debugger is attached
326- cur.flags &= ~VID_TOPMOST ;
327- }
328323 if (cur.mode [0 ] == 0 ) {
329324 // Use default resolution if one isn't specified
330325 Vector2Copy (defRes, cur.mode );
331326 }
332327 Vector2Copy (cur.mode , vid.size );
333328 Vector2Copy (defRes, scrSize);
334329
335- struct WindowRect {
336- int left, top;
337- int right, bottom;
338- };
339-
340330 // Get window rectangle
341- WindowRect wrec;
331+ WindowRect wrec{};
332+ std::optional<int > intersectedMonitor;
342333 if (cur.flags & VID_USESAVED ) {
343- // TODO(LV): Move offscreen windows to a monitor.
344- wrec.left = cur.save .pos [0 ];
345- wrec.top = cur.save .pos [1 ];
346334 if (cur.save .maximised ) {
347335 cur.flags |= VID_MAXIMIZE ;
348336 }
349337 else {
350338 cur.mode [0 ] = cur.save .size [0 ];
351339 cur.mode [1 ] = cur.save .size [1 ];
352340 }
341+
342+ wrec.left = cur.save .pos [0 ];
343+ wrec.top = cur.save .pos [1 ];
344+ wrec.right = wrec.left + cur.mode [0 ];
345+ wrec.bottom = wrec.top + cur.mode [1 ];
346+
347+ for (int m = 0 ; m < numMon; ++m) {
348+ WindowRect drec{ mon[m].left , mon[m].top };
349+ drec.right = drec.left + mon[m].width ;
350+ drec.bottom = drec.top + mon[m].height ;
351+
352+ // A.lo < B.hi && A.hi > B.lo (half-open rects)
353+ bool intersectsDisplay = drec.left < wrec.right && drec.top < wrec.bottom && drec.right > wrec.left && drec.bottom > wrec.top ;
354+ if (!intersectedMonitor && intersectsDisplay) {
355+ intersectedMonitor = m;
356+ break ;
357+ }
358+ }
353359 }
354- else {
355- wrec.left = (scrSize[0 ] - cur.mode [0 ]) / 2 + mon[cur.display ].left ;
356- wrec.top = (scrSize[1 ] - cur.mode [1 ]) / 2 + mon[cur.display ].top ;
360+
361+ if (!intersectedMonitor) {
362+ wrec.left = (scrSize[0 ] - cur.mode [0 ]) / 2 + mon[display].left ;
363+ wrec.top = (scrSize[1 ] - cur.mode [1 ]) / 2 + mon[display].top ;
357364 }
358365 vid.pos [0 ] = wrec.left ;
359366 vid.pos [1 ] = wrec.top ;
360- wrec.right = wrec.left + cur.mode [0 ];
361- wrec.bottom = wrec.top + cur.mode [1 ];
362- // TODO(LV): Verify that stored coordinates are aligned right.
363367
364368 if (initialised) {
365- glfwSetWindowSize (wnd, cur.mode [0 ], cur.mode [1 ]);
369+ if (!!glfwGetWindowAttrib (wnd, GLFW_MAXIMIZED )) {
370+ glfwRestoreWindow (wnd);
371+ }
372+ glfwSetWindowPos (wnd, wrec.left , wrec.top );
373+ glfwSetWindowSize (wnd, wrec.right - wrec.left , wrec.bottom - wrec.top );
374+ if (cur.flags & VID_MAXIMIZE ) {
375+ glfwMaximizeWindow (wnd);
376+ }
366377 if (cur.shown ) {
367378 glfwShowWindow (wnd);
368379 sys->conWin ->SetForeground ();
369380 }
381+ else {
382+ glfwHideWindow (wnd);
383+ }
370384 }
371385 else {
372386 glfwWindowHint (GLFW_RESIZABLE , !!(cur.flags & VID_RESIZABLE ));
373- glfwWindowHint (GLFW_VISIBLE , GLFW_TRUE );
374- glfwWindowHint (GLFW_FLOATING , !!(cur.flags & VID_TOPMOST ));
375- glfwWindowHint (GLFW_MAXIMIZED , !!(cur.flags & VID_MAXIMIZE ));
387+ glfwWindowHint (GLFW_VISIBLE , GLFW_FALSE ); // Start hidden to not flash the user with a stock window.
388+ glfwWindowHint (GLFW_MAXIMIZED , GLFW_FALSE ); // Start restored in order to position the window before maximizing.
376389 glfwWindowHint (GLFW_CLIENT_API , GLFW_OPENGL_ES_API );
377390 glfwWindowHint (GLFW_CONTEXT_CREATION_API , GLFW_EGL_CONTEXT_API );
378391 glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR , 2 );
379392 glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR , 0 );
380393 glfwWindowHint (GLFW_DEPTH_BITS , 24 );
381394 // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
395+
382396 wnd = glfwCreateWindow (cur.mode [0 ], cur.mode [1 ], curTitle, nullptr , nullptr );
383397 if (!wnd) {
384398 char const * errDesc = " Unknown error" ;
385399 glfwGetError (&errDesc);
386400 sys->con ->Printf (" Could not create window, %s\n " , errDesc);
387401 }
388402
389- {
390- sys_programIcons_c icons;
391- if (icons.Size () > 0 ) {
392- glfwSetWindowIcon (wnd, (int )icons.Size (), icons.Data ());
393- }
394- }
395403 glfwMakeContextCurrent (wnd);
396404 gladLoadGLES2 (glfwGetProcAddress);
397405
398- glClearColor (0 .0f , 0 .0f , 0 .0f , 1 .0f );
399- glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
400- glfwSwapBuffers (wnd);
401-
406+ // Set up all our window callbacks
402407 glfwSetWindowUserPointer (wnd, sys);
403408 glfwSetCursorEnterCallback (wnd, [](GLFWwindow* wnd, int entered) {
404409 auto sys = (sys_main_c*)glfwGetWindowUserPointer (wnd);
@@ -544,11 +549,27 @@ int sys_video_c::Apply(sys_vidSet_s* set)
544549 auto sys = (sys_main_c*)glfwGetWindowUserPointer (wnd);
545550 sys->video ->vid .dpiScale = xScale;
546551 });
547- }
548552
549- glfwSetWindowSizeLimits (wnd, cur.minSize [0 ], cur.minSize [1 ], GLFW_DONT_CARE , GLFW_DONT_CARE );
553+ // Adjust window look and position
554+ {
555+ sys_programIcons_c icons;
556+ if (icons.Size () > 0 ) {
557+ glfwSetWindowIcon (wnd, (int )icons.Size (), icons.Data ());
558+ }
559+ }
560+ glfwSetWindowSizeLimits (wnd, cur.minSize [0 ], cur.minSize [1 ], GLFW_DONT_CARE , GLFW_DONT_CARE );
561+ glfwSetWindowPos (wnd, vid.pos [0 ], vid.pos [1 ]);
562+ if (!!(cur.flags & VID_MAXIMIZE )) {
563+ glfwMaximizeWindow (wnd);
564+ }
565+ glfwShowWindow (wnd);
566+
567+ // Clear early to avoid flash
568+ glClearColor (0 .0f , 0 .0f , 0 .0f , 1 .0f );
569+ glClear (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
570+ glfwSwapBuffers (wnd);
571+ }
550572
551- glfwSetWindowPos (wnd, vid.pos [0 ], vid.pos [1 ]);
552573 glfwGetFramebufferSize (wnd, &vid.fbSize [0 ], &vid.fbSize [1 ]);
553574 glfwGetWindowSize (wnd, &vid.size [0 ], &vid.size [1 ]);
554575 glfwGetWindowContentScale (wnd, &sys->video ->vid .dpiScale , nullptr );
0 commit comments