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