FreeRDP
Loading...
Searching...
No Matches
SdlRailWindow Class Reference

#include <sdl_rail_window.hpp>

Data Structures

struct  LoopEndActions
 

Public Member Functions

 SdlRailWindow (uint64_t id, const SDL_Rect &rect)
 
 SdlRailWindow (SdlRailWindow &&)=delete
 
 SdlRailWindow (const SdlRailWindow &)=delete
 
SdlRailWindow & operator= (const SdlRailWindow &)=delete
 
SdlRailWindow & operator= (SdlRailWindow &&)=delete
 
uint64_t id () const
 
SDL_WindowID sdlId () const
 
SDL_Window * window () const
 
SDL_Renderer * renderer () const
 
void updateWindowRect (const SDL_Rect &rect)
 
SDL_Rect windowRect () const
 
void setLocalMoveActive (bool active)
 
bool localMoveActive () const
 
bool localMoveSizeChanged () const
 
SDL_Point localMoveServerPos () const
 
void adoptLocalGeometry (const SDL_Rect &rect)
 
void setResizeAnchor (bool right, bool bottom)
 
void markDeleted ()
 
bool isDeleted () const
 
bool geomApplyPending () const
 
void clearGeomApplyPending ()
 
void armLoopEnd ()
 
bool loopEndPending () const
 
void deferMaximize ()
 
void deferSnap (const SDL_Rect &serverRect)
 
void clearLoopEnd ()
 
LoopEndActions takeLoopEnd ()
 
bool takeWmOverride (SDL_Rect &outer)
 
void setVisibilityRects (std::vector< SDL_Rect > rects)
 
void setVisibleOffset (SDL_Point offset)
 
void setMinMaxSize (SDL_Point minSize, SDL_Point maxSize)
 
void setResizeMargins (int left, int top, int right, int bottom)
 
SDL_Rect resizeMargins () const
 
void setFrameMargins (const SDL_Rect &m)
 
SDL_Rect frameMargins () const
 
void setOwner (uint64_t ownerId)
 
uint64_t owner () const
 
bool isPopup () const
 
bool isFullscreen () const
 
bool isLayered () const
 
void setShadowAnchored (bool anchored)
 
void setFrame (bool frame)
 
bool isFrame () const
 
SDL_Rect insets () const
 
SDL_Rect outerRect () const
 
SDL_Point serverOrigin () const
 
SDL_Rect serverRect (const SDL_Rect &outer) const
 
void setStyle (uint32_t style, uint32_t exStyle)
 
void setTitle (const std::string &title)
 
void setVisible (bool visible)
 
void setIcon (const SdlRailIcon &icon)
 
bool takeSurfaceChange (uint32_t surfaceId)
 
void updateGfxSurface (const void *data, uint32_t stride, uint32_t width, uint32_t height, const RECTANGLE_16 *damage, uint32_t nbDamage, uint32_t format)
 
void invalidateAll ()
 
bool railMaximized () const
 
void setRailMaximized (bool m)
 
void setServerMaximized (bool m)
 
bool railMinimized () const
 
void setRailMinimized (bool m)
 
void setServerMinimized (bool m)
 
void markGeometryDirty ()
 
bool geometryFrozen () const
 
bool awaitingRestoreRect () const
 
bool effectivelyMaximized () const
 
bool stateTransitionPending () const
 
bool reconcile (SDL_Window *parent, const SDL_Rect &parentRect)
 
bool paint (SDL_Surface *primary, SDL_PixelFormat fallbackFormat, const std::vector< SDL_Rect > &damage, SDL_Window *parent, const SDL_Rect &parentRect)
 

Detailed Description

A single RemoteApp window, backed by a borderless SDL window.

Geometry is server-authoritative: _windowRect mirrors the server's WINDOW_ORDER offset/size and the local SDL window is moved/resized to follow it.

Definition at line 48 of file sdl_rail_window.hpp.


Data Structure Documentation

◆ SdlRailWindow::LoopEndActions

struct SdlRailWindow::LoopEndActions

Definition at line 95 of file sdl_rail_window.hpp.

Data Fields
bool maximize = false
bool snap = false
SDL_Rect snapRect = { 0, 0, 0, 0 }

Constructor & Destructor Documentation

◆ SdlRailWindow()

SdlRailWindow::SdlRailWindow ( uint64_t  id,
const SDL_Rect &  rect 
)

