summaryrefslogtreecommitdiff
path: root/src/ui/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/window.c')
-rw-r--r--src/ui/window.c557
1 files changed, 295 insertions, 262 deletions
diff --git a/src/ui/window.c b/src/ui/window.c
index b8198636..92125d81 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -67,7 +67,7 @@ static float initialUiScale_ = 1.1f;
67 67
68static iBool isOpenGLRenderer_; 68static iBool isOpenGLRenderer_;
69 69
70iDefineTypeConstructionArgs(Window, (iRect rect), rect) 70iDefineTypeConstructionArgs(MainWindow, (iRect rect), rect)
71 71
72/* TODO: Define menus per platform. */ 72/* TODO: Define menus per platform. */
73 73
@@ -169,17 +169,17 @@ int numRoots_Window(const iWindow *d) {
169 return num; 169 return num;
170} 170}
171 171
172static void windowSizeChanged_Window_(iWindow *d) { 172static void windowSizeChanged_MainWindow_(iMainWindow *d) {
173 const int numRoots = numRoots_Window(d); 173 const int numRoots = numRoots_Window(as_Window(d));
174 const iInt2 rootSize = d->size; 174 const iInt2 rootSize = d->base.size;
175 const int weights[2] = { 175 const int weights[2] = {
176 d->roots[0] ? (d->splitMode & twoToOne_WindowSplit ? 2 : 1) : 0, 176 d->base.roots[0] ? (d->splitMode & twoToOne_WindowSplit ? 2 : 1) : 0,
177 d->roots[1] ? (d->splitMode & oneToTwo_WindowSplit ? 2 : 1) : 0, 177 d->base.roots[1] ? (d->splitMode & oneToTwo_WindowSplit ? 2 : 1) : 0,
178 }; 178 };
179 const int totalWeight = weights[0] + weights[1]; 179 const int totalWeight = weights[0] + weights[1];
180 int w = 0; 180 int w = 0;
181 iForIndices(i, d->roots) { 181 iForIndices(i, d->base.roots) {
182 iRoot *root = d->roots[i]; 182 iRoot *root = d->base.roots[i];
183 if (root) { 183 if (root) {
184 iRect *rect = &root->widget->rect; 184 iRect *rect = &root->widget->rect;
185 /* Horizontal split frame. */ 185 /* Horizontal split frame. */
@@ -199,26 +199,26 @@ static void windowSizeChanged_Window_(iWindow *d) {
199 } 199 }
200} 200}
201 201
202static void setupUserInterface_Window(iWindow *d) { 202static void setupUserInterface_MainWindow(iMainWindow *d) {
203#if defined (iHaveNativeMenus) 203#if defined (iHaveNativeMenus)
204 insertMacMenus_(); 204 insertMacMenus_();
205#endif 205#endif
206 /* One root is created by default. */ 206 /* One root is created by default. */
207 d->roots[0] = new_Root(); 207 d->base.roots[0] = new_Root();
208 setCurrent_Root(d->roots[0]); 208 setCurrent_Root(d->base.roots[0]);
209 createUserInterface_Root(d->roots[0]); 209 createUserInterface_Root(d->base.roots[0]);
210 setCurrent_Root(NULL); 210 setCurrent_Root(NULL);
211 /* One of the roots always has keyboard input focus. */ 211 /* One of the roots always has keyboard input focus. */
212 d->keyRoot = d->roots[0]; 212 d->base.keyRoot = d->base.roots[0];
213} 213}
214 214
215static void updateSize_Window_(iWindow *d, iBool notifyAlways) { 215static void updateSize_MainWindow_(iMainWindow *d, iBool notifyAlways) {
216 iInt2 *size = &d->size; 216 iInt2 *size = &d->base.size;
217 const iInt2 oldSize = *size; 217 const iInt2 oldSize = *size;
218 SDL_GetRendererOutputSize(d->render, &size->x, &size->y); 218 SDL_GetRendererOutputSize(d->base.render, &size->x, &size->y);
219 size->y -= d->keyboardHeight; 219 size->y -= d->keyboardHeight;
220 if (notifyAlways || !isEqual_I2(oldSize, *size)) { 220 if (notifyAlways || !isEqual_I2(oldSize, *size)) {
221 windowSizeChanged_Window_(d); 221 windowSizeChanged_MainWindow_(d);
222 if (!isEqual_I2(*size, d->place.lastNotifiedSize)) { 222 if (!isEqual_I2(*size, d->place.lastNotifiedSize)) {
223 const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); 223 const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x);
224 const iBool isVert = (d->place.lastNotifiedSize.y != size->y); 224 const iBool isVert = (d->place.lastNotifiedSize.y != size->y);
@@ -234,8 +234,8 @@ static void updateSize_Window_(iWindow *d, iBool notifyAlways) {
234 } 234 }
235} 235}
236 236
237void drawWhileResizing_Window(iWindow *d, int w, int h) { 237void drawWhileResizing_MainWindow(iMainWindow *d, int w, int h) {
238 draw_Window(d); 238 draw_MainWindow(d);
239} 239}
240 240
241static float pixelRatio_Window_(const iWindow *d) { 241static float pixelRatio_Window_(const iWindow *d) {
@@ -308,7 +308,7 @@ static iRoot *rootAt_Window_(const iWindow *d, iInt2 coord) {
308} 308}
309 309
310#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 310#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)
311static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos, void *data) { 311static SDL_HitTestResult hitTest_MainWindow_(SDL_Window *win, const SDL_Point *pos, void *data) {
312 iWindow *d = data; 312 iWindow *d = data;
313 iAssert(d->win == win); 313 iAssert(d->win == win);
314 if (SDL_GetWindowFlags(d->win) & (SDL_WINDOW_MOUSE_CAPTURE | SDL_WINDOW_FULLSCREEN_DESKTOP)) { 314 if (SDL_GetWindowFlags(d->win) & (SDL_WINDOW_MOUSE_CAPTURE | SDL_WINDOW_FULLSCREEN_DESKTOP)) {
@@ -361,19 +361,22 @@ SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos) {
361#endif 361#endif
362 362
363iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) { 363iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) {
364 flags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN; 364 flags |= SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN;
365 if (d->type == main_WindowType) {
366 flags |= SDL_WINDOW_RESIZABLE;
365#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 367#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)
366 if (prefs_App()->customFrame) { 368 if (prefs_App()->customFrame) {
367 /* We are drawing a custom frame so hide the default one. */ 369 /* We are drawing a custom frame so hide the default one. */
368 flags |= SDL_WINDOW_BORDERLESS; 370 flags |= SDL_WINDOW_BORDERLESS;
369 } 371 }
370#endif 372#endif
373 }
371 if (SDL_CreateWindowAndRenderer( 374 if (SDL_CreateWindowAndRenderer(
372 width_Rect(rect), height_Rect(rect), flags, &d->win, &d->render)) { 375 width_Rect(rect), height_Rect(rect), flags, &d->win, &d->render)) {
373 return iFalse; 376 return iFalse;
374 } 377 }
375#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 378#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)
376 if (prefs_App()->customFrame) { 379 if (type_Window(d) == main_WindowType && prefs_App()->customFrame) {
377 /* Register a handler for window hit testing (drag, resize). */ 380 /* Register a handler for window hit testing (drag, resize). */
378 SDL_SetWindowHitTest(d->win, hitTest_Window_, d); 381 SDL_SetWindowHitTest(d->win, hitTest_Window_, d);
379 SDL_SetWindowResizable(d->win, SDL_TRUE); 382 SDL_SetWindowResizable(d->win, SDL_TRUE);
@@ -397,40 +400,28 @@ static SDL_Surface *loadImage_(const iBlock *data, int resized) {
397 pixels, w, h, 8 * num, w * num, SDL_PIXELFORMAT_RGBA32); 400 pixels, w, h, 8 * num, w * num, SDL_PIXELFORMAT_RGBA32);
398} 401}
399 402
400void init_Window(iWindow *d, iRect rect) { 403void init_Window(iWindow *d, enum iWindowType type, iRect rect, uint32_t flags) {
401 theWindow_ = d; 404 d->type = type;
402 d->win = NULL; 405 d->win = NULL;
403 d->size = zero_I2(); /* will be updated below */ 406 d->size = zero_I2(); /* will be updated below */
404 iZap(d->roots); 407 d->hover = NULL;
405 d->splitMode = d->pendingSplitMode = 0; 408 d->lastHover = NULL;
406 d->pendingSplitUrl = new_String(); 409 d->mouseGrab = NULL;
407 d->hover = NULL; 410 d->focus = NULL;
408 d->lastHover = NULL;
409 d->mouseGrab = NULL;
410 d->focus = NULL;
411 iZap(d->cursors);
412 d->place.initialPos = rect.pos;
413 d->place.normalRect = rect;
414 d->place.lastNotifiedSize = zero_I2();
415 d->place.snap = 0;
416 d->pendingCursor = NULL; 411 d->pendingCursor = NULL;
417 d->isDrawFrozen = iTrue; 412 d->isDrawFrozen = iTrue;
418 d->isExposed = iFalse; 413 d->isExposed = iFalse;
419 d->isMinimized = iFalse; 414 d->isMinimized = iFalse;
420 d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */ 415 d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */
421 d->isMouseInside = iTrue; 416 d->isMouseInside = iTrue;
422 d->ignoreClick = iFalse; 417 d->ignoreClick = iFalse;
423 d->focusGainedAt = 0; 418 d->focusGainedAt = 0;
424 d->keyboardHeight = 0; 419 d->presentTime = 0.0;
425 uint32_t flags = 0; 420 d->frameTime = SDL_GetTicks();
426#if defined (iPlatformAppleDesktop) 421 d->keyRoot = NULL;
427 SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl"); 422 d->borderShadow = NULL;
428#elif defined (iPlatformAppleMobile) 423 iZap(d->roots);
429 SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal"); 424 iZap(d->cursors);
430#else
431 flags |= SDL_WINDOW_OPENGL;
432#endif
433 SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");
434 /* First try SDL's default renderer that should be the best option. */ 425 /* First try SDL's default renderer that should be the best option. */
435 if (forceSoftwareRender_App() || !create_Window_(d, rect, flags)) { 426 if (forceSoftwareRender_App() || !create_Window_(d, rect, flags)) {
436 /* No luck, maybe software only? This should always work as long as there is a display. */ 427 /* No luck, maybe software only? This should always work as long as there is a display. */
@@ -443,40 +434,74 @@ void init_Window(iWindow *d, iRect rect) {
443 if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) { 434 if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) {
444 SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect)); 435 SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect));
445 } 436 }
446#if defined (iPlatformMobile) 437 SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y);
438 drawBlank_Window_(d);
439 d->pixelRatio = pixelRatio_Window_(d); /* point/pixel conversion */
440 d->displayScale = displayScale_Window_(d);
441 d->uiScale = initialUiScale_;
442 /* TODO: Ratios, scales, and metrics must be window-specific, not global. */
443 setScale_Metrics(d->pixelRatio * d->displayScale * d->uiScale);
444}
445
446void deinit_Window(iWindow *d) {
447 SDL_DestroyRenderer(d->render);
448 SDL_DestroyWindow(d->win);
449 iForIndices(i, d->cursors) {
450 if (d->cursors[i]) {
451 SDL_FreeCursor(d->cursors[i]);
452 }
453 }
454}
455
456void init_MainWindow(iMainWindow *d, iRect rect) {
457 theWindow_ = &d->base;
458 uint32_t flags = 0;
459#if defined (iPlatformAppleDesktop)
460 SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl");
461#elif defined (iPlatformAppleMobile)
462 SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");
463#else
464 flags |= SDL_WINDOW_OPENGL;
465#endif
466 SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");
467 init_Window(&d->base, main_WindowType, rect, flags);
468 d->splitMode = d->pendingSplitMode = 0;
469 d->pendingSplitUrl = new_String();
470 d->place.initialPos = rect.pos;
471 d->place.normalRect = rect;
472 d->place.lastNotifiedSize = zero_I2();
473 d->place.snap = 0;
474 d->keyboardHeight = 0;
475#if defined(iPlatformMobile)
447 const iInt2 minSize = zero_I2(); /* windows aren't independently resizable */ 476 const iInt2 minSize = zero_I2(); /* windows aren't independently resizable */
448#else 477#else
449 const iInt2 minSize = init_I2(425, 325); 478 const iInt2 minSize = init_I2(425, 325);
450#endif 479#endif
451 SDL_SetWindowMinimumSize(d->win, minSize.x, minSize.y); 480 SDL_SetWindowMinimumSize(d->base.win, minSize.x, minSize.y);
452 SDL_SetWindowTitle(d->win, "Lagrange"); 481 SDL_SetWindowTitle(d->base.win, "Lagrange");
453 /* Some info. */ { 482 /* Some info. */ {
454 SDL_RendererInfo info; 483 SDL_RendererInfo info;
455 SDL_GetRendererInfo(d->render, &info); 484 SDL_GetRendererInfo(d->base.render, &info);
456 isOpenGLRenderer_ = !iCmpStr(info.name, "opengl"); 485 isOpenGLRenderer_ = !iCmpStr(info.name, "opengl");
457 printf("[window] renderer: %s%s\n", info.name, 486 printf("[window] renderer: %s%s\n",
487 info.name,
458 info.flags & SDL_RENDERER_ACCELERATED ? " (accelerated)" : ""); 488 info.flags & SDL_RENDERER_ACCELERATED ? " (accelerated)" : "");
459#if !defined (NDEBUG) 489#if !defined(NDEBUG)
460 printf("[window] max texture size: %d x %d\n", 490 printf("[window] max texture size: %d x %d\n",
461 info.max_texture_width, 491 info.max_texture_width,
462 info.max_texture_height); 492 info.max_texture_height);
463 for (size_t i = 0; i < info.num_texture_formats; ++i) { 493 for (size_t i = 0; i < info.num_texture_formats; ++i) {
464 printf("[window] supported texture format: %s\n", SDL_GetPixelFormatName( 494 printf("[window] supported texture format: %s\n",
465 info.texture_formats[i])); 495 SDL_GetPixelFormatName(info.texture_formats[i]));
466 } 496 }
467#endif 497#endif
468 } 498 }
469 drawBlank_Window_(d); 499#if defined(iPlatformMsys)
470 d->pixelRatio = pixelRatio_Window_(d); /* point/pixel conversion */ 500 SDL_SetWindowMinimumSize(d->win, minSize.x * d->base.displayScale, minSize.y * d->base.displayScale);
471 d->displayScale = displayScale_Window_(d); 501 useExecutableIconResource_SDLWindow(d->base.win);
472 d->uiScale = initialUiScale_;
473 setScale_Metrics(d->pixelRatio * d->displayScale * d->uiScale);
474#if defined (iPlatformMsys)
475 SDL_SetWindowMinimumSize(d->win, minSize.x * d->displayScale, minSize.y * d->displayScale);
476 useExecutableIconResource_SDLWindow(d->win);
477#endif 502#endif
478#if defined (iPlatformLinux) 503#if defined (iPlatformLinux)
479 SDL_SetWindowMinimumSize(d->win, minSize.x * d->pixelRatio, minSize.y * d->pixelRatio); 504 SDL_SetWindowMinimumSize(d->win, minSize.x * d->base.pixelRatio, minSize.y * d->base.pixelRatio);
480 /* Load the window icon. */ { 505 /* Load the window icon. */ {
481 SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, 0); 506 SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, 0);
482 SDL_SetWindowIcon(d->win, surf); 507 SDL_SetWindowIcon(d->win, surf);
@@ -487,18 +512,14 @@ void init_Window(iWindow *d, iRect rect) {
487#if defined (iPlatformAppleMobile) 512#if defined (iPlatformAppleMobile)
488 setupWindow_iOS(d); 513 setupWindow_iOS(d);
489#endif 514#endif
490 d->presentTime = 0.0; 515 init_Text(d->base.render);
491 d->frameTime = SDL_GetTicks(); 516 SDL_GetRendererOutputSize(d->base.render, &d->base.size.x, &d->base.size.y);
492 d->loadAnimTimer = 0; 517 setupUserInterface_MainWindow(d);
493 init_Text(d->render);
494 SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y);
495 setupUserInterface_Window(d);
496 postCommand_App("~bindings.changed"); /* update from bindings */ 518 postCommand_App("~bindings.changed"); /* update from bindings */
497 //updateSize_Window_(d, iFalse);
498 /* Load the border shadow texture. */ { 519 /* Load the border shadow texture. */ {
499 SDL_Surface *surf = loadImage_(&imageShadow_Embedded, 0); 520 SDL_Surface *surf = loadImage_(&imageShadow_Embedded, 0);
500 d->borderShadow = SDL_CreateTextureFromSurface(d->render, surf); 521 d->base.borderShadow = SDL_CreateTextureFromSurface(d->base.render, surf);
501 SDL_SetTextureBlendMode(d->borderShadow, SDL_BLENDMODE_BLEND); 522 SDL_SetTextureBlendMode(d->base.borderShadow, SDL_BLENDMODE_BLEND);
502 free(surf->pixels); 523 free(surf->pixels);
503 SDL_FreeSurface(surf); 524 SDL_FreeSurface(surf);
504 } 525 }
@@ -508,7 +529,7 @@ void init_Window(iWindow *d, iRect rect) {
508 if (prefs_App()->customFrame) { 529 if (prefs_App()->customFrame) {
509 SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, appIconSize_Root()); 530 SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, appIconSize_Root());
510 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); 531 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
511 d->appIcon = SDL_CreateTextureFromSurface(d->render, surf); 532 d->appIcon = SDL_CreateTextureFromSurface(d->base.render, surf);
512 free(surf->pixels); 533 free(surf->pixels);
513 SDL_FreeSurface(surf); 534 SDL_FreeSurface(surf);
514 /* We need to observe non-client-area events. */ 535 /* We need to observe non-client-area events. */
@@ -517,7 +538,7 @@ void init_Window(iWindow *d, iRect rect) {
517#endif 538#endif
518} 539}
519 540
520void deinit_Window(iWindow *d) { 541static void deinitRoots_Window_(iWindow *d) {
521 iRecycle(); 542 iRecycle();
522 iForIndices(i, d->roots) { 543 iForIndices(i, d->roots) {
523 if (d->roots[i]) { 544 if (d->roots[i]) {
@@ -525,19 +546,17 @@ void deinit_Window(iWindow *d) {
525 deinit_Root(d->roots[i]); 546 deinit_Root(d->roots[i]);
526 } 547 }
527 } 548 }
528 if (theWindow_ == d) { 549 setCurrent_Root(NULL);
550}
551
552void deinit_MainWindow(iMainWindow *d) {
553 deinitRoots_Window_(as_Window(d));
554 if (theWindow_ == as_Window(d)) {
529 theWindow_ = NULL; 555 theWindow_ = NULL;
530 } 556 }
531 setCurrent_Root(NULL);
532 delete_String(d->pendingSplitUrl); 557 delete_String(d->pendingSplitUrl);
533 deinit_Text(); 558 deinit_Text();
534 SDL_DestroyRenderer(d->render); 559 deinit_Window(&d->base);
535 SDL_DestroyWindow(d->win);
536 iForIndices(i, d->cursors) {
537 if (d->cursors[i]) {
538 SDL_FreeCursor(d->cursors[i]);
539 }
540 }
541} 560}
542 561
543SDL_Renderer *renderer_Window(const iWindow *d) { 562SDL_Renderer *renderer_Window(const iWindow *d) {
@@ -550,8 +569,8 @@ iInt2 maxTextureSize_Window(const iWindow *d) {
550 return init_I2(info.max_texture_width, info.max_texture_height); 569 return init_I2(info.max_texture_width, info.max_texture_height);
551} 570}
552 571
553iBool isFullscreen_Window(const iWindow *d) { 572iBool isFullscreen_MainWindow(const iMainWindow *d) {
554 return snap_Window(d) == fullscreen_WindowSnap; 573 return snap_MainWindow(d) == fullscreen_WindowSnap;
555} 574}
556 575
557iRoot *findRoot_Window(const iWindow *d, const iWidget *widget) { 576iRoot *findRoot_Window(const iWindow *d, const iWidget *widget) {
@@ -570,36 +589,41 @@ iRoot *otherRoot_Window(const iWindow *d, iRoot *root) {
570 return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0]; 589 return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0];
571} 590}
572 591
573static void invalidate_Window_(iWindow *d, iBool forced) { 592static void invalidate_MainWindow_(iMainWindow *d, iBool forced) {
574 if (d && (!d->isInvalidated || forced)) { 593 if (d && (!d->base.isInvalidated || forced)) {
575 d->isInvalidated = iTrue; 594 d->base.isInvalidated = iTrue;
576 resetFonts_Text(); 595 resetFonts_Text();
577 postCommand_App("theme.changed auto:1"); /* forces UI invalidation */ 596 postCommand_App("theme.changed auto:1"); /* forces UI invalidation */
578 } 597 }
579} 598}
580 599
581void invalidate_Window(iWindow *d) { 600void invalidate_Window(iAnyWindow *d) {
582 invalidate_Window_(d, iFalse); 601 if (type_Window(d) == main_WindowType) {
602 invalidate_MainWindow_(as_MainWindow(d), iFalse);
603 }
604 else {
605 iAssert(type_Window(d) == main_WindowType);
606 }
583} 607}
584 608
585static iBool isNormalPlacement_Window_(const iWindow *d) { 609static iBool isNormalPlacement_MainWindow_(const iMainWindow *d) {
586 if (d->isDrawFrozen) return iFalse; 610 if (d->base.isDrawFrozen) return iFalse;
587#if defined (iPlatformApple) 611#if defined (iPlatformApple)
588 /* Maximized mode is not special on macOS. */ 612 /* Maximized mode is not special on macOS. */
589 if (snap_Window(d) == maximized_WindowSnap) { 613 if (snap_MainWindow(d) == maximized_WindowSnap) {
590 return iTrue; 614 return iTrue;
591 } 615 }
592#endif 616#endif
593 if (snap_Window(d)) return iFalse; 617 if (snap_MainWindow(d)) return iFalse;
594 return !(SDL_GetWindowFlags(d->win) & SDL_WINDOW_MINIMIZED); 618 return !(SDL_GetWindowFlags(d->base.win) & SDL_WINDOW_MINIMIZED);
595} 619}
596 620
597static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) { 621static iBool unsnap_MainWindow_(iMainWindow *d, const iInt2 *newPos) {
598#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 622#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)
599 if (!prefs_App()->customFrame) { 623 if (!prefs_App()->customFrame) {
600 return iFalse; 624 return iFalse;
601 } 625 }
602 const int snap = snap_Window(d); 626 const int snap = snap_MainWindow(d);
603 if (snap == yMaximized_WindowSnap || snap == left_WindowSnap || snap == right_WindowSnap) { 627 if (snap == yMaximized_WindowSnap || snap == left_WindowSnap || snap == right_WindowSnap) {
604 if (!newPos || (d->place.lastHit == SDL_HITTEST_RESIZE_LEFT || 628 if (!newPos || (d->place.lastHit == SDL_HITTEST_RESIZE_LEFT ||
605 d->place.lastHit == SDL_HITTEST_RESIZE_RIGHT)) { 629 d->place.lastHit == SDL_HITTEST_RESIZE_RIGHT)) {
@@ -607,21 +631,21 @@ static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) {
607 } 631 }
608 if (newPos) { 632 if (newPos) {
609 SDL_Rect usable; 633 SDL_Rect usable;
610 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable); 634 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable);
611 /* Snap to top. */ 635 /* Snap to top. */
612 if (snap == yMaximized_WindowSnap && 636 if (snap == yMaximized_WindowSnap &&
613 iAbs(newPos->y - usable.y) < lineHeight_Text(uiContent_FontId) * 2) { 637 iAbs(newPos->y - usable.y) < lineHeight_Text(uiContent_FontId) * 2) {
614 setSnap_Window(d, redo_WindowSnap | yMaximized_WindowSnap); 638 setSnap_MainWindow(d, redo_WindowSnap | yMaximized_WindowSnap);
615 return iFalse; 639 return iFalse;
616 } 640 }
617 } 641 }
618 } 642 }
619 if (snap && snap != fullscreen_WindowSnap) { 643 if (snap && snap != fullscreen_WindowSnap) {
620 if (snap_Window(d) == yMaximized_WindowSnap && newPos) { 644 if (snap_MainWindow(d) == yMaximized_WindowSnap && newPos) {
621 d->place.normalRect.pos = *newPos; 645 d->place.normalRect.pos = *newPos;
622 } 646 }
623 //printf("unsnap\n"); fflush(stdout); 647 //printf("unsnap\n"); fflush(stdout);
624 setSnap_Window(d, none_WindowSnap); 648 setSnap_MainWindow(d, none_WindowSnap);
625 return iTrue; 649 return iTrue;
626 } 650 }
627#endif 651#endif
@@ -652,109 +676,110 @@ static void checkPixelRatioChange_Window_(iWindow *d) {
652 } 676 }
653} 677}
654 678
655static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { 679static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent *ev) {
656 switch (ev->event) { 680 switch (ev->event) {
657#if defined (iPlatformDesktop) 681#if defined(iPlatformDesktop)
658 case SDL_WINDOWEVENT_EXPOSED: 682 case SDL_WINDOWEVENT_EXPOSED:
659 if (!d->isExposed) { 683 if (!d->base.isExposed) {
660 drawBlank_Window_(d); /* avoid showing system-provided contents */ 684 drawBlank_Window_(as_Window(d)); /* avoid showing system-provided contents */
661 d->isExposed = iTrue; 685 d->base.isExposed = iTrue;
662 } 686 }
663 /* Since we are manually controlling when to redraw the window, we are responsible 687 /* Since we are manually controlling when to redraw the window, we are responsible
664 for ensuring that window contents get redrawn after expose events. Under certain 688 for ensuring that window contents get redrawn after expose events. Under certain
665 circumstances (e.g., under openbox), not doing this would mean that the window 689 circumstances (e.g., under openbox), not doing this would mean that the window
666 is missing contents until other events trigger a refresh. */ 690 is missing contents until other events trigger a refresh. */
667 postRefresh_App(); 691 postRefresh_App();
668#if defined (LAGRANGE_ENABLE_WINDOWPOS_FIX) 692#if defined(LAGRANGE_ENABLE_WINDOWPOS_FIX)
669 if (d->place.initialPos.x >= 0) { 693 if (d->place.initialPos.x >= 0) {
670 int bx, by; 694 int bx, by;
671 SDL_GetWindowBordersSize(d->win, &by, &bx, NULL, NULL); 695 SDL_GetWindowBordersSize(d->win, &by, &bx, NULL, NULL);
672 SDL_SetWindowPosition(d->win, d->place.initialPos.x + bx, d->place.initialPos.y + by); 696 SDL_SetWindowPosition(
697 d->win, d->place.initialPos.x + bx, d->place.initialPos.y + by);
673 d->place.initialPos = init1_I2(-1); 698 d->place.initialPos = init1_I2(-1);
674 } 699 }
675#endif 700#endif
676 return iFalse; 701 return iFalse;
677 case SDL_WINDOWEVENT_MOVED: { 702 case SDL_WINDOWEVENT_MOVED: {
678 if (d->isMinimized) { 703 if (d->base.isMinimized) {
679 return iFalse; 704 return iFalse;
680 } 705 }
681 checkPixelRatioChange_Window_(d); 706 checkPixelRatioChange_Window_(as_Window(d));
682 const iInt2 newPos = init_I2(ev->data1, ev->data2); 707 const iInt2 newPos = init_I2(ev->data1, ev->data2);
683 if (isEqual_I2(newPos, init1_I2(-32000))) { /* magic! */ 708 if (isEqual_I2(newPos, init1_I2(-32000))) { /* magic! */
684 /* Maybe minimized? Seems like a Windows constant of some kind. */ 709 /* Maybe minimized? Seems like a Windows constant of some kind. */
685 d->isMinimized = iTrue; 710 d->base.isMinimized = iTrue;
686 return iFalse; 711 return iFalse;
687 } 712 }
688#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 713#if defined(LAGRANGE_ENABLE_CUSTOM_FRAME)
689 /* Set the snap position depending on where the mouse cursor is. */ 714 /* Set the snap position depending on where the mouse cursor is. */
690 if (prefs_App()->customFrame) { 715 if (prefs_App()->customFrame) {
691 SDL_Rect usable; 716 SDL_Rect usable;
692 iInt2 mouse = cursor_Win32(); /* SDL is unaware of the current cursor pos */ 717 iInt2 mouse = cursor_Win32(); /* SDL is unaware of the current cursor pos */
693 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable); 718 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable);
694 const iBool isTop = iAbs(mouse.y - usable.y) < gap_UI * 20; 719 const iBool isTop = iAbs(mouse.y - usable.y) < gap_UI * 20;
695 const iBool isBottom = iAbs(usable.y + usable.h - mouse.y) < gap_UI * 20; 720 const iBool isBottom = iAbs(usable.y + usable.h - mouse.y) < gap_UI * 20;
696 if (iAbs(mouse.x - usable.x) < gap_UI) { 721 if (iAbs(mouse.x - usable.x) < gap_UI) {
697 setSnap_Window(d, 722 setSnap_MainWindow(d,
698 redo_WindowSnap | left_WindowSnap | 723 redo_WindowSnap | left_WindowSnap |
699 (isTop ? topBit_WindowSnap : 0) | 724 (isTop ? topBit_WindowSnap : 0) |
700 (isBottom ? bottomBit_WindowSnap : 0)); 725 (isBottom ? bottomBit_WindowSnap : 0));
701 return iTrue; 726 return iTrue;
702 } 727 }
703 if (iAbs(mouse.x - usable.x - usable.w) < gap_UI) { 728 if (iAbs(mouse.x - usable.x - usable.w) < gap_UI) {
704 setSnap_Window(d, 729 setSnap_MainWindow(d,
705 redo_WindowSnap | right_WindowSnap | 730 redo_WindowSnap | right_WindowSnap |
706 (isTop ? topBit_WindowSnap : 0) | 731 (isTop ? topBit_WindowSnap : 0) |
707 (isBottom ? bottomBit_WindowSnap : 0)); 732 (isBottom ? bottomBit_WindowSnap : 0));
708 return iTrue; 733 return iTrue;
709 } 734 }
710 if (iAbs(mouse.y - usable.y) < 2) { 735 if (iAbs(mouse.y - usable.y) < 2) {
711 setSnap_Window(d, 736 setSnap_MainWindow(d,
712 redo_WindowSnap | (d->place.lastHit == SDL_HITTEST_RESIZE_TOP 737 redo_WindowSnap | (d->place.lastHit == SDL_HITTEST_RESIZE_TOP
713 ? yMaximized_WindowSnap 738 ? yMaximized_WindowSnap
714 : maximized_WindowSnap)); 739 : maximized_WindowSnap));
715 return iTrue; 740 return iTrue;
716 } 741 }
717 } 742 }
718#endif /* defined LAGRANGE_ENABLE_CUSTOM_FRAME */ 743#endif /* defined LAGRANGE_ENABLE_CUSTOM_FRAME */
719 if (unsnap_Window_(d, &newPos)) { 744 if (unsnap_MainWindow_(d, &newPos)) {
720 return iTrue; 745 return iTrue;
721 } 746 }
722 if (isNormalPlacement_Window_(d)) { 747 if (isNormalPlacement_MainWindow_(d)) {
723 d->place.normalRect.pos = newPos; 748 d->place.normalRect.pos = newPos;
724 //printf("normal rect set (move)\n"); fflush(stdout); 749 // printf("normal rect set (move)\n"); fflush(stdout);
725 iInt2 border = zero_I2(); 750 iInt2 border = zero_I2();
726#if !defined (iPlatformApple) 751#if !defined(iPlatformApple)
727 SDL_GetWindowBordersSize(d->win, &border.y, &border.x, NULL, NULL); 752 SDL_GetWindowBordersSize(d->win, &border.y, &border.x, NULL, NULL);
728#endif 753#endif
729 d->place.normalRect.pos = max_I2(zero_I2(), sub_I2(d->place.normalRect.pos, border)); 754 d->place.normalRect.pos =
755 max_I2(zero_I2(), sub_I2(d->place.normalRect.pos, border));
730 } 756 }
731 return iTrue; 757 return iTrue;
732 } 758 }
733 case SDL_WINDOWEVENT_RESIZED: 759 case SDL_WINDOWEVENT_RESIZED:
734 if (d->isMinimized) { 760 if (d->base.isMinimized) {
735 //updateSize_Window_(d, iTrue); 761 // updateSize_Window_(d, iTrue);
736 return iTrue; 762 return iTrue;
737 } 763 }
738 if (unsnap_Window_(d, NULL)) { 764 if (unsnap_MainWindow_(d, NULL)) {
739 return iTrue; 765 return iTrue;
740 } 766 }
741 if (isNormalPlacement_Window_(d)) { 767 if (isNormalPlacement_MainWindow_(d)) {
742 d->place.normalRect.size = init_I2(ev->data1, ev->data2); 768 d->place.normalRect.size = init_I2(ev->data1, ev->data2);
743 //printf("normal rect set (resize)\n"); fflush(stdout); 769 // printf("normal rect set (resize)\n"); fflush(stdout);
744 } 770 }
745 checkPixelRatioChange_Window_(d); 771 checkPixelRatioChange_Window_(as_Window(d));
746 //updateSize_Window_(d, iTrue /* we were already redrawing during the resize */);
747 postRefresh_App(); 772 postRefresh_App();
748 return iTrue; 773 return iTrue;
749 case SDL_WINDOWEVENT_RESTORED: 774 case SDL_WINDOWEVENT_RESTORED:
750 case SDL_WINDOWEVENT_SHOWN: 775 case SDL_WINDOWEVENT_SHOWN:
751 updateSize_Window_(d, iTrue); 776 updateSize_MainWindow_(d, iTrue);
752 invalidate_Window_(d, iTrue); 777 invalidate_MainWindow_(d, iTrue);
753 d->isMinimized = iFalse; 778 d->base.isMinimized = iFalse;
754 postRefresh_App(); 779 postRefresh_App();
755 return iTrue; 780 return iTrue;
756 case SDL_WINDOWEVENT_MINIMIZED: 781 case SDL_WINDOWEVENT_MINIMIZED:
757 d->isMinimized = iTrue; 782 d->base.isMinimized = iTrue;
758 return iTrue; 783 return iTrue;
759#else /* if defined (!iPlatformDesktop) */ 784#else /* if defined (!iPlatformDesktop) */
760 case SDL_WINDOWEVENT_RESIZED: 785 case SDL_WINDOWEVENT_RESIZED:
@@ -765,19 +790,19 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) {
765#endif 790#endif
766 case SDL_WINDOWEVENT_LEAVE: 791 case SDL_WINDOWEVENT_LEAVE:
767 unhover_Widget(); 792 unhover_Widget();
768 d->isMouseInside = iFalse; 793 d->base.isMouseInside = iFalse;
769 postCommand_App("window.mouse.exited"); 794 postCommand_App("window.mouse.exited");
770 return iTrue; 795 return iTrue;
771 case SDL_WINDOWEVENT_ENTER: 796 case SDL_WINDOWEVENT_ENTER:
772 d->isMouseInside = iTrue; 797 d->base.isMouseInside = iTrue;
773 postCommand_App("window.mouse.entered"); 798 postCommand_App("window.mouse.entered");
774 return iTrue; 799 return iTrue;
775 case SDL_WINDOWEVENT_FOCUS_GAINED: 800 case SDL_WINDOWEVENT_FOCUS_GAINED:
776 d->focusGainedAt = SDL_GetTicks(); 801 d->base.focusGainedAt = SDL_GetTicks();
777 setCapsLockDown_Keys(iFalse); 802 setCapsLockDown_Keys(iFalse);
778 postCommand_App("window.focus.gained"); 803 postCommand_App("window.focus.gained");
779 d->isExposed = iTrue; 804 d->base.isExposed = iTrue;
780#if !defined (iPlatformDesktop) 805#if !defined(iPlatformDesktop)
781 /* Returned to foreground, may have lost buffered content. */ 806 /* Returned to foreground, may have lost buffered content. */
782 invalidate_Window_(d, iTrue); 807 invalidate_Window_(d, iTrue);
783 postCommand_App("window.unfreeze"); 808 postCommand_App("window.unfreeze");
@@ -785,12 +810,12 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) {
785 return iFalse; 810 return iFalse;
786 case SDL_WINDOWEVENT_FOCUS_LOST: 811 case SDL_WINDOWEVENT_FOCUS_LOST:
787 postCommand_App("window.focus.lost"); 812 postCommand_App("window.focus.lost");
788#if !defined (iPlatformDesktop) 813#if !defined(iPlatformDesktop)
789 setFreezeDraw_Window(d, iTrue); 814 setFreezeDraw_Window(d, iTrue);
790#endif 815#endif
791 return iFalse; 816 return iFalse;
792 case SDL_WINDOWEVENT_TAKE_FOCUS: 817 case SDL_WINDOWEVENT_TAKE_FOCUS:
793 SDL_SetWindowInputFocus(d->win); 818 SDL_SetWindowInputFocus(d->base.win);
794 postRefresh_App(); 819 postRefresh_App();
795 return iTrue; 820 return iTrue;
796 default: 821 default:
@@ -806,7 +831,8 @@ static void applyCursor_Window_(iWindow *d) {
806 } 831 }
807} 832}
808 833
809iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { 834iBool processEvent_MainWindow(iMainWindow *d, const SDL_Event *ev) {
835 iWindow *w = as_Window(d);
810 switch (ev->type) { 836 switch (ev->type) {
811#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 837#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)
812 case SDL_SYSWMEVENT: { 838 case SDL_SYSWMEVENT: {
@@ -819,19 +845,19 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
819 } 845 }
820#endif 846#endif
821 case SDL_WINDOWEVENT: { 847 case SDL_WINDOWEVENT: {
822 return handleWindowEvent_Window_(d, &ev->window); 848 return handleWindowEvent_MainWindow_(d, &ev->window);
823 } 849 }
824 case SDL_RENDER_TARGETS_RESET: 850 case SDL_RENDER_TARGETS_RESET:
825 case SDL_RENDER_DEVICE_RESET: { 851 case SDL_RENDER_DEVICE_RESET: {
826 invalidate_Window_(d, iTrue /* force full reset */); 852 invalidate_MainWindow_(d, iTrue /* force full reset */);
827 break; 853 break;
828 } 854 }
829 default: { 855 default: {
830 SDL_Event event = *ev; 856 SDL_Event event = *ev;
831 if (event.type == SDL_USEREVENT && isCommand_UserEvent(ev, "window.unfreeze")) { 857 if (event.type == SDL_USEREVENT && isCommand_UserEvent(ev, "window.unfreeze")) {
832 d->isDrawFrozen = iFalse; 858 d->base.isDrawFrozen = iFalse;
833 if (SDL_GetWindowFlags(d->win) & SDL_WINDOW_HIDDEN) { 859 if (SDL_GetWindowFlags(w->win) & SDL_WINDOW_HIDDEN) {
834 SDL_ShowWindow(d->win); 860 SDL_ShowWindow(w->win);
835 } 861 }
836 postRefresh_App(); 862 postRefresh_App();
837 postCommand_App("media.player.update"); /* in case a player needs updating */ 863 postCommand_App("media.player.update"); /* in case a player needs updating */
@@ -840,35 +866,35 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
840 if (processEvent_Touch(&event)) { 866 if (processEvent_Touch(&event)) {
841 return iTrue; 867 return iTrue;
842 } 868 }
843 if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->focusGainedAt < 10) { 869 if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->base.focusGainedAt < 10) {
844 /* Suspiciously close to when input focus was received. For example under openbox, 870 /* Suspiciously close to when input focus was received. For example under openbox,
845 closing xterm with Ctrl+D will cause the keydown event to "spill" over to us. 871 closing xterm with Ctrl+D will cause the keydown event to "spill" over to us.
846 As a workaround, ignore these events. */ 872 As a workaround, ignore these events. */
847 return iTrue; /* won't go to bindings, either */ 873 return iTrue; /* won't go to bindings, either */
848 } 874 }
849 if (event.type == SDL_MOUSEBUTTONDOWN && d->ignoreClick) { 875 if (event.type == SDL_MOUSEBUTTONDOWN && d->base.ignoreClick) {
850 d->ignoreClick = iFalse; 876 d->base.ignoreClick = iFalse;
851 return iTrue; 877 return iTrue;
852 } 878 }
853 /* Map mouse pointer coordinate to our coordinate system. */ 879 /* Map mouse pointer coordinate to our coordinate system. */
854 if (event.type == SDL_MOUSEMOTION) { 880 if (event.type == SDL_MOUSEMOTION) {
855 setCursor_Window(d, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */ 881 setCursor_Window(w, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */
856 const iInt2 pos = coord_Window(d, event.motion.x, event.motion.y); 882 const iInt2 pos = coord_Window(w, event.motion.x, event.motion.y);
857 event.motion.x = pos.x; 883 event.motion.x = pos.x;
858 event.motion.y = pos.y; 884 event.motion.y = pos.y;
859 } 885 }
860 else if (event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { 886 else if (event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) {
861 const iInt2 pos = coord_Window(d, event.button.x, event.button.y); 887 const iInt2 pos = coord_Window(w, event.button.x, event.button.y);
862 event.button.x = pos.x; 888 event.button.x = pos.x;
863 event.button.y = pos.y; 889 event.button.y = pos.y;
864 if (event.type == SDL_MOUSEBUTTONDOWN) { 890 if (event.type == SDL_MOUSEBUTTONDOWN) {
865 /* Button clicks will change keyroot. */ 891 /* Button clicks will change keyroot. */
866 if (numRoots_Window(d) > 1) { 892 if (numRoots_Window(w) > 1) {
867 const iInt2 click = init_I2(event.button.x, event.button.y); 893 const iInt2 click = init_I2(event.button.x, event.button.y);
868 iForIndices(i, d->roots) { 894 iForIndices(i, w->roots) {
869 iRoot *root = d->roots[i]; 895 iRoot *root = w->roots[i];
870 if (root != d->keyRoot && contains_Rect(rect_Root(root), click)) { 896 if (root != w->keyRoot && contains_Rect(rect_Root(root), click)) {
871 setKeyRoot_Window(d, root); 897 setKeyRoot_Window(w, root);
872 break; 898 break;
873 } 899 }
874 } 900 }
@@ -883,13 +909,13 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
883 event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { 909 event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) {
884 if (mouseGrab_Widget()) { 910 if (mouseGrab_Widget()) {
885 iWidget *grabbed = mouseGrab_Widget(); 911 iWidget *grabbed = mouseGrab_Widget();
886 setCurrent_Root(findRoot_Window(d, grabbed)); 912 setCurrent_Root(findRoot_Window(w, grabbed));
887 wasUsed = dispatchEvent_Widget(grabbed, &event); 913 wasUsed = dispatchEvent_Widget(grabbed, &event);
888 } 914 }
889 } 915 }
890 /* Dispatch the event to the tree of widgets. */ 916 /* Dispatch the event to the tree of widgets. */
891 if (!wasUsed) { 917 if (!wasUsed) {
892 wasUsed = dispatchEvent_Window(d, &event); 918 wasUsed = dispatchEvent_Window(w, &event);
893 } 919 }
894 if (!wasUsed) { 920 if (!wasUsed) {
895 /* As a special case, clicking the middle mouse button can be used for pasting 921 /* As a special case, clicking the middle mouse button can be used for pasting
@@ -902,17 +928,17 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
902 paste.key.keysym.mod = KMOD_PRIMARY; 928 paste.key.keysym.mod = KMOD_PRIMARY;
903 paste.key.state = SDL_PRESSED; 929 paste.key.state = SDL_PRESSED;
904 paste.key.timestamp = SDL_GetTicks(); 930 paste.key.timestamp = SDL_GetTicks();
905 wasUsed = dispatchEvent_Window(d, &paste); 931 wasUsed = dispatchEvent_Window(w, &paste);
906 } 932 }
907 if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_RIGHT) { 933 if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_RIGHT) {
908 if (postContextClick_Window(d, &event.button)) { 934 if (postContextClick_Window(w, &event.button)) {
909 wasUsed = iTrue; 935 wasUsed = iTrue;
910 } 936 }
911 } 937 }
912 } 938 }
913 if (isMetricsChange_UserEvent(&event)) { 939 if (isMetricsChange_UserEvent(&event)) {
914 iForIndices(i, d->roots) { 940 iForIndices(i, w->roots) {
915 updateMetrics_Root(d->roots[i]); 941 updateMetrics_Root(w->roots[i]);
916 } 942 }
917 } 943 }
918 if (isCommand_UserEvent(&event, "lang.changed")) { 944 if (isCommand_UserEvent(&event, "lang.changed")) {
@@ -921,16 +947,16 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
921 removeMacMenus_(); 947 removeMacMenus_();
922 insertMacMenus_(); 948 insertMacMenus_();
923#endif 949#endif
924 invalidate_Window(d); 950 invalidate_Window(w);
925 iForIndices(i, d->roots) { 951 iForIndices(i, w->roots) {
926 if (d->roots[i]) { 952 if (w->roots[i]) {
927 updatePreferencesLayout_Widget(findChild_Widget(d->roots[i]->widget, "prefs")); 953 updatePreferencesLayout_Widget(findChild_Widget(w->roots[i]->widget, "prefs"));
928 arrange_Widget(d->roots[i]->widget); 954 arrange_Widget(w->roots[i]->widget);
929 } 955 }
930 } 956 }
931 } 957 }
932 if (event.type == SDL_MOUSEMOTION) { 958 if (event.type == SDL_MOUSEMOTION) {
933 applyCursor_Window_(d); 959 applyCursor_Window_(w);
934 } 960 }
935 return wasUsed; 961 return wasUsed;
936 } 962 }
@@ -1018,25 +1044,26 @@ iBool postContextClick_Window(iWindow *d, const SDL_MouseButtonEvent *ev) {
1018 return iFalse; 1044 return iFalse;
1019} 1045}
1020 1046
1021void draw_Window(iWindow *d) { 1047void draw_MainWindow(iMainWindow *d) {
1022 if (d->isDrawFrozen) { 1048 iWindow *w = as_Window(d);
1049 if (w->isDrawFrozen) {
1023 return; 1050 return;
1024 } 1051 }
1025 /* Check if root needs resizing. */ { 1052 /* Check if root needs resizing. */ {
1026 iInt2 renderSize; 1053 iInt2 renderSize;
1027 SDL_GetRendererOutputSize(d->render, &renderSize.x, &renderSize.y); 1054 SDL_GetRendererOutputSize(w->render, &renderSize.x, &renderSize.y);
1028 if (!isEqual_I2(renderSize, d->size)) { 1055 if (!isEqual_I2(renderSize, w->size)) {
1029 updateSize_Window_(d, iTrue); 1056 updateSize_MainWindow_(d, iTrue);
1030 processEvents_App(postedEventsOnly_AppEventMode); 1057 processEvents_App(postedEventsOnly_AppEventMode);
1031 } 1058 }
1032 } 1059 }
1033 const int winFlags = SDL_GetWindowFlags(d->win); 1060 const int winFlags = SDL_GetWindowFlags(d->base.win);
1034 const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; 1061 const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0;
1035 iPaint p; 1062 iPaint p;
1036 init_Paint(&p); 1063 init_Paint(&p);
1037 /* Clear the window. The clear color is visible as a border around the window 1064 /* Clear the window. The clear color is visible as a border around the window
1038 when the custom frame is being used. */ { 1065 when the custom frame is being used. */ {
1039 setCurrent_Root(d->roots[0]); 1066 setCurrent_Root(w->roots[0]);
1040#if defined (iPlatformMobile) 1067#if defined (iPlatformMobile)
1041 iColor back = get_Color(uiBackground_ColorId); 1068 iColor back = get_Color(uiBackground_ColorId);
1042 if (deviceType_App() == phone_AppDeviceType) { 1069 if (deviceType_App() == phone_AppDeviceType) {
@@ -1050,16 +1077,16 @@ void draw_Window(iWindow *d) {
1050 : uiSeparator_ColorId); 1077 : uiSeparator_ColorId);
1051#endif 1078#endif
1052 unsetClip_Paint(&p); /* update clip to full window */ 1079 unsetClip_Paint(&p); /* update clip to full window */
1053 SDL_SetRenderDrawColor(d->render, back.r, back.g, back.b, 255); 1080 SDL_SetRenderDrawColor(w->render, back.r, back.g, back.b, 255);
1054 SDL_RenderClear(d->render); 1081 SDL_RenderClear(w->render);
1055 } 1082 }
1056 /* Draw widgets. */ 1083 /* Draw widgets. */
1057 d->frameTime = SDL_GetTicks(); 1084 w->frameTime = SDL_GetTicks();
1058 if (isExposed_Window(d)) { 1085 if (isExposed_Window(w)) {
1059 d->isInvalidated = iFalse; 1086 w->isInvalidated = iFalse;
1060 extern int drawCount_; 1087 extern int drawCount_;
1061 iForIndices(i, d->roots) { 1088 iForIndices(i, w->roots) {
1062 iRoot *root = d->roots[i]; 1089 iRoot *root = w->roots[i];
1063 if (root) { 1090 if (root) {
1064 setCurrent_Root(root); 1091 setCurrent_Root(root);
1065 unsetClip_Paint(&p); /* update clip to current root */ 1092 unsetClip_Paint(&p); /* update clip to current root */
@@ -1076,14 +1103,14 @@ void draw_Window(iWindow *d) {
1076 SDL_SetTextureColorMod(d->appIcon, iconColor.r, iconColor.g, iconColor.b); 1103 SDL_SetTextureColorMod(d->appIcon, iconColor.r, iconColor.g, iconColor.b);
1077 SDL_SetTextureAlphaMod(d->appIcon, gotFocus || !isLight ? 255 : 92); 1104 SDL_SetTextureAlphaMod(d->appIcon, gotFocus || !isLight ? 255 : 92);
1078 SDL_RenderCopy( 1105 SDL_RenderCopy(
1079 d->render, 1106 w->render,
1080 d->appIcon, 1107 d->appIcon,
1081 NULL, 1108 NULL,
1082 &(SDL_Rect){ left_Rect(rect) + gap_UI * 1.25f, mid.y - size / 2, size, size }); 1109 &(SDL_Rect){ left_Rect(rect) + gap_UI * 1.25f, mid.y - size / 2, size, size });
1083 } 1110 }
1084#endif 1111#endif
1085 /* Root separator and keyboard focus indicator. */ 1112 /* Root separator and keyboard focus indicator. */
1086 if (numRoots_Window(d) > 1){ 1113 if (numRoots_Window(w) > 1){
1087 const iRect bounds = bounds_Widget(root->widget); 1114 const iRect bounds = bounds_Widget(root->widget);
1088 if (i == 1) { 1115 if (i == 1) {
1089 fillRect_Paint(&p, (iRect){ 1116 fillRect_Paint(&p, (iRect){
@@ -1091,7 +1118,7 @@ void draw_Window(iWindow *d) {
1091 init_I2(gap_UI / 4, height_Rect(bounds)) 1118 init_I2(gap_UI / 4, height_Rect(bounds))
1092 }, uiSeparator_ColorId); 1119 }, uiSeparator_ColorId);
1093 } 1120 }
1094 if (root == d->keyRoot) { 1121 if (root == w->keyRoot) {
1095 const iBool isDark = isDark_ColorTheme(colorTheme_App()); 1122 const iBool isDark = isDark_ColorTheme(colorTheme_App());
1096 fillRect_Paint(&p, (iRect){ 1123 fillRect_Paint(&p, (iRect){
1097 topLeft_Rect(bounds), 1124 topLeft_Rect(bounds),
@@ -1104,7 +1131,7 @@ void draw_Window(iWindow *d) {
1104 } 1131 }
1105 setCurrent_Root(NULL); 1132 setCurrent_Root(NULL);
1106#if !defined (NDEBUG) 1133#if !defined (NDEBUG)
1107 draw_Text(defaultBold_FontId, safeRect_Root(d->roots[0]).pos, red_ColorId, "%d", drawCount_); 1134 draw_Text(defaultBold_FontId, safeRect_Root(w->roots[0]).pos, red_ColorId, "%d", drawCount_);
1108 drawCount_ = 0; 1135 drawCount_ = 0;
1109#endif 1136#endif
1110 } 1137 }
@@ -1116,21 +1143,21 @@ void draw_Window(iWindow *d) {
1116 SDL_RenderCopy(d->render, glyphCache_Text(), NULL, &rect); 1143 SDL_RenderCopy(d->render, glyphCache_Text(), NULL, &rect);
1117 } 1144 }
1118#endif 1145#endif
1119 SDL_RenderPresent(d->render); 1146 SDL_RenderPresent(w->render);
1120} 1147}
1121 1148
1122void resize_Window(iWindow *d, int w, int h) { 1149void resize_MainWindow(iMainWindow *d, int w, int h) {
1123 if (w > 0 && h > 0) { 1150 if (w > 0 && h > 0) {
1124 SDL_SetWindowSize(d->win, w, h); 1151 SDL_SetWindowSize(d->base.win, w, h);
1125 updateSize_Window_(d, iFalse); 1152 updateSize_MainWindow_(d, iFalse);
1126 } 1153 }
1127 else { 1154 else {
1128 updateSize_Window_(d, iTrue); /* notify always */ 1155 updateSize_MainWindow_(d, iTrue); /* notify always */
1129 } 1156 }
1130} 1157}
1131 1158
1132void setTitle_Window(iWindow *d, const iString *title) { 1159void setTitle_MainWindow(iMainWindow *d, const iString *title) {
1133 SDL_SetWindowTitle(d->win, cstr_String(title)); 1160 SDL_SetWindowTitle(d->base.win, cstr_String(title));
1134 iLabelWidget *bar = findChild_Widget(get_Root()->widget, "winbar.title"); 1161 iLabelWidget *bar = findChild_Widget(get_Root()->widget, "winbar.title");
1135 if (bar) { 1162 if (bar) {
1136 updateText_LabelWidget(bar, title); 1163 updateText_LabelWidget(bar, title);
@@ -1204,11 +1231,15 @@ iWindow *get_Window(void) {
1204 return theWindow_; 1231 return theWindow_;
1205} 1232}
1206 1233
1234iMainWindow *get_MainWindow(void) {
1235 return as_MainWindow(theWindow_);
1236}
1237
1207iBool isOpenGLRenderer_Window(void) { 1238iBool isOpenGLRenderer_Window(void) {
1208 return isOpenGLRenderer_; 1239 return isOpenGLRenderer_;
1209} 1240}
1210 1241
1211void setKeyboardHeight_Window(iWindow *d, int height) { 1242void setKeyboardHeight_MainWindow(iMainWindow *d, int height) {
1212 if (d->keyboardHeight != height) { 1243 if (d->keyboardHeight != height) {
1213 d->keyboardHeight = height; 1244 d->keyboardHeight = height;
1214 postCommandf_App("keyboard.changed arg:%d", height); 1245 postCommandf_App("keyboard.changed arg:%d", height);
@@ -1216,47 +1247,49 @@ void setKeyboardHeight_Window(iWindow *d, int height) {
1216 } 1247 }
1217} 1248}
1218 1249
1219void checkPendingSplit_Window(iWindow *d) { 1250void checkPendingSplit_MainWindow(iMainWindow *d) {
1220 if (d->splitMode != d->pendingSplitMode) { 1251 if (d->splitMode != d->pendingSplitMode) {
1221 setSplitMode_Window(d, d->pendingSplitMode); 1252 setSplitMode_MainWindow(d, d->pendingSplitMode);
1222 } 1253 }
1223} 1254}
1224 1255
1225void swapRoots_Window(iWindow *d) { 1256void swapRoots_MainWindow(iMainWindow *d) {
1226 if (numRoots_Window(d) == 2) { 1257 iWindow *w = as_Window(d);
1227 iSwap(iRoot *, d->roots[0], d->roots[1]); 1258 if (numRoots_Window(w) == 2) {
1228 updateSize_Window_(d, iTrue); 1259 iSwap(iRoot *, w->roots[0], w->roots[1]);
1260 updateSize_MainWindow_(d, iTrue);
1229 } 1261 }
1230} 1262}
1231 1263
1232void setSplitMode_Window(iWindow *d, int splitFlags) { 1264void setSplitMode_MainWindow(iMainWindow *d, int splitFlags) {
1233 const int splitMode = splitFlags & mode_WindowSplit; 1265 const int splitMode = splitFlags & mode_WindowSplit;
1234 if (deviceType_App() == phone_AppDeviceType) { 1266 if (deviceType_App() == phone_AppDeviceType) {
1235 /* There isn't enough room on the phone. */ 1267 /* There isn't enough room on the phone. */
1236 /* TODO: Maybe in landscape only? */ 1268 /* TODO: Maybe in landscape only? */
1237 return; 1269 return;
1238 } 1270 }
1271 iWindow *w = as_Window(d);
1239 iAssert(current_Root() == NULL); 1272 iAssert(current_Root() == NULL);
1240 if (d->splitMode != splitMode) { 1273 if (d->splitMode != splitMode) {
1241 int oldCount = numRoots_Window(d); 1274 int oldCount = numRoots_Window(w);
1242 setFreezeDraw_Window(d, iTrue); 1275 setFreezeDraw_Window(w, iTrue);
1243 if (oldCount == 2 && splitMode == 0) { 1276 if (oldCount == 2 && splitMode == 0) {
1244 /* Keep references to the tabs of the second root. */ 1277 /* Keep references to the tabs of the second root. */
1245 const iDocumentWidget *curPage = document_Root(d->keyRoot); 1278 const iDocumentWidget *curPage = document_Root(w->keyRoot);
1246 if (!curPage) { 1279 if (!curPage) {
1247 /* All tabs closed on that side. */ 1280 /* All tabs closed on that side. */
1248 curPage = document_Root(otherRoot_Window(d, d->keyRoot)); 1281 curPage = document_Root(otherRoot_Window(w, w->keyRoot));
1249 } 1282 }
1250 iObjectList *tabs = listDocuments_App(d->roots[1]); 1283 iObjectList *tabs = listDocuments_App(w->roots[1]);
1251 iForEach(ObjectList, i, tabs) { 1284 iForEach(ObjectList, i, tabs) {
1252 setRoot_Widget(i.object, d->roots[0]); 1285 setRoot_Widget(i.object, w->roots[0]);
1253 } 1286 }
1254 setFocus_Widget(NULL); 1287 setFocus_Widget(NULL);
1255 delete_Root(d->roots[1]); 1288 delete_Root(w->roots[1]);
1256 d->roots[1] = NULL; 1289 w->roots[1] = NULL;
1257 d->keyRoot = d->roots[0]; 1290 w->keyRoot = w->roots[0];
1258 /* Move the deleted root's tabs to the first root. */ 1291 /* Move the deleted root's tabs to the first root. */
1259 setCurrent_Root(d->roots[0]); 1292 setCurrent_Root(w->roots[0]);
1260 iWidget *docTabs = findWidget_Root("doctabs"); 1293 iWidget *docTabs = findWidget_Root("doctabs");
1261 iForEach(ObjectList, j, tabs) { 1294 iForEach(ObjectList, j, tabs) {
1262 appendTabPage_Widget(docTabs, j.object, "", 0, 0); 1295 appendTabPage_Widget(docTabs, j.object, "", 0, 0);
@@ -1268,38 +1301,38 @@ void setSplitMode_Window(iWindow *d, int splitFlags) {
1268 } 1301 }
1269 else if (splitMode && oldCount == 1) { 1302 else if (splitMode && oldCount == 1) {
1270 /* Add a second root. */ 1303 /* Add a second root. */
1271 iDocumentWidget *moved = document_Root(d->roots[0]); 1304 iDocumentWidget *moved = document_Root(w->roots[0]);
1272 iAssert(d->roots[1] == NULL); 1305 iAssert(w->roots[1] == NULL);
1273 const iBool addToLeft = (prefs_App()->pinSplit == 2); 1306 const iBool addToLeft = (prefs_App()->pinSplit == 2);
1274 size_t newRootIndex = 1; 1307 size_t newRootIndex = 1;
1275 if (addToLeft) { 1308 if (addToLeft) {
1276 iSwap(iRoot *, d->roots[0], d->roots[1]); 1309 iSwap(iRoot *, w->roots[0], w->roots[1]);
1277 newRootIndex = 0; 1310 newRootIndex = 0;
1278 } 1311 }
1279 d->roots[newRootIndex] = new_Root(); 1312 w->roots[newRootIndex] = new_Root();
1280 d->keyRoot = d->roots[newRootIndex]; 1313 w->keyRoot = w->roots[newRootIndex];
1281 setCurrent_Root(d->roots[newRootIndex]); 1314 setCurrent_Root(w->roots[newRootIndex]);
1282 createUserInterface_Root(d->roots[newRootIndex]); 1315 createUserInterface_Root(w->roots[newRootIndex]);
1283 if (!isEmpty_String(d->pendingSplitUrl)) { 1316 if (!isEmpty_String(d->pendingSplitUrl)) {
1284 postCommandf_Root(d->roots[newRootIndex], "open url:%s", 1317 postCommandf_Root(w->roots[newRootIndex], "open url:%s",
1285 cstr_String(d->pendingSplitUrl)); 1318 cstr_String(d->pendingSplitUrl));
1286 clear_String(d->pendingSplitUrl); 1319 clear_String(d->pendingSplitUrl);
1287 } 1320 }
1288 else if (~splitFlags & noEvents_WindowSplit) { 1321 else if (~splitFlags & noEvents_WindowSplit) {
1289 iWidget *docTabs0 = findChild_Widget(d->roots[newRootIndex ^ 1]->widget, "doctabs"); 1322 iWidget *docTabs0 = findChild_Widget(w->roots[newRootIndex ^ 1]->widget, "doctabs");
1290 iWidget *docTabs1 = findChild_Widget(d->roots[newRootIndex]->widget, "doctabs"); 1323 iWidget *docTabs1 = findChild_Widget(w->roots[newRootIndex]->widget, "doctabs");
1291 /* If the old root has multiple tabs, move the current one to the new split. */ 1324 /* If the old root has multiple tabs, move the current one to the new split. */
1292 if (tabCount_Widget(docTabs0) >= 2) { 1325 if (tabCount_Widget(docTabs0) >= 2) {
1293 int movedIndex = tabPageIndex_Widget(docTabs0, moved); 1326 int movedIndex = tabPageIndex_Widget(docTabs0, moved);
1294 removeTabPage_Widget(docTabs0, movedIndex); 1327 removeTabPage_Widget(docTabs0, movedIndex);
1295 showTabPage_Widget(docTabs0, tabPage_Widget(docTabs0, iMax(movedIndex - 1, 0))); 1328 showTabPage_Widget(docTabs0, tabPage_Widget(docTabs0, iMax(movedIndex - 1, 0)));
1296 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ 1329 iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */
1297 setRoot_Widget(as_Widget(moved), d->roots[newRootIndex]); 1330 setRoot_Widget(as_Widget(moved), w->roots[newRootIndex]);
1298 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); 1331 prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0);
1299 postCommandf_App("tabs.switch page:%p", moved); 1332 postCommandf_App("tabs.switch page:%p", moved);
1300 } 1333 }
1301 else { 1334 else {
1302 postCommand_Root(d->roots[newRootIndex], "navigate.home"); 1335 postCommand_Root(w->roots[newRootIndex], "navigate.home");
1303 } 1336 }
1304 } 1337 }
1305 setCurrent_Root(NULL); 1338 setCurrent_Root(NULL);
@@ -1328,26 +1361,26 @@ void setSplitMode_Window(iWindow *d, int splitFlags) {
1328 } 1361 }
1329#endif 1362#endif
1330 if (~splitFlags & noEvents_WindowSplit) { 1363 if (~splitFlags & noEvents_WindowSplit) {
1331 updateSize_Window_(d, iTrue); 1364 updateSize_MainWindow_(d, iTrue);
1332 postCommand_App("window.unfreeze"); 1365 postCommand_App("window.unfreeze");
1333 } 1366 }
1334 } 1367 }
1335} 1368}
1336 1369
1337void setSnap_Window(iWindow *d, int snapMode) { 1370void setSnap_MainWindow(iMainWindow *d, int snapMode) {
1338 if (!prefs_App()->customFrame) { 1371 if (!prefs_App()->customFrame) {
1339 if (snapMode == maximized_WindowSnap) { 1372 if (snapMode == maximized_WindowSnap) {
1340 SDL_MaximizeWindow(d->win); 1373 SDL_MaximizeWindow(d->base.win);
1341 } 1374 }
1342 else if (snapMode == fullscreen_WindowSnap) { 1375 else if (snapMode == fullscreen_WindowSnap) {
1343 SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP); 1376 SDL_SetWindowFullscreen(d->base.win, SDL_WINDOW_FULLSCREEN_DESKTOP);
1344 } 1377 }
1345 else { 1378 else {
1346 if (snap_Window(d) == fullscreen_WindowSnap) { 1379 if (snap_MainWindow(d) == fullscreen_WindowSnap) {
1347 SDL_SetWindowFullscreen(d->win, 0); 1380 SDL_SetWindowFullscreen(d->base.win, 0);
1348 } 1381 }
1349 else { 1382 else {
1350 SDL_RestoreWindow(d->win); 1383 SDL_RestoreWindow(d->base.win);
1351 } 1384 }
1352 } 1385 }
1353 return; 1386 return;
@@ -1359,9 +1392,9 @@ void setSnap_Window(iWindow *d, int snapMode) {
1359 const int snapDist = gap_UI * 4; 1392 const int snapDist = gap_UI * 4;
1360 iRect newRect = zero_Rect(); 1393 iRect newRect = zero_Rect();
1361 SDL_Rect usable; 1394 SDL_Rect usable;
1362 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable); 1395 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable);
1363 if (d->place.snap == fullscreen_WindowSnap) { 1396 if (d->place.snap == fullscreen_WindowSnap) {
1364 SDL_SetWindowFullscreen(d->win, 0); 1397 SDL_SetWindowFullscreen(d->base.win, 0);
1365 } 1398 }
1366 d->place.snap = snapMode & ~redo_WindowSnap; 1399 d->place.snap = snapMode & ~redo_WindowSnap;
1367 switch (snapMode & mask_WindowSnap) { 1400 switch (snapMode & mask_WindowSnap) {
@@ -1382,8 +1415,8 @@ void setSnap_Window(iWindow *d, int snapMode) {
1382 case yMaximized_WindowSnap: 1415 case yMaximized_WindowSnap:
1383 newRect.pos.y = 0; 1416 newRect.pos.y = 0;
1384 newRect.size.y = usable.h; 1417 newRect.size.y = usable.h;
1385 SDL_GetWindowSize(d->win, &newRect.size.x, NULL); 1418 SDL_GetWindowSize(d->base.win, &newRect.size.x, NULL);
1386 SDL_GetWindowPosition(d->win, &newRect.pos.x, NULL); 1419 SDL_GetWindowPosition(d->base.win, &newRect.pos.x, NULL);
1387 /* Snap the window to left/right edges, if close by. */ 1420 /* Snap the window to left/right edges, if close by. */
1388 if (iAbs(right_Rect(newRect) - (usable.x + usable.w)) < snapDist) { 1421 if (iAbs(right_Rect(newRect) - (usable.x + usable.w)) < snapDist) {
1389 newRect.pos.x = usable.x + usable.w - width_Rect(newRect); 1422 newRect.pos.x = usable.x + usable.w - width_Rect(newRect);
@@ -1393,7 +1426,7 @@ void setSnap_Window(iWindow *d, int snapMode) {
1393 } 1426 }
1394 break; 1427 break;
1395 case fullscreen_WindowSnap: 1428 case fullscreen_WindowSnap:
1396 SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP); 1429 SDL_SetWindowFullscreen(d->base.win, SDL_WINDOW_FULLSCREEN_DESKTOP);
1397 break; 1430 break;
1398 } 1431 }
1399 if (snapMode & (topBit_WindowSnap | bottomBit_WindowSnap)) { 1432 if (snapMode & (topBit_WindowSnap | bottomBit_WindowSnap)) {
@@ -1425,9 +1458,9 @@ void setSnap_Window(iWindow *d, int snapMode) {
1425#endif /* defined (LAGRANGE_ENABLE_CUSTOM_FRAME) */ 1458#endif /* defined (LAGRANGE_ENABLE_CUSTOM_FRAME) */
1426} 1459}
1427 1460
1428int snap_Window(const iWindow *d) { 1461int snap_MainWindow(const iMainWindow *d) {
1429 if (!prefs_App()->customFrame) { 1462 if (!prefs_App()->customFrame) {
1430 const int flags = SDL_GetWindowFlags(d->win); 1463 const int flags = SDL_GetWindowFlags(d->base.win);
1431 if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { 1464 if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) {
1432 return fullscreen_WindowSnap; 1465 return fullscreen_WindowSnap;
1433 } 1466 }