diff options
Diffstat (limited to 'src/ui/window.c')
-rw-r--r-- | src/ui/window.c | 557 |
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 | ||
68 | static iBool isOpenGLRenderer_; | 68 | static iBool isOpenGLRenderer_; |
69 | 69 | ||
70 | iDefineTypeConstructionArgs(Window, (iRect rect), rect) | 70 | iDefineTypeConstructionArgs(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 | ||
172 | static void windowSizeChanged_Window_(iWindow *d) { | 172 | static 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 | ||
202 | static void setupUserInterface_Window(iWindow *d) { | 202 | static 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 | ||
215 | static void updateSize_Window_(iWindow *d, iBool notifyAlways) { | 215 | static 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 | ||
237 | void drawWhileResizing_Window(iWindow *d, int w, int h) { | 237 | void drawWhileResizing_MainWindow(iMainWindow *d, int w, int h) { |
238 | draw_Window(d); | 238 | draw_MainWindow(d); |
239 | } | 239 | } |
240 | 240 | ||
241 | static float pixelRatio_Window_(const iWindow *d) { | 241 | static 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) |
311 | static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos, void *data) { | 311 | static 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 | ||
363 | iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) { | 363 | iBool 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 | ||
400 | void init_Window(iWindow *d, iRect rect) { | 403 | void 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 | |||
446 | void 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 | |||
456 | void 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 | ||
520 | void deinit_Window(iWindow *d) { | 541 | static 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 | |||
552 | void 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 | ||
543 | SDL_Renderer *renderer_Window(const iWindow *d) { | 562 | SDL_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 | ||
553 | iBool isFullscreen_Window(const iWindow *d) { | 572 | iBool isFullscreen_MainWindow(const iMainWindow *d) { |
554 | return snap_Window(d) == fullscreen_WindowSnap; | 573 | return snap_MainWindow(d) == fullscreen_WindowSnap; |
555 | } | 574 | } |
556 | 575 | ||
557 | iRoot *findRoot_Window(const iWindow *d, const iWidget *widget) { | 576 | iRoot *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 | ||
573 | static void invalidate_Window_(iWindow *d, iBool forced) { | 592 | static 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 | ||
581 | void invalidate_Window(iWindow *d) { | 600 | void 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 | ||
585 | static iBool isNormalPlacement_Window_(const iWindow *d) { | 609 | static 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 | ||
597 | static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) { | 621 | static 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 | ||
655 | static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | 679 | static 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 | ||
809 | iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | 834 | iBool 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 | ||
1021 | void draw_Window(iWindow *d) { | 1047 | void 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 | ||
1122 | void resize_Window(iWindow *d, int w, int h) { | 1149 | void 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 | ||
1132 | void setTitle_Window(iWindow *d, const iString *title) { | 1159 | void 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 | ||
1234 | iMainWindow *get_MainWindow(void) { | ||
1235 | return as_MainWindow(theWindow_); | ||
1236 | } | ||
1237 | |||
1207 | iBool isOpenGLRenderer_Window(void) { | 1238 | iBool isOpenGLRenderer_Window(void) { |
1208 | return isOpenGLRenderer_; | 1239 | return isOpenGLRenderer_; |
1209 | } | 1240 | } |
1210 | 1241 | ||
1211 | void setKeyboardHeight_Window(iWindow *d, int height) { | 1242 | void 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 | ||
1219 | void checkPendingSplit_Window(iWindow *d) { | 1250 | void 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 | ||
1225 | void swapRoots_Window(iWindow *d) { | 1256 | void 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 | ||
1232 | void setSplitMode_Window(iWindow *d, int splitFlags) { | 1264 | void 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 | ||
1337 | void setSnap_Window(iWindow *d, int snapMode) { | 1370 | void 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 | ||
1428 | int snap_Window(const iWindow *d) { | 1461 | int 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 | } |