Definition at line 67 of file sdl_rail_window.cpp.

67 : _id(id), _windowRect(rect)
68{
69}

Member Function Documentation

◆ adoptLocalGeometry()

void SdlRailWindow::adoptLocalGeometry ( const SDL_Rect &  rect)

Definition at line 163 of file sdl_rail_window.cpp.

164{
165 /* Adopt local geometry so the server's echoing WINDOW_ORDER is a no-op (not a size snap). */
166 std::unique_lock lock(_gfxLock);
167 /* A completed local move settles geometry via the completion path, not the reporter. */
168 _geomApplyPending = false;
169 /* Translate visible offset by move delta. */
170 if (_visOffsetSet)
171 {
172 _visOffset.x += rect.x - _windowRect.x;
173 _visOffset.y += rect.y - _windowRect.y;
174 }
175 _windowRect = rect;
176 _geometryDirty = false;
177 /* A resize drag ends here; the server surface still has the pre-drag size. */
178 _awaitingFrameUntil =
179 (_localMoveActive && _localMoveIsResize) ? (SDL_GetTicks() + kAwaitServerFrameMs) : 0;
180 _localMoveActive = false;
181 _needsFullBlit = true;
182 /* Repaint real content (clear placeholder). */
183 if (_hasGfx)
184 _gfxDamage.assign(1, SDL_Rect{ 0, 0, static_cast<int>(_gfxW), static_cast<int>(_gfxH) });
185}

◆ armLoopEnd()

void SdlRailWindow::armLoopEnd ( )

Definition at line 217 of file sdl_rail_window.cpp.

218{
219 std::unique_lock lock(_gfxLock);
220 _loopEnd.pending = true;
221}

◆ awaitingRestoreRect()

bool SdlRailWindow::awaitingRestoreRect ( ) const
inline

Definition at line 192 of file sdl_rail_window.hpp.

193 {
194 std::unique_lock lock(_gfxLock);
195 return restoreRectPending();
196 }

◆ clearGeomApplyPending()

void SdlRailWindow::clearGeomApplyPending ( )

Definition at line 211 of file sdl_rail_window.cpp.

212{
213 std::unique_lock lock(_gfxLock);
214 _geomApplyPending = false;
215}

◆ clearLoopEnd()

void SdlRailWindow::clearLoopEnd ( )

Definition at line 242 of file sdl_rail_window.cpp.

243{
244 std::unique_lock lock(_gfxLock);
245 _loopEnd = {};
246}

◆ deferMaximize()

void SdlRailWindow::deferMaximize ( )

Definition at line 229 of file sdl_rail_window.cpp.

230{
231 std::unique_lock lock(_gfxLock);
232 _loopEnd.maximize = true;
233}

◆ deferSnap()

void SdlRailWindow::deferSnap ( const SDL_Rect &  serverRect)

Definition at line 235 of file sdl_rail_window.cpp.

236{
237 std::unique_lock lock(_gfxLock);
238 _loopEnd.snap = true;
239 _loopEnd.snapRect = serverRect;
240}

◆ effectivelyMaximized()

bool SdlRailWindow::effectivelyMaximized ( ) const

Definition at line 967 of file sdl_rail_window.cpp.

968{
969 return _maxState.rail ||
970 (_win && (SDL_GetWindowFlags(_win->window()) & SDL_WINDOW_MAXIMIZED) != 0);
971}

◆ frameMargins()

SDL_Rect SdlRailWindow::frameMargins ( ) const

Definition at line 320 of file sdl_rail_window.cpp.

321{
322 std::unique_lock lock(_gfxLock);
323 return _frameMargins;
324}

◆ geomApplyPending()

bool SdlRailWindow::geomApplyPending ( ) const

Definition at line 205 of file sdl_rail_window.cpp.

206{
207 std::unique_lock lock(_gfxLock);
208 return _geomApplyPending;
209}

◆ geometryFrozen()

bool SdlRailWindow::geometryFrozen ( ) const
inline

Definition at line 187 of file sdl_rail_window.hpp.

188 {
189 return _maxState.rail || _maxState.server || _minState.rail || _minState.server;
190 }

◆ id()

uint64_t SdlRailWindow::id ( ) const

Definition at line 74 of file sdl_rail_window.cpp.

75{
76 return _id;
77}

◆ insets()

SDL_Rect SdlRailWindow::insets ( ) const

