Changeset - r28810:dd35d3d734ac
[Not reviewed]
master
0 2 0
Peter Nelson - 9 months ago 2024-02-25 08:35:57
peter1138@openttd.org
Fix d3c673e: Don't defer OnResize() after ReInit() (#12174)

Some windows resize themselves during painting and issue ReInit(). In this case deferred OnResize() causes a visible glitch as the event is handled on the next redraw.
2 files changed with 10 insertions and 6 deletions:
0 comments (0 inline, 0 general)
src/window.cpp
Show inline comments
 
@@ -975,25 +975,25 @@ void Window::ReInit(int rx, int ry, bool
 
	int dy = (this->resize.step_height == 0) ? 0 : window_height - this->height;
 
	/* dx and dy has to go by step.. calculate it.
 
	 * The cast to int is necessary else dx/dy are implicitly casted to unsigned int, which won't work. */
 
	if (this->resize.step_width  > 1) dx -= dx % (int)this->resize.step_width;
 
	if (this->resize.step_height > 1) dy -= dy % (int)this->resize.step_height;
 

	
 
	if (reposition) {
 
		Point pt = this->OnInitialPosition(this->nested_root->smallest_x, this->nested_root->smallest_y, window_number);
 
		this->InitializePositionSize(pt.x, pt.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
 
		this->FindWindowPlacementAndResize(this->window_desc->GetDefaultWidth(), this->window_desc->GetDefaultHeight());
 
	}
 

	
 
	ResizeWindow(this, dx, dy);
 
	ResizeWindow(this, dx, dy, true, false);
 
	/* ResizeWindow() does this->SetDirty() already, no need to do it again here. */
 
}
 

	
 
/**
 
 * Set the shaded state of the window to \a make_shaded.
 
 * @param make_shaded If \c true, shade the window (roll up until just the title bar is visible), else unshade/unroll the window to its original size.
 
 * @note The method uses #Window::ReInit(), thus after the call, the whole window should be considered changed.
 
 */
 
void Window::SetShaded(bool make_shaded)
 
{
 
	if (this->shade_select == nullptr) return;
 

	
 
@@ -1438,26 +1438,26 @@ void Window::FindWindowPlacementAndResiz
 
		int enlarge_x = std::max(std::min(def_width  - this->width,  _screen.width - this->width),  0);
 
		int enlarge_y = std::max(std::min(def_height - this->height, free_height   - this->height), 0);
 

	
 
		/* X and Y has to go by step.. calculate it.
 
		 * The cast to int is necessary else x/y are implicitly casted to
 
		 * unsigned int, which won't work. */
 
		if (this->resize.step_width  > 1) enlarge_x -= enlarge_x % (int)this->resize.step_width;
 
		if (this->resize.step_height > 1) enlarge_y -= enlarge_y % (int)this->resize.step_height;
 

	
 
		ResizeWindow(this, enlarge_x, enlarge_y);
 
		/* ResizeWindow() calls this->OnResize(). */
 
	} else {
 
		/* Schedule OnResize; that way the scrollbars and matrices get initialized. */
 
		this->ScheduleResize();
 
		/* Always call OnResize; that way the scrollbars and matrices get initialized. */
 
		this->OnResize();
 
	}
 

	
 
	int nx = this->left;
 
	int ny = this->top;
 

	
 
	if (nx + this->width > _screen.width) nx -= (nx + this->width - _screen.width);
 

	
 
	const Window *wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
 
	ny = std::max(ny, (wt == nullptr || this == wt || this->top == 0) ? 0 : wt->height);
 
	nx = std::max(nx, 0);
 

	
 
	if (this->viewport != nullptr) {
 
@@ -2015,25 +2015,25 @@ static void EnsureVisibleCaption(Window 
 
}
 

	
 
/**
 
 * Resize the window.
 
 * Update all the widgets of a window based on their resize flags
 
 * Both the areas of the old window and the new sized window are set dirty
 
 * ensuring proper redrawal.
 
 * @param w       Window to resize
 
 * @param delta_x Delta x-size of changed window (positive if larger, etc.)
 
 * @param delta_y Delta y-size of changed window
 
 * @param clamp_to_screen Whether to make sure the whole window stays visible
 
 */
 
void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen)
 
void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen, bool schedule_resize)
 
