588{
589 std::unique_lock lock(_gfxLock);
590
591
592
593 const bool popupReady = !_isPopup || _hasGfx;
594
595 const bool unplaceable =
596 _frame || (_overlay && !railPlatformCaps().positionsReadable && isFullDisplaySize());
597
598 const bool drawable =
599 _visible && (_windowRect.w > 0) && (_windowRect.h > 0) && popupReady && !unplaceable &&
600 (!_layered || (_hasGfx && !_visRects.empty() && (_shadowAnchored || _overlay)));
601
602 if (!drawable)
603 {
604
605 if (_layered && _hasGfx && !_visRects.empty() && !_shadowAnchored && !_overlay &&
606 !_shadowSuppressLogged)
607 {
608 _shadowSuppressLogged = true;
609 WLog_DBG(TAG,
610 "shadow-rule suppressed id=0x%08" PRIx32 " %dx%d style=0x%08" PRIx32
611 " ex=0x%08" PRIx32,
612 static_cast<uint32_t>(_id), _windowRect.w, _windowRect.h, _style, _exStyle);
613 }
614 if (_win)
615 {
616 if ((SDL_GetWindowFlags(_win->window()) & SDL_WINDOW_HIDDEN) == 0)
617 {
618 WLog_DBG(TAG, "hide id=0x%08" PRIx32 " %s", static_cast<uint32_t>(_id), role());
619 SDL_HideWindow(_win->window());
620 }
621 _mapped = false;
622 }
623 if (_isPopup && !_visible)
624 {
625 _gfxPresented = false;
626 _hasGfx = false;
627 }
628 return false;
629 }
630
631 if (!_win)
632 {
633 if (!create(parent, parentRect))
634 return false;
635 _geometryDirty = false;
636
637 }
638
639
640 if (_topmostDirty)
641 {
642 _topmostDirty = false;
643
644 if (!_isPopup && !_layered)
645 std::ignore = SDL_SetWindowAlwaysOnTop(_win->window(), _topmost);
646 }
647
648
649 if (_styleDirty)
650 {
651 _win->resizeable(styleResizable());
652 _styleDirty = false;
653
654 }
655
656
657
658 if (applyServerState(_maxState, "maximize", SDL_MaximizeWindow))
659 _awaitRestoreUntil = SDL_GetTicks() + kAwaitRestoreRectMs;
660 std::ignore = applyServerState(_minState, "minimize", SDL_MinimizeWindow);
661 const bool restorePending = restoreRectPending();
662
663
664 const bool maxed = effectivelyMaximized();
665 if ((maxed != _wasMaximized) && !_localMoveActive && !restorePending)
666 {
667 _appliedInsets = bandInsets();
668 if (!maxed)
669 _geometryDirty = true;
670 _wasMaximized = maxed;
671 }
672
673
674 const SDL_Rect ext = bandInsets();
675 if (!SDL_RectsEqual(&ext, &_extentsApplied) &&
676 sdl_x11_set_frame_extents(_win->window(), ext.x, ext.w, ext.y, ext.h))
677 _extentsApplied = ext;
678
679
680
681 const bool wmOwnsGeometry =
682 _localMoveActive || geometryFrozen() || _fullscreen || restorePending;
683 if ((_minMaxDirty || _geometryDirty) && !wmOwnsGeometry)
684 {
685 const SDL_Rect vis = targetOuterRect();
686 SDL_SetWindowMinimumSize(_win->window(), std::clamp(_minSize.x, 0, vis.w),
687 std::clamp(_minSize.y, 0, vis.h));
688 int maxW = (_maxSize.x > 0) ? std::max(1, _maxSize.x) : 0;
689 int maxH = (_maxSize.y > 0) ? std::max(1, _maxSize.y) : 0;
690
691 SDL_Rect usable{};
692 if (!railPlatformCaps().positionsReadable &&
693 SDL_GetDisplayUsableBounds(SDL_GetPrimaryDisplay(), &usable))
694 {
695
696 const SDL_Rect bi = bandInsets();
697 const int capW = usable.w + bi.x + bi.w;
698 const int capH = usable.h + bi.y + bi.h;
699 if ((maxW == 0) || (maxW > capW))
700 maxW = capW;
701 if ((maxH == 0) || (maxH > capH))
702 maxH = capH;
703 }
704 SDL_SetWindowMaximumSize(_win->window(), maxW, maxH);
705 _minMaxDirty = false;
706 }
707
708
709 if (_geometryDirty && !wmOwnsGeometry)
710 {
711 const SDL_Rect vis = targetOuterRect();
712
713
714 _appliedInsets = bandInsets();
715 int cw = 0;
716 int ch = 0;
717 SDL_GetWindowSize(_win->window(), &cw, &ch);
718 bool applied = false;
719
720 if (_isPopup && parent)
721 {
722 if (!SDL_SetWindowPosition(_win->window(), vis.x - parentRect.x, vis.y - parentRect.y))
723 WLog_VRB(TAG, "popup reposition unsupported id=0x%08" PRIx32 ": %s",
724 static_cast<uint32_t>(_id), SDL_GetError());
725 else if (!railPlatformCaps().positionsReadable)
726 _needsFullBlit = true;
727 applied = true;
728 }
729 else if (railPlatformCaps().positionsReadable &&
730 !(_isPopup && SDL_GetWindowParent(_win->window())))
731 {
732 int cx = 0;
733 int cy = 0;
734 SDL_GetWindowPosition(_win->window(), &cx, &cy);
735 if ((cx != vis.x) || (cy != vis.y))
736 {
737 SDL_SetWindowPosition(_win->window(), vis.x, vis.y);
738 applied = true;
739 }
740 }
741 if ((cw != vis.w) || (ch != vis.h))
742 {
743 std::ignore = _win->resize({ vis.w, vis.h });
744 applied = true;
745
746
747 if (railPlatformCaps().positionsReadable && !_isPopup && !_localMoveActive &&
748 !_loopEnd.pending)
749 {
750 const bool settled = SDL_SyncWindow(_win->window());
751 int aw = 0;
752 int ah = 0;
753 SDL_GetWindowSize(_win->window(), &aw, &ah);
754 if (settled && ((aw != vis.w) || (ah != vis.h)))
755 {
756
757 _wmRefusedOuter = { vis.x, vis.y, aw, ah };
758 _wmRefused = true;
759 applied = false;
760 }
761 }
762 }
763 _geometryDirty = false;
764
765 _geomApplyPending = applied && !_isPopup;
766 }
767
768 if (!_isPopup && parent && !_parentApplied)
769 {
770 if (SDL_SetWindowParent(_win->window(), parent))
771 _parentApplied = true;
772 }
773 if (_titleDirty)
774 {
775 if (!_isPopup)
776 SDL_SetWindowTitle(_win->window(), _title.c_str());
777 _titleDirty = false;
778 }
779 if (_iconDirty)
780 {
781 if (!_isPopup && !_icon.bgra.empty())
782 {
783 SDL_Surface* s = SDL_CreateSurfaceFrom(
784 static_cast<int>(_icon.w), static_cast<int>(_icon.h), SDL_PIXELFORMAT_BGRA32,
785 _icon.bgra.data(), static_cast<int>(_icon.w * 4));
786 if (s)
787 {
788 if (!SDL_SetWindowIcon(_win->window(), s))
789 WLog_WARN(TAG, "SDL_SetWindowIcon failed for window 0x%08" PRIx32 ": %s",
790 static_cast<uint32_t>(_id), SDL_GetError());
791 SDL_DestroySurface(s);
792 }
793 }
794 _iconDirty = false;
795 }
796
797
798 if (!_minState.rail && _gfxPresented &&
799 (SDL_GetWindowFlags(_win->window()) & SDL_WINDOW_HIDDEN))
800 {
801
802 SDL_Window* owner = _isPopup ? nullptr : SDL_GetWindowParent(_win->window());
803 if (owner && ((SDL_GetWindowFlags(owner) & SDL_WINDOW_HIDDEN) != 0))
804 std::ignore = SDL_SetWindowParent(_win->window(), nullptr);
805 SDL_ShowWindow(_win->window());
806 }
807 return true;
808}