Definition at line 431 of file sdl_rail_window.cpp.

432{
433 std::unique_lock lock(_gfxLock);
434 return _appliedInsets;
435}

◆ invalidateAll()

void SdlRailWindow::invalidateAll ( )

Definition at line 903 of file sdl_rail_window.cpp.

904{
905 std::unique_lock lock(_gfxLock);
906 _needsFullBlit = true;
907 if (_hasGfx)
908 _gfxDamage.assign(1, SDL_Rect{ 0, 0, static_cast<int>(_gfxW), static_cast<int>(_gfxH) });
909}

◆ isDeleted()

bool SdlRailWindow::isDeleted ( ) const

Definition at line 199 of file sdl_rail_window.cpp.

200{
201 std::unique_lock lock(_gfxLock);
202 return _deleted;
203}

◆ isFrame()

bool SdlRailWindow::isFrame ( ) const

Definition at line 368 of file sdl_rail_window.cpp.

369{
370 std::unique_lock lock(_gfxLock);
371 return _frame;
372}

◆ isFullscreen()

bool SdlRailWindow::isFullscreen ( ) const

Definition at line 344 of file sdl_rail_window.cpp.

345{
346 std::unique_lock lock(_gfxLock);
347 return _fullscreen;
348}

◆ isLayered()

bool SdlRailWindow::isLayered ( ) const

Definition at line 350 of file sdl_rail_window.cpp.

351{
352 std::unique_lock lock(_gfxLock);
353 return _layered;
354}

◆ isPopup()

bool SdlRailWindow::isPopup ( ) const

Definition at line 338 of file sdl_rail_window.cpp.

339{
340 std::unique_lock lock(_gfxLock);
341 return _isPopup;
342}

◆ localMoveActive()

bool SdlRailWindow::localMoveActive ( ) const

Definition at line 145 of file sdl_rail_window.cpp.

146{
147 std::unique_lock lock(_gfxLock);
148 return _localMoveActive;
149}

◆ localMoveServerPos()

SDL_Point SdlRailWindow::localMoveServerPos ( ) const

Definition at line 157 of file sdl_rail_window.cpp.

158{
159 std::unique_lock lock(_gfxLock);
160 return _localMoveServerPos;
161}

◆ localMoveSizeChanged()

bool SdlRailWindow::localMoveSizeChanged ( ) const

Definition at line 151 of file sdl_rail_window.cpp.

152{
153 std::unique_lock lock(_gfxLock);
154 return _localMoveSizeChanged;
155}

◆ loopEndPending()

bool SdlRailWindow::loopEndPending ( ) const

Definition at line 223 of file sdl_rail_window.cpp.

224{
225 std::unique_lock lock(_gfxLock);
226 return _loopEnd.pending;
227}

◆ markDeleted()

void SdlRailWindow::markDeleted ( )

Definition at line 193 of file sdl_rail_window.cpp.

194{
195 std::unique_lock lock(_gfxLock);
196 _deleted = true;
197}

◆ markGeometryDirty()

void SdlRailWindow::markGeometryDirty ( )
inline

Definition at line 181 of file sdl_rail_window.hpp.

182 {
183 std::unique_lock lock(_gfxLock);
184 _geometryDirty = true;
185 }

◆ outerRect()

SDL_Rect SdlRailWindow::outerRect ( ) const

Definition at line 438 of file sdl_rail_window.cpp.

439{
440 std::unique_lock lock(_gfxLock);
441 return addInsets(_windowRect, _appliedInsets);
442}

◆ owner()

uint64_t SdlRailWindow::owner ( ) const

Definition at line 332 of file sdl_rail_window.cpp.

333{
334 std::unique_lock lock(_gfxLock);
335 return _ownerId;
336}

◆ paint()

bool SdlRailWindow::paint ( SDL_Surface *  primary,
SDL_PixelFormat  fallbackFormat,
const std::vector< SDL_Rect > &  damage,
SDL_Window *  parent,
const SDL_Rect &  parentRect 
)

Definition at line 973 of file sdl_rail_window.cpp.