{
 
	if (delta_x != 0 || delta_y != 0) {
 
		if (clamp_to_screen) {
 
			/* Determine the new right/bottom position. If that is outside of the bounds of
 
			 * the resolution clamp it in such a manner that it stays within the bounds. */
 
			int new_right  = w->left + w->width  + delta_x;
 
			int new_bottom = w->top  + w->height + delta_y;
 
			if (new_right  >= (int)_screen.width)  delta_x -= Ceil(new_right  - _screen.width,  std::max(1U, w->nested_root->resize_x));
 
			if (new_bottom >= (int)_screen.height) delta_y -= Ceil(new_bottom - _screen.height, std::max(1U, w->nested_root->resize_y));
 
		}
 

	
 
		w->SetDirty();
 
@@ -2042,25 +2042,29 @@ void ResizeWindow(Window *w, int delta_x
 
		uint new_yinc = std::max(0, (w->nested_root->resize_y == 0) ? 0 : (int)(w->nested_root->current_y - w->nested_root->smallest_y) + delta_y);
 
		assert(w->nested_root->resize_x == 0 || new_xinc % w->nested_root->resize_x == 0);
 
		assert(w->nested_root->resize_y == 0 || new_yinc % w->nested_root->resize_y == 0);
 

	
 
		w->nested_root->AssignSizePosition(ST_RESIZE, 0, 0, w->nested_root->smallest_x + new_xinc, w->nested_root->smallest_y + new_yinc, _current_text_dir == TD_RTL);
 
		w->width  = w->nested_root->current_x;
 
		w->height = w->nested_root->current_y;
 
	}
 

	
 
	EnsureVisibleCaption(w, w->left, w->top);
 

	
 
	/* Schedule OnResize to make sure everything is initialised correctly if it needs to be. */
 
	w->ScheduleResize();
 
	if (schedule_resize) {
 
		w->ScheduleResize();
 
	} else {
 
		w->OnResize();
 
	}
 
	w->SetDirty();
 
}
 

	
 
/**
 
 * Return the top of the main view available for general use.
 
 * @return Uppermost vertical coordinate available.
 
 * @note Above the upper y coordinate is often the main toolbar.
 
 */
 
int GetMainViewTop()
 
{
 
	Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
 
	return (w == nullptr) ? 0 : w->top + w->height;
src/window_func.h
Show inline comments
 
@@ -17,25 +17,25 @@
 

	
 
Window *FindWindowById(WindowClass cls, WindowNumber number);
 
Window *FindWindowByClass(WindowClass cls);
 
Window *GetMainWindow();
 
void ChangeWindowOwner(Owner old_owner, Owner new_owner);
 

	
 
template<typename T, std::enable_if_t<std::is_base_of<StrongTypedefBase, T>::value, int> = 0>
 
Window *FindWindowById(WindowClass cls, T number)
 
{
 
	return FindWindowById(cls, number.base());
 
}
 

	
 
void ResizeWindow(Window *w, int x, int y, bool clamp_to_screen = true);
 
void ResizeWindow(Window *w, int x, int y, bool clamp_to_screen = true, bool schedule_resize = true);
 
int PositionMainToolbar(Window *w);
 
int PositionStatusbar(Window *w);
 
int PositionNewsMessage(Window *w);
 
int PositionNetworkChatWindow(Window *w);
 

	
 
int GetMainViewTop();
 
int GetMainViewBottom();
 

	
 
void InitWindowSystem();
 
void UnInitWindowSystem();
 
void ResetWindowSystem();
 
void SetupColoursAndInitialWindow();
0 comments (0 inline, 0 general)