773{
774 std::unique_lock lock(_gfxLock);
775
776
777
778 const bool popupReady = !_isPopup || _hasGfx;
779
780 const bool unplaceable =
781 _frame || (_overlay && !railPlatformCaps().supportsWindowPositions && isFullDisplaySize());
782
783 const bool drawable =
784 _visible && (_windowRect.w > 0) && (_windowRect.h > 0) && popupReady && !unplaceable &&
785 (!_layered || (_hasGfx && !_visRects.empty() && (_shadowAnchored || _overlay)));
786
787 if (!drawable)
788 {
789
790 if (_layered && _hasGfx && !_visRects.empty() && !_shadowAnchored && !_overlay &&
791 !_shadowSuppressLogged)
792 {
793 _shadowSuppressLogged = true;
794 WLog_DBG(TAG,
795 "shadow-rule suppressed id=0x%08" PRIx32 " %dx%d style=0x%08" PRIx32
796 " ex=0x%08" PRIx32,
797 static_cast<uint32_t>(_id), _windowRect.w, _windowRect.h, _style, _exStyle);
798 }
799 if (_win)
800 {
801 if ((SDL_GetWindowFlags(_win->window()) & SDL_WINDOW_HIDDEN) == 0)
802 {
803 WLog_DBG(TAG, "hide id=0x%08" PRIx32 " %s", static_cast<uint32_t>(_id), role());
804 SDL_HideWindow(_win->window());
805 }
806 _mapped = false;
807 }
808 if (_isPopup && !_visible)
809 {
810 _gfxPresented = false;
811 _hasGfx = false;
812 }
813 return false;
814 }
815
816 if (!_win)
817 {
818 if (!create(parent, parentRect))
819 return false;
820 _geometryDirty = false;
821
822 }
823
824
825 if (_topmostDirty)
826 {
827 _topmostDirty = false;
828
829 if (!_isPopup && !_layered)
830 std::ignore = SDL_SetWindowAlwaysOnTop(_win->window(), _topmost);
831 }
832
833
834 if (_styleDirty)
835 {
836 _win->resizeable(styleResizable());
837 _styleDirty = false;
838
839 }
840
841
842
843 if (applyServerState(_maxState, "maximize", SDL_MaximizeWindow))
844 armDeadline(_awaitRestoreUntil, kAwaitRestoreRectMs);
845
846 if ((_localRestoreUntil != 0) && (SDL_GetTicks() >= _localRestoreUntil))
847 {
848 _localRestoreUntil = 0;
849 if (_minState.server && !_minState.rail && !_restoreRetried)
850 {
851 _restoreRetried = true;
852 _restoreRetry = true;
853 armDeadline(_localRestoreUntil, kAwaitRestoreRectMs);
854 }
855 else if (_minState.server != _minState.rail)
856 _minState.dirty = true;
857 }
858 std::ignore = applyServerState(_minState, "minimize", SDL_MinimizeWindow);
859 const bool restorePending = restoreRectPending();
860
861
862 const bool maxed = effectivelyMaximized();
863 const SDL_Rect band = bandInsets();
864 if ((maxed != _wasMaximized) && !_localMoveActive && !restorePending)
865 {
866 setAppliedInsets(band);
867 if (!maxed)
868 _geometryDirty = true;
869 _wasMaximized = maxed;
870 }
871
872
873 if ((railPlatformCaps().band == RailBandMechanism::FrameExtents) && !restorePending &&
874 !SDL_RectsEqual(&band, &_extentsApplied) && railPlatformSetBand(_win->window(), band))
875 {
876 _extentsApplied = band;
877 }
878 const bool wmOwnsGeometry =
879 _localMoveActive || geometryFrozen() || _fullscreen || restorePending;
880
881
882 if ((_minMaxDirty || _geometryDirty) && !wmOwnsGeometry)
883 {
884 const SDL_Rect vis = targetOuterRect();
885 const int bandW = band.x + band.w;
886 const int bandH = band.y + band.h;
887
888 const SDL_Rect& m = _resizeMargins;
889 const int padW = bandW - m.x - m.w;
890 const int padH = bandH - m.y - m.h;
891 const auto toOuter = [](int track, int pad)
892 { return (track > 0) ? std::max(1, track + pad) : 0; };
893 const int minW = toOuter(_minSize.x, padW);
894 const int minH = toOuter(_minSize.y, padH);
895 SDL_SetWindowMinimumSize(_win->window(), std::clamp(minW, 0, vis.w),
896 std::clamp(minH, 0, vis.h));
897 int maxW = toOuter(_maxSize.x, padW);
898 int maxH = toOuter(_maxSize.y, padH);
899
900 SDL_Rect usable{};
901 if (!railPlatformCaps().supportsWindowPositions &&
902 SDL_GetDisplayUsableBounds(SDL_GetPrimaryDisplay(), &usable))
903 {
904 const int capW = usable.w + bandW;
905 const int capH = usable.h + bandH;
906 if ((maxW == 0) || (maxW > capW))
907 maxW = capW;
908 if ((maxH == 0) || (maxH > capH))
909 maxH = capH;
910 }
911 SDL_SetWindowMaximumSize(_win->window(), maxW, maxH);
912 _minMaxDirty = false;
913 }
914
915
916 if (_geometryDirty && !wmOwnsGeometry)
917 {
918 const SDL_Rect vis = targetOuterRect();
919
920 setAppliedInsets(band);
921 int cw = 0;
922 int ch = 0;
923 SDL_GetWindowSize(_win->window(), &cw, &ch);
924 bool applied = false;
925 bool placed = false;
926
927 if (_isPopup && parent)
928 {
929 placePopup(vis, parentRect);
930 applied = true;
931 }
932 else if (railPlatformCaps().supportsWindowPositions &&
933 !(_isPopup && SDL_GetWindowParent(_win->window())))
934 {
935 int cx = 0;
936 int cy = 0;
937 SDL_GetWindowPosition(_win->window(), &cx, &cy);
938 if ((cx != vis.x) || (cy != vis.y))
939 {
940 placed = railPlatformSetWindowRect(_win->window(), vis);
941 if (!placed)
942 SDL_SetWindowPosition(_win->window(), vis.x, vis.y);
943 applied = true;
944 }
945 }
946 if ((cw != vis.w) || (ch != vis.h))
947 {
948 if (!placed && !railPlatformSetWindowRect(_win->window(), vis))
949 std::ignore = _win->resize({ vis.w, vis.h });
950 applied = true;
951
952
953 if (railPlatformCaps().supportsWindowPositions && !_isPopup && !_localMoveActive &&
954 !_loopEnd.pending)
955 {
956 const bool settled = SDL_SyncWindow(_win->window());
957 int aw = 0;
958 int ah = 0;
959 SDL_GetWindowSize(_win->window(), &aw, &ah);
960 if (settled && ((aw != vis.w) || (ah != vis.h)))
961 {
962
963 _wmRefusedOuter = { vis.x, vis.y, aw, ah };
964 _wmRefused = true;
965 applied = false;
966 }
967 }
968 }
969 _geometryDirty = false;
970
971 _geomApplyPending = applied && !_isPopup;
972 }
973
974
975 if (!_isPopup && parent && !_parentApplied &&
976 ((SDL_GetWindowFlags(parent) & SDL_WINDOW_HIDDEN) == 0))
977 {
978 if (SDL_SetWindowParent(_win->window(), parent))
979 {
980 _parentApplied = true;
981
982 if (((SDL_GetWindowFlags(_win->window()) & SDL_WINDOW_HIDDEN) == 0) &&
983 !railPlatformRaiseOwned(_win->window()))
984 WLog_WARN(TAG, "raising dialog id=0x%08" PRIx32 " failed",
985 static_cast<uint32_t>(_id));
986 }
987 }
988 if (_titleDirty)
989 {
990 if (!_isPopup)
991 SDL_SetWindowTitle(_win->window(), _title.c_str());
992 _titleDirty = false;
993 }
994 if (_iconDirty)
995 {
996 if (!_isPopup && !_icon.bgra.empty())
997 {
998 SDL_Surface* s = SDL_CreateSurfaceFrom(
999 static_cast<int>(_icon.w), static_cast<int>(_icon.h), SDL_PIXELFORMAT_BGRA32,
1000 _icon.bgra.data(), static_cast<int>(_icon.w * 4));
1001 if (s)
1002 {
1003 if (!SDL_SetWindowIcon(_win->window(), s))
1004 WLog_WARN(TAG, "SDL_SetWindowIcon failed for window 0x%08" PRIx32 ": %s",
1005 static_cast<uint32_t>(_id), SDL_GetError());
1006 SDL_DestroySurface(s);
1007 }
1008 }
1009 _iconDirty = false;
1010 }
1011
1012
1013 if (!_minState.rail && _gfxPresented &&
1014 (SDL_GetWindowFlags(_win->window()) & SDL_WINDOW_HIDDEN))
1015 {
1016
1017 SDL_Window* owner = _isPopup ? nullptr : SDL_GetWindowParent(_win->window());
1018 if (owner && ((SDL_GetWindowFlags(owner) & SDL_WINDOW_HIDDEN) != 0))
1019 {
1020 if (SDL_SetWindowParent(_win->window(), nullptr))
1021 _parentApplied = false;
1022 else
1023 WLog_WARN(TAG, "detaching dialog id=0x%08" PRIx32 " failed: %s",
1024 static_cast<uint32_t>(_id), SDL_GetError());
1025 }
1026 SDL_ShowWindow(_win->window());
1027 }
1028 return true;
1029}