976{
977 if (!reconcile(parent, parentRect))
978 return false;
979
980 bool ok = false;
981 {
982 std::unique_lock lock(_gfxLock);
983 if (_hasGfx)
984 {
985 ok = paintGfx(fallbackFormat);
986 }
987 else
988 {
989 lock.unlock();
990 ok = paintLegacy(primary, damage);
991 }
992 }
993
994 /* Map in the same pass as the first frame, else the window defers a frame (menu lag). */
995 if (_gfxPresented && !_mapped && !_minState.rail)
996 {
997 _mapped = true;
998 WLog_DBG(TAG, "map id=0x%08" PRIx32 " %s", static_cast<uint32_t>(_id), role());
999 SDL_ShowWindow(_win->window());
1000 /* Reassert target position after show to override stale events. */
1001 if (_isPopup && parent)
1002 {
1003 std::unique_lock lock(_gfxLock);
1004 const SDL_Rect vis = targetOuterRect();
1005 SDL_SetWindowPosition(_win->window(), vis.x - parentRect.x, vis.y - parentRect.y);
1006 if (!railPlatformCaps().positionsReadable)
1007 _needsFullBlit = true; /* Wayland applies move on next surface commit */
1008 }
1009 if ((!_isPopup && !_layered) || _fullscreen)
1010 _win->raise(); /* Bring app and fullscreen windows to front. */
1011 }
1012 return ok;
1013}

◆ railMaximized()

bool SdlRailWindow::railMaximized ( ) const
inline

Definition at line 159 of file sdl_rail_window.hpp.

160 {
161 return _maxState.rail;
162 }

◆ railMinimized()

bool SdlRailWindow::railMinimized ( ) const
inline

Definition at line 169 of file sdl_rail_window.hpp.

170 {
171 return _minState.rail;
172 }

◆ reconcile()

bool SdlRailWindow::reconcile ( SDL_Window *  parent,
const SDL_Rect &  parentRect 
)

Definition at line 587 of file sdl_rail_window.cpp.

588{
589 std::unique_lock lock(_gfxLock);
590
591 /* Hidden windows get no local SDL window. Layered windows (e.g. docks) need GFX content and
592 * vis-rects to show; this hides empty DWM snap overlays. */
593 const bool popupReady = !_isPopup || _hasGfx;
594 /* Suppress server shadow frames and unparented full-display overlays. */
595 const bool unplaceable =
596 _frame || (_overlay && !railPlatformCaps().positionsReadable && isFullDisplaySize());
597 /* Layered window is shown only when anchored to an adjoining visible popup or overlay. */
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 /* Log standalone layered windows suppressed by popup shadow heuristic. */
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 /* Shown + raised in paint() after the first frame (created hidden). */
637 }
638
639 /* create() returned false on failure, so _win is non-null from here down. */
640 if (_topmostDirty)
641 {
642 _topmostDirty = false;
643 /* X11 only; Wayland has no protocol for this, the call still returns true. */
644 if (!_isPopup && !_layered)
645 std::ignore = SDL_SetWindowAlwaysOnTop(_win->window(), _topmost);
646 }
647
648 /* Resizability first: SDL refuses to maximize a non-resizable window. */
649 if (_styleDirty)
650 {
651 _win->resizeable(styleResizable());
652 _styleDirty = false;
653 /* Insets refresh on geometry updates to avoid flicker. */
654 }
655
656 /* State first: maximized/minimized gates the geometry apply below. */
657 /* Hold geometry sync until server sends restored rect to prevent re-maximizing. */
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 /* Update insets across maximize transitions outside active drag grab. */
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 /* _GTK_FRAME_EXTENTS: tell the WM the band ring is frame, not content (snap/tile geometry). */
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 /* Clamp min size hints to target bounds so stale hints do not block programmatic resize.
680 * Defer size hints and programmatic resize during active WM move/resize grab. */
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 /* Wayland: cap to the usable area - an oversized window cannot be dragged into reach. */
691 SDL_Rect usable{};
692 if (!railPlatformCaps().positionsReadable &&
693 SDL_GetDisplayUsableBounds(SDL_GetPrimaryDisplay(), &usable))
694 {
695 /* The local window is the outer frame: cap to the usable area plus the insets. */
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 /* Skip geometry apply when maximized, minimized or WM-dragged. */
709 if (_geometryDirty && !wmOwnsGeometry)
710 {
711 const SDL_Rect vis = targetOuterRect();
712 /* The window is (or becomes) vis = _windowRect + fresh insets: record those as the insets
713 * now baked in, so the round-trip back to server coords strips exactly this. */
714 _appliedInsets = bandInsets();
715 int cw = 0;
716 int ch = 0;
717 SDL_GetWindowSize(_win->window(), &cw, &ch);
718 bool applied = false;
719 /* Apply position and size if changed. */
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; /* Wayland applies move on next surface commit */
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 /* Settle window resize via SDL_SyncWindow before reading back geometry to avoid
746 * adopting transient dimensions while configure events are in flight. */
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 /* Adopt WM size while preserving server origin. */
757 _wmRefusedOuter = { vis.x, vis.y, aw, ah };
758 _wmRefused = true;
759 applied = false; /* Geometry refused by WM; do not await echo. */
760 }
761 }
762 }
763 _geometryDirty = false;
764 /* Echo filtering is only tracked for top-level app windows. */
765 _geomApplyPending = applied && !_isPopup;
766 }
767 /* Make dialog transient for owner. */
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 /* Defer show until first frame; this runs every reconcile, so skip the call once visible. */
798 if (!_minState.rail && _gfxPresented &&
799 (SDL_GetWindowFlags(_win->window()) & SDL_WINDOW_HIDDEN))
800 {
801 /* If transient-for owner was closed or hidden, show dialog standalone. */
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}

◆ renderer()

SDL_Renderer * SdlRailWindow::renderer ( ) const

Definition at line 89 of file sdl_rail_window.cpp.

90{
91 return _win ? _win->renderer() : nullptr;
92}

◆ resizeMargins()

SDL_Rect SdlRailWindow::resizeMargins ( ) const

Definition at line 308 of file sdl_rail_window.cpp.

309{
310 std::unique_lock lock(_gfxLock);
311 return _resizeMargins;
312}

◆ sdlId()

SDL_WindowID SdlRailWindow::sdlId ( ) const

Definition at line 79 of file sdl_rail_window.cpp.

80{
81 return _win ? _win->id() : 0;
82}

◆ serverOrigin()

SDL_Point SdlRailWindow::serverOrigin ( ) const

Definition at line 468 of file sdl_rail_window.cpp.

469{
470 std::unique_lock lock(_gfxLock);
471 /* Derive server coordinate from blit offset to match on-screen pixels. */
472 const SDL_Point dst = blitOffset();
473 return { _windowRect.x - dst.x, _windowRect.y - dst.y };
474}

◆ serverRect()

SDL_Rect SdlRailWindow::serverRect ( const SDL_Rect &  outer) const

Definition at line 444 of file sdl_rail_window.cpp.

445{
446 return stripInsets(outer, insets());
447}

◆ setFrame()

void SdlRailWindow::setFrame ( bool  frame)

Definition at line 362 of file sdl_rail_window.cpp.

363{
364 std::unique_lock lock(_gfxLock);
365 _frame = frame;
366}

◆ setFrameMargins()

void SdlRailWindow::setFrameMargins ( const SDL_Rect &  m)

Definition at line 314 of file sdl_rail_window.cpp.

315{
316 std::unique_lock lock(_gfxLock);
317 _frameMargins = m;
318}

◆ setIcon()

void SdlRailWindow::setIcon ( const SdlRailIcon &  icon)

Definition at line 516 of file sdl_rail_window.cpp.

517{
518 std::unique_lock lock(_gfxLock);
519 _icon = icon;
520 _iconDirty = true;
521}

◆ setLocalMoveActive()

void SdlRailWindow::setLocalMoveActive ( bool  active)

Definition at line 126 of file sdl_rail_window.cpp.

127{
128 std::unique_lock lock(_gfxLock);
129 _localMoveActive = active;
130 if (active)
131 {
132 _localMoveIsResize = false; /* default to move; setResizeAnchor marks a resize */
133 _localMoveSizeChanged = false;
134 }
135}

◆ setMinMaxSize()

void SdlRailWindow::setMinMaxSize ( SDL_Point  minSize,
SDL_Point  maxSize 
)

Definition at line 286 of file sdl_rail_window.cpp.

287{
288 std::unique_lock lock(_gfxLock);
289 _minSize = { std::max(0, minSize.x), std::max(0, minSize.y) };
290 _maxSize = { std::max(0, maxSize.x), std::max(0, maxSize.y) };
291 _minMaxDirty = true;
292 /* Re-apply geometry on min/max change. */
293 _geometryDirty = true;
294}

◆ setOwner()

void SdlRailWindow::setOwner ( uint64_t  ownerId)

Definition at line 326 of file sdl_rail_window.cpp.

327{
328 std::unique_lock lock(_gfxLock);
329 _ownerId = ownerId;
330}

◆ setRailMaximized()

void SdlRailWindow::setRailMaximized ( bool  m)
inline

Definition at line 163 of file sdl_rail_window.hpp.

164 {
165 std::unique_lock lock(_gfxLock);
166 _maxState.rail = m;
167 }

◆ setRailMinimized()

void SdlRailWindow::setRailMinimized ( bool  m)
inline

Definition at line 173 of file sdl_rail_window.hpp.

174 {
175 std::unique_lock lock(_gfxLock);
176 _minState.rail = m;
177 }

◆ setResizeAnchor()

void SdlRailWindow::setResizeAnchor ( bool  right,
bool  bottom 
)

Definition at line 137 of file sdl_rail_window.cpp.

138{
139 std::unique_lock lock(_gfxLock);
140 _resizeAnchorRight = right;
141 _resizeAnchorBottom = bottom;
142 _localMoveIsResize = true;
143}

◆ setResizeMargins()

void SdlRailWindow::setResizeMargins ( int  left,
int  top,
int  right,
int  bottom 
)

Definition at line 296 of file sdl_rail_window.cpp.

297{
298 std::unique_lock lock(_gfxLock);
299 const SDL_Rect m = { left, top, right, bottom };
300 if (SDL_RectsEqual(&m, &_resizeMargins))
301 return;
302 _resizeMargins = m;
303 /* Margins usually arrive after the first frame; the window must regrow to cover them. */
304 if (!railMaximized())
305 _geometryDirty = true;
306}

◆ setServerMaximized()

void SdlRailWindow::setServerMaximized ( bool  m)

Definition at line 921 of file sdl_rail_window.cpp.

922{
923 setServerState(_maxState, m);
924}

◆ setServerMinimized()

void SdlRailWindow::setServerMinimized ( bool  m)

Definition at line 926 of file sdl_rail_window.cpp.

927{
928 setServerState(_minState, m);
929}

◆ setShadowAnchored()

void SdlRailWindow::setShadowAnchored ( bool  anchored)

Definition at line 356 of file sdl_rail_window.cpp.

357{
358 std::unique_lock lock(_gfxLock);
359 _shadowAnchored = anchored;
360}

◆ setStyle()

void SdlRailWindow::setStyle ( uint32_t  style,
uint32_t  exStyle 
)

Definition at line 476 of file sdl_rail_window.cpp.

477{
478 std::unique_lock lock(_gfxLock);
479 const bool wasResizable = styleResizable();
480 const bool wasTopmost = _topmost;
481 _style = style;
482 _exStyle = exStyle;
483 _topmost = (exStyle & WS_EX_TOPMOST) != 0;
484 if (_topmost != wasTopmost)
485 _topmostDirty = true;
486 if ((style & (WS_THICKFRAME | WS_MAXIMIZEBOX)) != 0)
487 _everResizable = true;
488 /* Update resizability on style change. */
489 if (styleResizable() != wasResizable)
490 _styleDirty = true;
491 /* Classify popup and layered window types once on creation. */
492 if (!_popupClassified)
493 {
494 const auto classification = classifySdlRailWindowStyle(style, exStyle, _ownerId != 0);
495 _isPopup = classification.popup;
496 _layered = classification.layered;
497 _clickThrough = classification.clickThrough;
498 _overlay = classification.overlay;
499 _popupClassified = true;
500 }
501}

◆ setTitle()

void SdlRailWindow::setTitle ( const std::string &  title)

Definition at line 503 of file sdl_rail_window.cpp.

504{
505 std::unique_lock lock(_gfxLock);
506 _title = title;
507 _titleDirty = true;
508}

◆ setVisibilityRects()

void SdlRailWindow::setVisibilityRects ( std::vector< SDL_Rect >  rects)

Definition at line 266 of file sdl_rail_window.cpp.

267{
268 std::unique_lock lock(_gfxLock);
269 _visRects = std::move(rects);
270 _visDirty = true;
271}

◆ setVisible()

void SdlRailWindow::setVisible ( bool  visible)

Definition at line 510 of file sdl_rail_window.cpp.

511{
512 std::unique_lock lock(_gfxLock);
513 _visible = visible;
514}

◆ setVisibleOffset()

void SdlRailWindow::setVisibleOffset ( SDL_Point  offset)

Definition at line 273 of file sdl_rail_window.cpp.

274{
275 std::unique_lock lock(_gfxLock);
276 /* Freeze visible offset during local move. */
277 if (_localMoveActive)
278 return;
279 if (_visOffsetSet && (offset.x == _visOffset.x) && (offset.y == _visOffset.y))
280 return;
281 _visOffset = offset;
282 _visOffsetSet = true;
283 _visDirty = true;
284}

◆ stateTransitionPending()

bool SdlRailWindow::stateTransitionPending ( ) const
inline

Definition at line 200 of file sdl_rail_window.hpp.

201 {
202 /* _maxState/_minState are written under _gfxLock on the RDP thread. */
203 std::unique_lock lock(_gfxLock);
204 return _maxState.dirty || _minState.dirty || (_maxState.rail != _maxState.server) ||
205 (_minState.rail != _minState.server);
206 }

◆ takeLoopEnd()

SdlRailWindow::LoopEndActions SdlRailWindow::takeLoopEnd ( )

Definition at line 248 of file sdl_rail_window.cpp.

249{
250 std::unique_lock lock(_gfxLock);
251 const LoopEndActions actions{ _loopEnd.maximize, _loopEnd.snap, _loopEnd.snapRect };
252 _loopEnd = {};
253 return actions;
254}

◆ takeSurfaceChange()

bool SdlRailWindow::takeSurfaceChange ( uint32_t  surfaceId)

Definition at line 810 of file sdl_rail_window.cpp.

811{
812 std::unique_lock lock(_gfxLock);
813 if (_surfaceId == surfaceId)
814 return false;
815 _surfaceId = surfaceId;
816 return true;
817}

◆ takeWmOverride()

bool SdlRailWindow::takeWmOverride ( SDL_Rect &  outer)

Definition at line 256 of file sdl_rail_window.cpp.

257{
258 std::unique_lock lock(_gfxLock);
259 if (!_wmRefused)
260 return false;
261 outer = _wmRefusedOuter;
262 _wmRefused = false;
263 return true;
264}

◆ updateGfxSurface()

void SdlRailWindow::updateGfxSurface ( const void *  data,
uint32_t  stride,
uint32_t  width,
uint32_t  height,
const RECTANGLE_16 *  damage,
uint32_t  nbDamage,
uint32_t  format 
)

Definition at line 819 of file sdl_rail_window.cpp.

822{
823 std::unique_lock lock(_gfxLock);
824 /* The copies below are byte-for-byte; gdi_CreateSurface yields nothing else. */
825 WINPR_ASSERT((format == PIXEL_FORMAT_BGRA32) || (format == PIXEL_FORMAT_BGRX32));
826 /* Deep-copy GDI pixels to prevent UAF. */
827 const size_t bytes = static_cast<size_t>(stride) * height;
828 if (!data || (bytes == 0) || (width == 0) || (height == 0))
829 {
830 if (_hasGfx)
831 WLog_DBG(TAG, "gfx cleared id=0x%08" PRIx32 " (surface unmapped)",
832 static_cast<uint32_t>(_id));
833 _gfxBuffer.clear();
834 _hasGfx = false;
835 _gfxDamage.clear();
836 _gfxStride = stride;
837 _gfxW = width;
838 _gfxH = height;
839 _gfxVisOrigin = { 0, 0 };
840 return;
841 }
842
843 const auto* src = static_cast<const uint8_t*>(data);
844 /* Geometry/stride change, first frame, or no damage rects: full copy + repaint. */
845 const bool full = !_hasGfx || (_gfxBuffer.size() != bytes) || (_gfxStride != stride) ||
846 (_gfxW != width) || (_gfxH != height) || (nbDamage == 0);
847 if (full)
848 {
849 const SDL_Rect bounds{ 0, 0, static_cast<int>(width), static_cast<int>(height) };
850 /* Check _hasGfx first to avoid redundant full-surface blank checks once content exists. */
851 if (!_hasGfx && regionIsBlank(src, stride, bounds))
852 return;
853 _gfxBuffer.assign(src, src + bytes);
854 _gfxDamage.assign(1, SDL_Rect{ 0, 0, static_cast<int>(width), static_cast<int>(height) });
855 _needsFullBlit = true;
856 /* Blend real alpha, force opaque otherwise. */
857 _gfxHasAlpha = honorsAlpha() &&
858 regionHasAlpha(_gfxBuffer.data(), stride,
859 { 0, 0, static_cast<int>(width), static_cast<int>(height) });
860 }
861 else
862 {
863 const SDL_Rect bounds{ 0, 0, static_cast<int>(width), static_cast<int>(height) };
864 for (uint32_t i = 0; i < nbDamage; i++)
865 {
866 const SDL_Rect r{ damage[i].left, damage[i].top, damage[i].right - damage[i].left,
867 damage[i].bottom - damage[i].top };
868 SDL_Rect clip{};
869 if (!SDL_GetRectIntersection(&r, &bounds, &clip))
870 continue;
871 std::ignore = freerdp_image_copy_no_overlap(
872 _gfxBuffer.data(), PIXEL_FORMAT_BGRA32, stride, static_cast<UINT32>(clip.x),
873 static_cast<UINT32>(clip.y), static_cast<UINT32>(clip.w),
874 static_cast<UINT32>(clip.h), src, PIXEL_FORMAT_BGRA32, stride,
875 static_cast<UINT32>(clip.x), static_cast<UINT32>(clip.y), nullptr,
876 FREERDP_FLIP_NONE);
877 _gfxDamage.push_back(clip);
878 /* Alpha may first appear in a later incremental frame (e.g. a menu fading in). */
879 if (honorsAlpha() && !_gfxHasAlpha && regionHasAlpha(_gfxBuffer.data(), stride, clip))
880 _gfxHasAlpha = true;
881 }
882 /* A hidden window accumulates rects without ever painting; collapse to one full repaint. */
883 if (_gfxDamage.size() > 32)
884 _gfxDamage.assign(1,
885 SDL_Rect{ 0, 0, static_cast<int>(width), static_cast<int>(height) });
886 }
887 if ((_gfxW != width) || (_gfxH != height))
888 {
889 _resizeAnchorRight = false;
890 _resizeAnchorBottom = false;
891 _needsFullBlit = true;
892 /* Invalidate surface origin until visibility rect matching new dimensions arrives. */
893 _gfxVisOrigin = { 0, 0 };
894 }
895 _hasGfx = true;
896 _gfxStride = stride;
897 _gfxW = width;
898 _gfxH = height;
899 WLog_VRB(TAG, "gfx id=0x%08" PRIx32 " %ux%u full=%d nDamage=%u", static_cast<uint32_t>(_id),
900 width, height, full ? 1 : 0, nbDamage);
901}

◆ updateWindowRect()

void SdlRailWindow::updateWindowRect ( const SDL_Rect &  rect)

Definition at line 94 of file sdl_rail_window.cpp.

95{
96 std::unique_lock lock(_gfxLock);
97 _awaitRestoreUntil = 0; /* Server geometry received. */
98 if (_localMoveActive)
99 {
100 /* Adopt server size change during local move. */
101 if (!_localMoveIsResize && ((rect.w != _windowRect.w) || (rect.h != _windowRect.h)))
102 {
103 WLog_DBG(TAG, "size adopted mid-move id=0x%08" PRIx32 " %dx%d -> %dx%d at %d,%d",
104 static_cast<uint32_t>(_id), _windowRect.w, _windowRect.h, rect.w, rect.h,
105 rect.x, rect.y);
106 _windowRect.w = rect.w;
107 _windowRect.h = rect.h;
108 /* Record server re-anchor position. */
109 _localMoveServerPos = { rect.x, rect.y };
110 _localMoveSizeChanged = true;
111 _painted = false;
112 }
113 return;
114 }
115 /* Accept post-move geometry echoes. */
116 if (SDL_RectsEqual(&rect, &_windowRect))
117 return;
118 /* A resize recreates the render target, so the content needs a full re-copy. */
119 if ((rect.w != _windowRect.w) || (rect.h != _windowRect.h))
120 _painted = false;
121 _windowRect = rect;
122 /* Mark dirty even if frozen/maximized so pending restore rect applies upon unfreeze. */
123 _geometryDirty = true;
124}

◆ window()

SDL_Window * SdlRailWindow::window ( ) const

Definition at line 84 of file sdl_rail_window.cpp.

85{
86 return _win ? _win->window() : nullptr;
87}

◆ windowRect()

SDL_Rect SdlRailWindow::windowRect ( ) const

Definition at line 187 of file sdl_rail_window.cpp.

188{
189 std::unique_lock lock(_gfxLock);
190 return _windowRect;
191}

The documentation for this class was generated from the following files: