OpenTTD Source: src/window.cpp Source File

OpenTTD Source 15.0-beta1

window.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "company_func.h"
12#include "gfx_func.h"
13#include "console_func.h"
14#include "console_gui.h"
15#include "viewport_func.h"
16#include "progress.h"
17#include "blitter/factory.hpp"
18#include "zoom_func.h"
19#include "vehicle_base.h"
20#include "depot_func.h"
21#include "window_func.h"
22#include "tilehighlight_func.h"
23#include "network/network.h"
24#include "querystring_gui.h"
25#include "strings_func.h"
26#include "settings_type.h"
27#include "settings_func.h"
28#include "ini_type.h"
29#include "newgrf_debug.h"
30#include "hotkeys.h"
31#include "toolbar_gui.h"
32#include "statusbar_gui.h"
33#include "error.h"
34#include "game/game.hpp"
35#include "video/video_driver.hpp"
36#include "framerate_type.h"
37#include "network/network_func.h"
38#include "news_func.h"
39#include "timer/timer.h"
40#include "timer/timer_window.h"
41
42#include "safeguards.h"
43
45 enum ViewportAutoscrolling {
46 VA_DISABLED,
47 VA_MAIN_VIEWPORT_FULLSCREEN,
48 VA_MAIN_VIEWPORT,
49 VA_EVERY_VIEWPORT,
50};
51
52 static Point _drag_delta;
53 static Window *_mouseover_last_w = nullptr;
54 static Window *_last_scroll_window = nullptr;
55
57WindowList _z_windows;
58
60/* static */ std::vector<Window *> Window::closed_windows;
61
65/* static */ void Window::DeleteClosedWindows()
66{
67 for (Window *w : Window::closed_windows) delete w;
68 Window::closed_windows.clear();
69
70 /* Remove dead entries from the window list */
71 _z_windows.remove(nullptr);
72}
73
75 bool _window_highlight_colour = false;
76
77/*
78 * Window that currently has focus. - The main purpose is to generate
79 * #FocusLost events, not to give next window in z-order focus when a
80 * window is closed.
81 */
82 Window *_focused_window;
83
84 Point _cursorpos_drag_start;
85
86int _scrollbar_start_pos;
87int _scrollbar_size;
88uint8_t _scroller_click_timeout = 0;
89
90 bool _scrolling_viewport;
91 bool _mouse_hovering;
92
93 SpecialMouseMode _special_mouse_mode;
94
99std::vector<WindowDesc*> *_window_descs = nullptr;
100
102std::string _windows_file;
103
105WindowDesc::WindowDesc(WindowPosition def_pos, const char *ini_key, int16_t def_width_trad, int16_t def_height_trad,
106 WindowClass window_class, WindowClass parent_class, uint32_t flags,
107 const std::span<const NWidgetPart> nwid_parts, HotkeyList *hotkeys,
108 const std::source_location location) :
109 source_location(location),
110 default_pos(def_pos),
111 cls(window_class),
112 parent_cls(parent_class),
113 ini_key(ini_key),
114 flags(flags),
115 nwid_parts(nwid_parts),
116 hotkeys(hotkeys),
117 pref_sticky(false),
118 pref_width(0),
119 pref_height(0),
120 default_width_trad(def_width_trad),
121 default_height_trad(def_height_trad)
122{
123 if (_window_descs == nullptr) _window_descs = new std::vector<WindowDesc*>();
124 _window_descs->push_back(this);
125}
126
127WindowDesc::~WindowDesc()
128{
129 _window_descs->erase(std::ranges::find(*_window_descs, this));
130}
131
137int16_t WindowDesc::GetDefaultWidth() const
138{
139 return this->pref_width != 0 ? this->pref_width : ScaleGUITrad(this->default_width_trad);
140}
141
147int16_t WindowDesc::GetDefaultHeight() const
148{
149 return this->pref_height != 0 ? this->pref_height : ScaleGUITrad(this->default_height_trad);
150}
151
155 void WindowDesc::LoadFromConfig()
156{
157 IniFile ini;
158 ini.LoadFromDisk(_windows_file, NO_DIRECTORY);
159 for (WindowDesc *wd : *_window_descs) {
160 if (wd->ini_key == nullptr) continue;
161 IniLoadWindowSettings(ini, wd->ini_key, wd);
162 }
163}
164
168 static bool DescSorter(WindowDesc * const &a, WindowDesc * const &b)
169{
170 if (a->ini_key != nullptr && b->ini_key != nullptr) return strcmp(a->ini_key, b->ini_key) < 0;
171 return a->ini_key != nullptr;
172}
173
177 void WindowDesc::SaveToConfig()
178{
179 /* Sort the stuff to get a nice ini file on first write */
180 std::sort(_window_descs->begin(), _window_descs->end(), DescSorter);
181
182 IniFile ini;
183 ini.LoadFromDisk(_windows_file, NO_DIRECTORY);
184 for (WindowDesc *wd : *_window_descs) {
185 if (wd->ini_key == nullptr) continue;
186 IniSaveWindowSettings(ini, wd->ini_key, wd);
187 }
188 ini.SaveToDisk(_windows_file);
189}
190
194 void Window::ApplyDefaults()
195{
196 if (this->nested_root != nullptr && this->nested_root->GetWidgetOfType(WWT_STICKYBOX) != nullptr) {
197 if (this->window_desc.pref_sticky) this->flags |= WF_STICKY;
198 } else {
199 /* There is no stickybox; clear the preference in case someone tried to be funny */
200 this->window_desc.pref_sticky = false;
201 }
202}
203
213 int Window::GetRowFromWidget(int clickpos, WidgetID widget, int padding, int line_height) const
214{
215 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(widget);
216 if (line_height < 0) line_height = wid->resize_y;
217 if (clickpos < wid->pos_y + padding) return INT_MAX;
218 return (clickpos - wid->pos_y - padding) / line_height;
219}
220
224 void Window::DisableAllWidgetHighlight()
225{
226 for (auto &pair : this->widget_lookup) {
227 NWidgetBase *nwid = pair.second;
228 if (nwid->IsHighlighted()) {
229 nwid->SetHighlighted(TC_INVALID);
230 nwid->SetDirty(this);
231 }
232 }
233
234 CLRBITS(this->flags, WF_HIGHLIGHTED);
235}
236
242 void Window::SetWidgetHighlight(WidgetID widget_index, TextColour highlighted_colour)
243{
244 NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget_index);
245 if (nwid == nullptr) return;
246
247 nwid->SetHighlighted(highlighted_colour);
248 nwid->SetDirty(this);
249
250 if (highlighted_colour != TC_INVALID) {
251 /* If we set a highlight, the window has a highlight */
252 this->flags |= WF_HIGHLIGHTED;
253 } else {
254 /* If we disable a highlight, check all widgets if anyone still has a highlight */
255 bool valid = false;
256 for (const auto &pair : this->widget_lookup) {
257 nwid = pair.second;
258 if (!nwid->IsHighlighted()) continue;
259
260 valid = true;
261 }
262 /* If nobody has a highlight, disable the flag on the window */
263 if (!valid) CLRBITS(this->flags, WF_HIGHLIGHTED);
264 }
265}
266
272 bool Window::IsWidgetHighlighted(WidgetID widget_index) const
273{
274 const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget_index);
275 if (nwid == nullptr) return false;
276
277 return nwid->IsHighlighted();
278}
279
287 void Window::OnDropdownClose(Point pt, WidgetID widget, int index, bool instant_close)
288{
289 if (widget < 0) return;
290
291 if (instant_close) {
292 /* Send event for selected option if we're still
293 * on the parent button of the dropdown (behaviour of the dropdowns in the main toolbar). */
294 if (GetWidgetFromPos(this, pt.x, pt.y) == widget) {
295 this->OnDropdownSelect(widget, index);
296 }
297 }
298
299 /* Raise the dropdown button */
300 NWidgetCore *nwi2 = this->GetWidget<NWidgetCore>(widget);
301 if ((nwi2->type & WWT_MASK) == NWID_BUTTON_DROPDOWN) {
302 nwi2->disp_flags &= ~ND_DROPDOWN_ACTIVE;
303 } else {
304 this->RaiseWidget(widget);
305 }
306 this->SetWidgetDirty(widget);
307}
308
314 const Scrollbar *Window::GetScrollbar(WidgetID widnum) const
315{
316 return this->GetWidget<NWidgetScrollbar>(widnum);
317}
318
324 Scrollbar *Window::GetScrollbar(WidgetID widnum)
325{
326 return this->GetWidget<NWidgetScrollbar>(widnum);
327}
328
334 const QueryString *Window::GetQueryString(WidgetID widnum) const
335{
336 auto query = this->querystrings.find(widnum);
337 return query != this->querystrings.end() ? query->second : nullptr;
338}
339
345 QueryString *Window::GetQueryString(WidgetID widnum)
346{
347 auto query = this->querystrings.find(widnum);
348 return query != this->querystrings.end() ? query->second : nullptr;
349}
350
354 void Window::UpdateQueryStringSize()
355{
356 for (auto &qs : this->querystrings) {
357 qs.second->text.UpdateSize();
358 }
359}
360
365/* virtual */ const Textbuf *Window::GetFocusedTextbuf() const
366{
367 if (this->nested_focus != nullptr && this->nested_focus->type == WWT_EDITBOX) {
368 return &this->GetQueryString(this->nested_focus->index)->text;
369 }
370
371 return nullptr;
372}
373
378/* virtual */ Point Window::GetCaretPosition() const
379{
380 if (this->nested_focus != nullptr && this->nested_focus->type == WWT_EDITBOX && !this->querystrings.empty()) {
381 return this->GetQueryString(this->nested_focus->index)->GetCaretPosition(this, this->nested_focus->index);
382 }
383
384 Point pt = {0, 0};
385 return pt;
386}
387
394/* virtual */ Rect Window::GetTextBoundingRect(const char *from, const char *to) const
395{
396 if (this->nested_focus != nullptr && this->nested_focus->type == WWT_EDITBOX) {
397 return this->GetQueryString(this->nested_focus->index)->GetBoundingRect(this, this->nested_focus->index, from, to);
398 }
399
400 Rect r = {0, 0, 0, 0};
401 return r;
402}
403
409/* virtual */ ptrdiff_t Window::GetTextCharacterAtPosition(const Point &pt) const
410{
411 if (this->nested_focus != nullptr && this->nested_focus->type == WWT_EDITBOX) {
412 return this->GetQueryString(this->nested_focus->index)->GetCharAtPosition(this, this->nested_focus->index, pt);
413 }
414
415 return -1;
416}
417
422 void SetFocusedWindow(Window *w)
423{
424 if (_focused_window == w) return;
425
426 /* Don't focus a tooltip */
427 if (w != nullptr && w->window_class == WC_TOOLTIPS) return;
428
429 /* Invalidate focused widget */
430 if (_focused_window != nullptr) {
431 if (_focused_window->nested_focus != nullptr) _focused_window->nested_focus->SetDirty(_focused_window);
432 }
433
434 /* Remember which window was previously focused */
435 Window *old_focused = _focused_window;
436 _focused_window = w;
437
438 /* So we can inform it that it lost focus */
439 if (old_focused != nullptr) old_focused->OnFocusLost(false);
440 if (_focused_window != nullptr) _focused_window->OnFocus();
441}
442
448 bool EditBoxInGlobalFocus()
449{
450 if (_focused_window == nullptr) return false;
451
452 /* The console does not have an edit box so a special case is needed. */
453 if (_focused_window->window_class == WC_CONSOLE) return true;
454
455 return _focused_window->nested_focus != nullptr && _focused_window->nested_focus->type == WWT_EDITBOX;
456}
457
462 bool FocusedWindowIsConsole()
463{
464 return _focused_window && _focused_window->window_class == WC_CONSOLE;
465}
466
470 void Window::UnfocusFocusedWidget()
471{
472 if (this->nested_focus != nullptr) {
473 if (this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxLostFocus();
474
475 /* Repaint the widget that lost focus. A focused edit box may else leave the caret on the screen. */
476 this->nested_focus->SetDirty(this);
477 this->nested_focus = nullptr;
478 }
479}
480
486 bool Window::SetFocusedWidget(WidgetID widget_index)
487{
488 NWidgetCore *widget = this->GetWidget<NWidgetCore>(widget_index);
489 assert(widget != nullptr); /* Setting focus to a non-existing widget is a bad idea. */
490
491 if (this->nested_focus != nullptr) {
492 /* Do nothing if widget_index is already focused. */
493 if (widget == this->nested_focus) return false;
494
495 /* Repaint the widget that lost focus. A focused edit box may else leave the caret on the screen. */
496 this->nested_focus->SetDirty(this);
497 if (this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxLostFocus();
498 }
499
500 this->nested_focus = widget;
501 if (this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxGainedFocus();
502 return true;
503}
504
508 void Window::OnFocus()
509{
510 if (this->nested_focus != nullptr && this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxGainedFocus();
511}
512
516 void Window::OnFocusLost(bool)
517{
518 if (this->nested_focus != nullptr && this->nested_focus->type == WWT_EDITBOX) VideoDriver::GetInstance()->EditBoxLostFocus();
519}
520
525 void Window::RaiseButtons(bool autoraise)
526{
527 for (auto &pair : this->widget_lookup) {
528 WidgetType type = pair.second->type;
529 NWidgetCore *wid = dynamic_cast<NWidgetCore *>(pair.second);
530 if (((type & ~WWB_PUSHBUTTON) < WWT_LAST || type == NWID_PUSHBUTTON_DROPDOWN) &&
531 (!autoraise || (type & WWB_PUSHBUTTON) || type == WWT_EDITBOX) && wid->IsLowered()) {
532 wid->SetLowered(false);
533 wid->SetDirty(this);
534 }
535 }
536
537 /* Special widgets without widget index */
538 {
539 NWidgetCore *wid = this->nested_root != nullptr ? dynamic_cast<NWidgetCore *>(this->nested_root->GetWidgetOfType(WWT_DEFSIZEBOX)) : nullptr;
540 if (wid != nullptr) {
541 wid->SetLowered(false);
542 wid->SetDirty(this);
543 }
544 }
545}
546
551 void Window::SetWidgetDirty(WidgetID widget_index) const
552{
553 /* Sometimes this function is called before the window is even fully initialized */
554 auto it = this->widget_lookup.find(widget_index);
555 if (it == std::end(this->widget_lookup)) return;
556
557 it->second->SetDirty(this);
558}
559
565 EventState Window::OnHotkey(int hotkey)
566{
567 if (hotkey < 0) return ES_NOT_HANDLED;
568
569 NWidgetCore *nw = this->GetWidget<NWidgetCore>(hotkey);
570 if (nw == nullptr || nw->IsDisabled()) return ES_NOT_HANDLED;
571
572 if (nw->type == WWT_EDITBOX) {
573 if (this->IsShaded()) return ES_NOT_HANDLED;
574
575 /* Focus editbox */
576 this->SetFocusedWidget(hotkey);
577 SetFocusedWindow(this);
578 } else {
579 /* Click button */
580 this->OnClick(Point(), hotkey, 1);
581 }
582 return ES_HANDLED;
583}
584
590 void Window::HandleButtonClick(WidgetID widget)
591{
592 this->LowerWidget(widget);
593 this->SetTimeout();
594 this->SetWidgetDirty(widget);
595}
596
597static void StartWindowDrag(Window *w);
598static void StartWindowSizing(Window *w, bool to_left);
599
607 static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count)
608{
609 NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y);
610 WidgetType widget_type = (nw != nullptr) ? nw->type : WWT_EMPTY;
611
612 /* Allow dropdown close flag detection to work. */
613 if (nw != nullptr) ClrBit(nw->disp_flags, NDB_DROPDOWN_CLOSED);
614
615 bool focused_widget_changed = false;
616 /* If clicked on a window that previously did not have focus */
617 if (_focused_window != w && // We already have focus, right?
618 (w->window_desc.flags & WDF_NO_FOCUS) == 0 && // Don't lose focus to toolbars
619 widget_type != WWT_CLOSEBOX) { // Don't change focused window if 'X' (close button) was clicked
620 focused_widget_changed = true;
621 SetFocusedWindow(w);
622 }
623
624 if (nw == nullptr) return; // exit if clicked outside of widgets
625
626 /* don't allow any interaction if the button has been disabled */
627 if (nw->IsDisabled()) return;
628
629 WidgetID widget_index = nw->index;
630
631 /* Clicked on a widget that is not disabled.
632 * So unless the clicked widget is the caption bar, change focus to this widget.
633 * Exception: In the OSK we always want the editbox to stay focused. */
634 if (widget_index >= 0 && widget_type != WWT_CAPTION && w->window_class != WC_OSK) {
635 /* focused_widget_changed is 'now' only true if the window this widget
636 * is in gained focus. In that case it must remain true, also if the
637 * local widget focus did not change. As such it's the logical-or of
638 * both changed states.
639 *
640 * If this is not preserved, then the OSK window would be opened when
641 * a user has the edit box focused and then click on another window and
642 * then back again on the edit box (to type some text).
643 */
644 focused_widget_changed |= w->SetFocusedWidget(widget_index);
645 }
646
647 /* Dropdown window of this widget was closed so don't process click this time. */
648 if (HasBit(nw->disp_flags, NDB_DROPDOWN_CLOSED)) return;
649
650 if ((widget_type & ~WWB_PUSHBUTTON) < WWT_LAST && (widget_type & WWB_PUSHBUTTON)) w->HandleButtonClick(widget_index);
651
652 Point pt = { x, y };
653
654 switch (widget_type) {
655 case NWID_VSCROLLBAR:
656 case NWID_HSCROLLBAR:
657 ScrollbarClickHandler(w, nw, x, y);
658 break;
659
660 case WWT_EDITBOX: {
661 QueryString *query = w->GetQueryString(widget_index);
662 if (query != nullptr) query->ClickEditBox(w, pt, widget_index, click_count, focused_widget_changed);
663 break;
664 }
665
666 case WWT_CLOSEBOX: // 'X'
667 w->Close();
668 return;
669
670 case WWT_CAPTION: // 'Title bar'
671 StartWindowDrag(w);
672 return;
673
674 case WWT_RESIZEBOX:
675 /* When the resize widget is on the left size of the window
676 * we assume that that button is used to resize to the left. */
677 StartWindowSizing(w, nw->pos_x < (w->width / 2));
678 nw->SetDirty(w);
679 return;
680
681 case WWT_DEFSIZEBOX: {
682 if (_ctrl_pressed) {
683 w->window_desc.pref_width = w->width;
684 w->window_desc.pref_height = w->height;
685 } else {
686 int16_t def_width = std::max<int16_t>(std::min<int16_t>(w->window_desc.GetDefaultWidth(), _screen.width), w->nested_root->smallest_x);
687 int16_t def_height = std::max<int16_t>(std::min<int16_t>(w->window_desc.GetDefaultHeight(), _screen.height - 50), w->nested_root->smallest_y);
688
689 int dx = (w->resize.step_width == 0) ? 0 : def_width - w->width;
690 int dy = (w->resize.step_height == 0) ? 0 : def_height - w->height;
691 /* dx and dy has to go by step.. calculate it.
692 * The cast to int is necessary else dx/dy are implicitly casted to unsigned int, which won't work. */
693 if (w->resize.step_width > 1) dx -= dx % (int)w->resize.step_width;
694 if (w->resize.step_height > 1) dy -= dy % (int)w->resize.step_height;
695 ResizeWindow(w, dx, dy, false);
696 }
697
698 nw->SetLowered(true);
699 nw->SetDirty(w);
700 w->SetTimeout();
701 break;
702 }
703
704 case WWT_DEBUGBOX:
705 w->ShowNewGRFInspectWindow();
706 break;
707
708 case WWT_SHADEBOX:
709 nw->SetDirty(w);
710 w->SetShaded(!w->IsShaded());
711 return;
712
713 case WWT_STICKYBOX:
714 w->flags ^= WF_STICKY;
715 nw->SetDirty(w);
716 if (_ctrl_pressed) w->window_desc.pref_sticky = (w->flags & WF_STICKY) != 0;
717 return;
718
719 default:
720 break;
721 }
722
723 /* Widget has no index, so the window is not interested in it. */
724 if (widget_index < 0) return;
725
726 /* Check if the widget is highlighted; if so, disable highlight and dispatch an event to the GameScript */
727 if (w->IsWidgetHighlighted(widget_index)) {
728 w->SetWidgetHighlight(widget_index, TC_INVALID);
729 Game::NewEvent(new ScriptEventWindowWidgetClick((ScriptWindow::WindowClass)w->window_class, w->window_number, widget_index));
730 }
731
732 w->OnClick(pt, widget_index, click_count);
733}
734
741 static void DispatchRightClickEvent(Window *w, int x, int y)
742{
743 NWidgetCore *wid = w->nested_root->GetWidgetFromPos(x, y);
744 if (wid == nullptr) return;
745
746 Point pt = { x, y };
747
748 /* No widget to handle, or the window is not interested in it. */
749 if (wid->index >= 0) {
750 if (w->OnRightClick(pt, wid->index)) return;
751 }
752
753 /* Right-click close is enabled and there is a closebox. */
754 if (_settings_client.gui.right_click_wnd_close == RCC_YES && (w->window_desc.flags & WDF_NO_CLOSE) == 0) {
755 w->Close();
756 } else if (_settings_client.gui.right_click_wnd_close == RCC_YES_EXCEPT_STICKY && (w->flags & WF_STICKY) == 0 && (w->window_desc.flags & WDF_NO_CLOSE) == 0) {
757 /* Right-click close is enabled, but excluding sticky windows. */
758 w->Close();
759 } else if (_settings_client.gui.hover_delay_ms == 0 && !w->OnTooltip(pt, wid->index, TCC_RIGHT_CLICK) && wid->tool_tip != 0) {
760 GuiShowTooltips(w, wid->tool_tip, TCC_RIGHT_CLICK);
761 }
762}
763
770 static void DispatchHoverEvent(Window *w, int x, int y)
771{
772 NWidgetCore *wid = w->nested_root->GetWidgetFromPos(x, y);
773
774 /* No widget to handle */
775 if (wid == nullptr) return;
776
777 Point pt = { x, y };
778
779 /* Show the tooltip if there is any */
780 if (!w->OnTooltip(pt, wid->index, TCC_HOVER) && wid->tool_tip != 0) {
781 GuiShowTooltips(w, wid->tool_tip, TCC_HOVER);
782 return;
783 }
784
785 /* Widget has no index, so the window is not interested in it. */
786 if (wid->index < 0) return;
787
788 w->OnHover(pt, wid->index);
789}
790
798 static void DispatchMouseWheelEvent(Window *w, NWidgetCore *nwid, int wheel)
799{
800 if (nwid == nullptr) return;
801
802 /* Using wheel on caption/shade-box shades or unshades the window. */
803 if (nwid->type == WWT_CAPTION || nwid->type == WWT_SHADEBOX) {
804 w->SetShaded(wheel < 0);
805 return;
806 }
807
808 /* Wheeling a vertical scrollbar. */
809 if (nwid->type == NWID_VSCROLLBAR) {
810 NWidgetScrollbar *sb = static_cast<NWidgetScrollbar *>(nwid);
811 if (sb->GetCount() > sb->GetCapacity()) {
812 if (sb->UpdatePosition(wheel)) w->SetDirty();
813 }
814 return;
815 }
816
817 /* Scroll the widget attached to the scrollbar. */
818 Scrollbar *sb = (nwid->scrollbar_index >= 0 ? w->GetScrollbar(nwid->scrollbar_index) : nullptr);
819 if (sb != nullptr && sb->GetCount() > sb->GetCapacity()) {
820 if (sb->UpdatePosition(wheel)) w->SetDirty();
821 }
822}
823
829 static bool MayBeShown(const Window *w)
830{
831 /* If we're not modal, everything is okay. */
832 if (!HasModalProgress()) return true;
833
834 switch (w->window_class) {
835 case WC_MAIN_WINDOW:
836 case WC_MODAL_PROGRESS:
837 case WC_CONFIRM_POPUP_QUERY:
838 return true;
839
840 default:
841 return false;
842 }
843}
844
857 static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom)
858{
859 Window::IteratorToFront it(w);
860 ++it;
861 for (; !it.IsEnd(); ++it) {
862 const Window *v = *it;
863 if (MayBeShown(v) &&
864 right > v->left &&
865 bottom > v->top &&
866 left < v->left + v->width &&
867 top < v->top + v->height) {
868 /* v and rectangle intersect with each other */
869 int x;
870
871 if (left < (x = v->left)) {
872 DrawOverlappedWindow(w, left, top, x, bottom);
873 DrawOverlappedWindow(w, x, top, right, bottom);
874 return;
875 }
876
877 if (right > (x = v->left + v->width)) {
878 DrawOverlappedWindow(w, left, top, x, bottom);
879 DrawOverlappedWindow(w, x, top, right, bottom);
880 return;
881 }
882
883 if (top < (x = v->top)) {
884 DrawOverlappedWindow(w, left, top, right, x);
885 DrawOverlappedWindow(w, left, x, right, bottom);
886 return;
887 }
888
889 if (bottom > (x = v->top + v->height)) {
890 DrawOverlappedWindow(w, left, top, right, x);
891 DrawOverlappedWindow(w, left, x, right, bottom);
892 return;
893 }
894
895 return;
896 }
897 }
898
899 /* Setup blitter, and dispatch a repaint event to window *wz */
900 DrawPixelInfo *dp = _cur_dpi;
901 dp->width = right - left;
902 dp->height = bottom - top;
903 dp->left = left - w->left;
904 dp->top = top - w->top;
905 dp->pitch = _screen.pitch;
906 dp->dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(_screen.dst_ptr, left, top);
907 dp->zoom = ZOOM_LVL_MIN;
908 w->OnPaint();
909}
910
919 void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
920{
921 DrawPixelInfo bk;
922 AutoRestoreBackup dpi_backup(_cur_dpi, &bk);
923
924 for (Window *w : Window::IterateFromBack()) {
925 if (MayBeShown(w) &&
926 right > w->left &&
927 bottom > w->top &&
928 left < w->left + w->width &&
929 top < w->top + w->height) {
930 /* Window w intersects with the rectangle => needs repaint */
931 DrawOverlappedWindow(w, std::max(left, w->left), std::max(top, w->top), std::min(right, w->left + w->width), std::min(bottom, w->top + w->height));
932 }
933 }
934}
935
940 void Window::SetDirty() const
941{
942 AddDirtyBlock(this->left, this->top, this->left + this->width, this->top + this->height);
943}
944
952 void Window::ReInit(int rx, int ry, bool reposition)
953{
954 this->SetDirty(); // Mark whole current window as dirty.
955
956 /* Save current size. */
957 int window_width = this->width * _gui_scale / this->scale;
958 int window_height = this->height * _gui_scale / this->scale;
959 this->scale = _gui_scale;
960
961 this->OnInit();
962 /* Re-initialize window smallest size. */
963 this->nested_root->SetupSmallestSize(this);
964 this->nested_root->AssignSizePosition(ST_SMALLEST, 0, 0, this->nested_root->smallest_x, this->nested_root->smallest_y, _current_text_dir == TD_RTL);
965 this->width = this->nested_root->smallest_x;
966 this->height = this->nested_root->smallest_y;
967 this->resize.step_width = this->nested_root->resize_x;
968 this->resize.step_height = this->nested_root->resize_y;
969
970 /* Resize as close to the original size + requested resize as possible. */
971 window_width = std::max(window_width + rx, this->width);
972 window_height = std::max(window_height + ry, this->height);
973 int dx = (this->resize.step_width == 0) ? 0 : window_width - this->width;
974 int dy = (this->resize.step_height == 0) ? 0 : window_height - this->height;
975 /* dx and dy has to go by step.. calculate it.
976 * The cast to int is necessary else dx/dy are implicitly casted to unsigned int, which won't work. */
977 if (this->resize.step_width > 1) dx -= dx % (int)this->resize.step_width;
978 if (this->resize.step_height > 1) dy -= dy % (int)this->resize.step_height;
979
980 if (reposition) {
981 Point pt = this->OnInitialPosition(this->nested_root->smallest_x, this->nested_root->smallest_y, window_number);
982 this->InitializePositionSize(pt.x, pt.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
983 this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight());
984 }
985
986 ResizeWindow(this, dx, dy, true, false);
987 /* ResizeWindow() does this->SetDirty() already, no need to do it again here. */
988}
989
995 void Window::SetShaded(bool make_shaded)
996{
997 if (this->shade_select == nullptr) return;
998
999 int desired = make_shaded ? SZSP_HORIZONTAL : 0;
1000 if (this->shade_select->shown_plane != desired) {
1001 if (make_shaded) {
1002 if (this->nested_focus != nullptr) this->UnfocusFocusedWidget();
1003 this->unshaded_size.width = this->width;
1004 this->unshaded_size.height = this->height;
1005 this->shade_select->SetDisplayedPlane(desired);
1006 this->ReInit(0, -this->height);
1007 } else {
1008 this->shade_select->SetDisplayedPlane(desired);
1009 int dx = ((int)this->unshaded_size.width > this->width) ? (int)this->unshaded_size.width - this->width : 0;
1010 int dy = ((int)this->unshaded_size.height > this->height) ? (int)this->unshaded_size.height - this->height : 0;
1011 this->ReInit(dx, dy);
1012 }
1013 }
1014}
1015
1022 Window *Window::FindChildWindow(WindowClass wc) const
1023{
1024 for (Window *v : Window::Iterate()) {
1025 if ((wc == WC_INVALID || wc == v->window_class) && v->parent == this) return v;
1026 }
1027
1028 return nullptr;
1029}
1030
1035 void Window::CloseChildWindows(WindowClass wc) const
1036{
1037 Window *child = this->FindChildWindow(wc);
1038 while (child != nullptr) {
1039 child->Close();
1040 child = this->FindChildWindow(wc);
1041 }
1042}
1043
1047 void Window::Close([[maybe_unused]] int data)
1048{
1049 /* Don't close twice. */
1050 if (*this->z_position == nullptr) return;
1051
1052 *this->z_position = nullptr;
1053
1054 if (_thd.window_class == this->window_class &&
1055 _thd.window_number == this->window_number) {
1056 ResetObjectToPlace();
1057 }
1058
1059 /* Prevent Mouseover() from resetting mouse-over coordinates on a non-existing window */
1060 if (_mouseover_last_w == this) _mouseover_last_w = nullptr;
1061
1062 /* We can't scroll the window when it's closed. */
1063 if (_last_scroll_window == this) _last_scroll_window = nullptr;
1064
1065 /* Make sure we don't try to access non-existing query strings. */
1066 this->querystrings.clear();
1067
1068 /* Make sure we don't try to access this window as the focused window when it doesn't exist anymore. */
1069 if (_focused_window == this) {
1070 this->OnFocusLost(true);
1071 _focused_window = nullptr;
1072 }
1073
1074 this->CloseChildWindows();
1075
1076 this->SetDirty();
1077
1078 Window::closed_windows.push_back(this);
1079}
1080
1084Window::~Window()
1085{
1086 /* Make sure the window is closed, deletion is allowed only in Window::DeleteClosedWindows(). */
1087 assert(*this->z_position == nullptr);
1088
1089 if (this->viewport != nullptr) DeleteWindowViewport(this);
1090}
1091
1098 Window *FindWindowById(WindowClass cls, WindowNumber number)
1099{
1100 for (Window *w : Window::Iterate()) {
1101 if (w->window_class == cls && w->window_number == number) return w;
1102 }
1103
1104 return nullptr;
1105}
1106
1113 Window *FindWindowByClass(WindowClass cls)
1114{
1115 for (Window *w : Window::Iterate()) {
1116 if (w->window_class == cls) return w;
1117 }
1118
1119 return nullptr;
1120}
1121
1127 Window *GetMainWindow()
1128{
1129 Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
1130 assert(w != nullptr);
1131 return w;
1132}
1133
1140 void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
1141{
1142 Window *w = FindWindowById(cls, number);
1143 if (w != nullptr && (force || (w->flags & WF_STICKY) == 0)) {
1144 w->Close(data);
1145 }
1146}
1147
1152 void CloseWindowByClass(WindowClass cls, int data)
1153{
1154 /* Note: the container remains stable, even when deleting windows. */
1155 for (Window *w : Window::Iterate()) {
1156 if (w->window_class == cls) {
1157 w->Close(data);
1158 }
1159 }
1160}
1161
1168 void CloseCompanyWindows(CompanyID id)
1169{
1170 /* Note: the container remains stable, even when deleting windows. */
1171 for (Window *w : Window::Iterate()) {
1172 if (w->owner == id) {
1173 w->Close();
1174 }
1175 }
1176
1177 /* Also delete the company specific windows that don't have a company-colour. */
1178 CloseWindowById(WC_BUY_COMPANY, id);
1179}
1180
1188 void ChangeWindowOwner(Owner old_owner, Owner new_owner)
1189{
1190 for (Window *w : Window::Iterate()) {
1191 if (w->owner != old_owner) continue;
1192
1193 switch (w->window_class) {
1194 case WC_COMPANY_COLOUR:
1195 case WC_FINANCES:
1196 case WC_STATION_LIST:
1197 case WC_TRAINS_LIST:
1198 case WC_ROADVEH_LIST:
1199 case WC_SHIPS_LIST:
1200 case WC_AIRCRAFT_LIST:
1201 case WC_BUY_COMPANY:
1202 case WC_COMPANY:
1203 case WC_COMPANY_INFRASTRUCTURE:
1204 case WC_VEHICLE_ORDERS: // Changing owner would also require changing WindowDesc, which is not possible; however keeping the old one crashes because of missing widgets etc.. See ShowOrdersWindow().
1205 continue;
1206
1207 default:
1208 w->owner = new_owner;
1209 break;
1210 }
1211 }
1212}
1213
1214static void BringWindowToFront(Window *w, bool dirty = true);
1215
1223 Window *BringWindowToFrontById(WindowClass cls, WindowNumber number)
1224{
1225 Window *w = FindWindowById(cls, number);
1226
1227 if (w != nullptr) {
1228 if (w->IsShaded()) w->SetShaded(false); // Restore original window size if it was shaded.
1229
1230 w->SetWhiteBorder();
1231 BringWindowToFront(w);
1232 w->SetDirty();
1233 }
1234
1235 return w;
1236}
1237
1238static inline bool IsVitalWindow(const Window *w)
1239{
1240 switch (w->window_class) {
1241 case WC_MAIN_TOOLBAR:
1242 case WC_STATUS_BAR:
1243 case WC_NEWS_WINDOW:
1244 case WC_SEND_NETWORK_MSG:
1245 return true;
1246
1247 default:
1248 return false;
1249 }
1250}
1251
1260 static uint GetWindowZPriority(WindowClass wc)
1261{
1262 assert(wc != WC_INVALID);
1263
1264 uint z_priority = 0;
1265
1266 switch (wc) {
1267 case WC_TOOLTIPS:
1268 ++z_priority;
1269 [[fallthrough]];
1270
1271 case WC_ERRMSG:
1272 case WC_CONFIRM_POPUP_QUERY:
1273 ++z_priority;
1274 [[fallthrough]];
1275
1276 case WC_ENDSCREEN:
1277 ++z_priority;
1278 [[fallthrough]];
1279
1280 case WC_HIGHSCORE:
1281 ++z_priority;
1282 [[fallthrough]];
1283
1284 case WC_DROPDOWN_MENU:
1285 ++z_priority;
1286 [[fallthrough]];
1287
1288 case WC_MAIN_TOOLBAR:
1289 case WC_STATUS_BAR:
1290 ++z_priority;
1291 [[fallthrough]];
1292
1293 case WC_OSK:
1294 ++z_priority;
1295 [[fallthrough]];
1296
1297 case WC_QUERY_STRING:
1298 case WC_SEND_NETWORK_MSG:
1299 ++z_priority;
1300 [[fallthrough]];
1301
1302 case WC_NETWORK_ASK_RELAY:
1303 case WC_MODAL_PROGRESS:
1304 case WC_NETWORK_STATUS_WINDOW:
1305 case WC_SAVE_PRESET:
1306 ++z_priority;
1307 [[fallthrough]];
1308
1309 case WC_GENERATE_LANDSCAPE:
1310 case WC_SAVELOAD:
1311 case WC_GAME_OPTIONS:
1312 case WC_CUSTOM_CURRENCY:
1313 case WC_NETWORK_WINDOW:
1314 case WC_GRF_PARAMETERS:
1315 case WC_SCRIPT_LIST:
1316 case WC_SCRIPT_SETTINGS:
1317 case WC_TEXTFILE:
1318 ++z_priority;
1319 [[fallthrough]];
1320
1321 case WC_CONSOLE:
1322 ++z_priority;
1323 [[fallthrough]];
1324
1325 case WC_NEWS_WINDOW:
1326 ++z_priority;
1327 [[fallthrough]];
1328
1329 default:
1330 ++z_priority;
1331 [[fallthrough]];
1332
1333 case WC_MAIN_WINDOW:
1334 return z_priority;
1335 }
1336}
1337
1344 static void BringWindowToFront(Window *w, bool dirty)
1345{
1346 auto priority = GetWindowZPriority(w->window_class);
1347 WindowList::iterator dest = _z_windows.begin();
1348 while (dest != _z_windows.end() && (*dest == nullptr || GetWindowZPriority((*dest)->window_class) <= priority)) ++dest;
1349
1350 if (dest != w->z_position) {
1351 _z_windows.splice(dest, _z_windows, w->z_position);
1352 }
1353
1354 if (dirty) w->SetDirty();
1355}
1356
1364 void Window::InitializeData(WindowNumber window_number)
1365{
1366 /* Set up window properties; some of them are needed to set up smallest size below */
1367 this->window_class = this->window_desc.cls;
1368 this->SetWhiteBorder();
1369 if (this->window_desc.default_pos == WDP_CENTER) this->flags |= WF_CENTERED;
1370 this->owner = INVALID_OWNER;
1371 this->nested_focus = nullptr;
1372 this->window_number = window_number;
1373
1374 this->OnInit();
1375 /* Initialize smallest size. */
1376 this->nested_root->SetupSmallestSize(this);
1377 /* Initialize to smallest size. */
1378 this->nested_root->AssignSizePosition(ST_SMALLEST, 0, 0, this->nested_root->smallest_x, this->nested_root->smallest_y, _current_text_dir == TD_RTL);
1379
1380 /* Further set up window properties,
1381 * this->left, this->top, this->width, this->height, this->resize.width, and this->resize.height are initialized later. */
1382 this->resize.step_width = this->nested_root->resize_x;
1383 this->resize.step_height = this->nested_root->resize_y;
1384
1385 /* Give focus to the opened window unless a dropdown menu has focus or a text box of the focused window has focus
1386 * (so we don't interrupt typing) unless the new window has a text box. */
1387 bool dropdown_active = _focused_window != nullptr && _focused_window->window_class == WC_DROPDOWN_MENU;
1388 bool editbox_active = EditBoxInGlobalFocus() && this->nested_root->GetWidgetOfType(WWT_EDITBOX) == nullptr;
1389 if (!dropdown_active && !editbox_active) SetFocusedWindow(this);
1390
1391 /* Insert the window into the correct location in the z-ordering. */
1392 BringWindowToFront(this, false);
1393}
1394
1402 void Window::InitializePositionSize(int x, int y, int sm_width, int sm_height)
1403{
1404 this->left = x;
1405 this->top = y;
1406 this->width = sm_width;
1407 this->height = sm_height;
1408}
1409
1420 void Window::FindWindowPlacementAndResize(int def_width, int def_height)
1421{
1422 def_width = std::max(def_width, this->width); // Don't allow default size to be smaller than smallest size
1423 def_height = std::max(def_height, this->height);
1424 /* Try to make windows smaller when our window is too small.
1425 * w->(width|height) is normally the same as min_(width|height),
1426 * but this way the GUIs can be made a little more dynamic;
1427 * one can use the same spec for multiple windows and those
1428 * can then determine the real minimum size of the window. */
1429 if (this->width != def_width || this->height != def_height) {
1430 /* Think about the overlapping toolbars when determining the minimum window size */
1431 int free_height = _screen.height;
1432 const Window *wt = FindWindowById(WC_STATUS_BAR, 0);
1433 if (wt != nullptr) free_height -= wt->height;
1434 wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
1435 if (wt != nullptr) free_height -= wt->height;
1436
1437 int enlarge_x = std::max(std::min(def_width - this->width, _screen.width - this->width), 0);
1438 int enlarge_y = std::max(std::min(def_height - this->height, free_height - this->height), 0);
1439
1440 /* X and Y has to go by step.. calculate it.
1441 * The cast to int is necessary else x/y are implicitly casted to
1442 * unsigned int, which won't work. */
1443 if (this->resize.step_width > 1) enlarge_x -= enlarge_x % (int)this->resize.step_width;
1444 if (this->resize.step_height > 1) enlarge_y -= enlarge_y % (int)this->resize.step_height;
1445
1446 ResizeWindow(this, enlarge_x, enlarge_y, true, false);
1447 /* ResizeWindow() calls this->OnResize(). */
1448 } else {
1449 /* Always call OnResize; that way the scrollbars and matrices get initialized. */
1450 this->OnResize();
1451 }
1452
1453 int nx = this->left;
1454 int ny = this->top;
1455
1456 if (nx + this->width > _screen.width) nx -= (nx + this->width - _screen.width);
1457
1458 const Window *wt = FindWindowById(WC_MAIN_TOOLBAR, 0);
1459 ny = std::max(ny, (wt == nullptr || this == wt || this->top == 0) ? 0 : wt->height);
1460 nx = std::max(nx, 0);
1461
1462 if (this->viewport != nullptr) {
1463 this->viewport->left += nx - this->left;
1464 this->viewport->top += ny - this->top;
1465 }
1466 this->left = nx;
1467 this->top = ny;
1468
1469 this->SetDirty();
1470}
1471
1484 static bool IsGoodAutoPlace1(int left, int top, int width, int height, int toolbar_y, Point &pos)
1485{
1486 int right = width + left;
1487 int bottom = height + top;
1488
1489 if (left < 0 || top < toolbar_y || right > _screen.width || bottom > _screen.height) return false;
1490
1491 /* Make sure it is not obscured by any window. */
1492 for (const Window *w : Window::Iterate()) {
1493 if (w->window_class == WC_MAIN_WINDOW) continue;
1494
1495 if (right > w->left &&
1496 w->left + w->width > left &&
1497 bottom > w->top &&
1498 w->top + w->height > top) {
1499 return false;
1500 }
1501 }
1502
1503 pos.x = left;
1504 pos.y = top;
1505 return true;
1506}
1507
1520 static bool IsGoodAutoPlace2(int left, int top, int width, int height, int toolbar_y, Point &pos)
1521{
1522 bool rtl = _current_text_dir == TD_RTL;
1523
1524 /* Left part of the rectangle may be at most 1/4 off-screen,
1525 * right part of the rectangle may be at most 1/2 off-screen
1526 */
1527 if (rtl) {
1528 if (left < -(width >> 1) || left > _screen.width - (width >> 2)) return false;
1529 } else {
1530 if (left < -(width >> 2) || left > _screen.width - (width >> 1)) return false;
1531 }
1532
1533 /* Bottom part of the rectangle may be at most 1/4 off-screen */
1534 if (top < toolbar_y || top > _screen.height - (height >> 2)) return false;
1535
1536 /* Make sure it is not obscured by any window. */
1537 for (const Window *w : Window::Iterate()) {
1538 if (w->window_class == WC_MAIN_WINDOW) continue;
1539
1540 if (left + width > w->left &&
1541 w->left + w->width > left &&
1542 top + height > w->top &&
1543 w->top + w->height > top) {
1544 return false;
1545 }
1546 }
1547
1548 pos.x = left;
1549 pos.y = top;
1550 return true;
1551}
1552
1559 static Point GetAutoPlacePosition(int width, int height)
1560{
1561 Point pt;
1562
1563 bool rtl = _current_text_dir == TD_RTL;
1564
1565 /* First attempt, try top-left of the screen */
1566 const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR);
1567 const int toolbar_y = main_toolbar != nullptr ? main_toolbar->height : 0;
1568 if (IsGoodAutoPlace1(rtl ? _screen.width - width : 0, toolbar_y, width, height, toolbar_y, pt)) return pt;
1569
1570 /* Second attempt, try around all existing windows.
1571 * The new window must be entirely on-screen, and not overlap with an existing window.
1572 * Eight starting points are tried, two at each corner.
1573 */
1574 for (const Window *w : Window::Iterate()) {
1575 if (w->window_class == WC_MAIN_WINDOW) continue;
1576
1577 if (IsGoodAutoPlace1(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt;
1578 if (IsGoodAutoPlace1(w->left - width, w->top, width, height, toolbar_y, pt)) return pt;
1579 if (IsGoodAutoPlace1(w->left, w->top + w->height, width, height, toolbar_y, pt)) return pt;
1580 if (IsGoodAutoPlace1(w->left, w->top - height, width, height, toolbar_y, pt)) return pt;
1581 if (IsGoodAutoPlace1(w->left + w->width, w->top + w->height - height, width, height, toolbar_y, pt)) return pt;
1582 if (IsGoodAutoPlace1(w->left - width, w->top + w->height - height, width, height, toolbar_y, pt)) return pt;
1583 if (IsGoodAutoPlace1(w->left + w->width - width, w->top + w->height, width, height, toolbar_y, pt)) return pt;
1584 if (IsGoodAutoPlace1(w->left + w->width - width, w->top - height, width, height, toolbar_y, pt)) return pt;
1585 }
1586
1587 /* Third attempt, try around all existing windows.
1588 * The new window may be partly off-screen, and must not overlap with an existing window.
1589 * Only four starting points are tried.
1590 */
1591 for (const Window *w : Window::Iterate()) {
1592 if (w->window_class == WC_MAIN_WINDOW) continue;
1593
1594 if (IsGoodAutoPlace2(w->left + w->width, w->top, width, height, toolbar_y, pt)) return pt;
1595 if (IsGoodAutoPlace2(w->left - width, w->top, width, height, toolbar_y, pt)) return pt;
1596 if (IsGoodAutoPlace2(w->left, w->top + w->height, width, height, toolbar_y, pt)) return pt;
1597 if (IsGoodAutoPlace2(w->left, w->top - height, width, height, toolbar_y, pt)) return pt;
1598 }
1599
1600 /* Fourth and final attempt, put window at diagonal starting from (0, toolbar_y), try multiples
1601 * of the closebox
1602 */
1603 int left = rtl ? _screen.width - width : 0, top = toolbar_y;
1604 int offset_x = rtl ? -(int)NWidgetLeaf::closebox_dimension.width : (int)NWidgetLeaf::closebox_dimension.width;
1605 int offset_y = std::max<int>(NWidgetLeaf::closebox_dimension.height, GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.captiontext.Vertical());
1606
1607restart:
1608 for (const Window *w : Window::Iterate()) {
1609 if (w->left == left && w->top == top) {
1610 left += offset_x;
1611 top += offset_y;
1612 goto restart;
1613 }
1614 }
1615
1616 pt.x = left;
1617 pt.y = top;
1618 return pt;
1619}
1620
1627 Point GetToolbarAlignedWindowPosition(int window_width)
1628{
1629 const Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
1630 assert(w != nullptr);
1631 Point pt = { _current_text_dir == TD_RTL ? w->left : (w->left + w->width) - window_width, w->top + w->height };
1632 return pt;
1633}
1634
1652 static Point LocalGetWindowPlacement(const WindowDesc &desc, int16_t sm_width, int16_t sm_height, int window_number)
1653{
1654 Point pt;
1655 const Window *w;
1656
1657 int16_t default_width = std::max(desc.GetDefaultWidth(), sm_width);
1658 int16_t default_height = std::max(desc.GetDefaultHeight(), sm_height);
1659
1660 if (desc.parent_cls != WC_NONE && (w = FindWindowById(desc.parent_cls, window_number)) != nullptr) {
1661 bool rtl = _current_text_dir == TD_RTL;
1662 if (desc.parent_cls == WC_BUILD_TOOLBAR || desc.parent_cls == WC_SCEN_LAND_GEN) {
1663 pt.x = w->left + (rtl ? w->width - default_width : 0);
1664 pt.y = w->top + w->height;
1665 return pt;
1666 } else {
1667 /* Position child window with offset of closebox, but make sure that either closebox or resizebox is visible
1668 * - Y position: closebox of parent + closebox of child + statusbar
1669 * - X position: closebox on left/right, resizebox on right/left (depending on ltr/rtl)
1670 */
1671 int indent_y = std::max<int>(NWidgetLeaf::closebox_dimension.height, GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.captiontext.Vertical());
1672 if (w->top + 3 * indent_y < _screen.height) {
1673 pt.y = w->top + indent_y;
1674 int indent_close = NWidgetLeaf::closebox_dimension.width;
1675 int indent_resize = NWidgetLeaf::resizebox_dimension.width;
1676 if (_current_text_dir == TD_RTL) {
1677 pt.x = std::max(w->left + w->width - default_width - indent_close, 0);
1678 if (pt.x + default_width >= indent_close && pt.x + indent_resize <= _screen.width) return pt;
1679 } else {
1680 pt.x = std::min(w->left + indent_close, _screen.width - default_width);
1681 if (pt.x + default_width >= indent_resize && pt.x + indent_close <= _screen.width) return pt;
1682 }
1683 }
1684 }
1685 }
1686
1687 switch (desc.default_pos) {
1688 case WDP_ALIGN_TOOLBAR: // Align to the toolbar
1689 return GetToolbarAlignedWindowPosition(default_width);
1690
1691 case WDP_AUTO: // Find a good automatic position for the window
1692 return GetAutoPlacePosition(default_width, default_height);
1693
1694 case WDP_CENTER: // Centre the window horizontally
1695 pt.x = (_screen.width - default_width) / 2;
1696 pt.y = (_screen.height - default_height) / 2;
1697 break;
1698
1699 case WDP_MANUAL:
1700 pt.x = 0;
1701 pt.y = 0;
1702 break;
1703
1704 default:
1705 NOT_REACHED();
1706 }
1707
1708 return pt;
1709}
1710
1711/* virtual */ Point Window::OnInitialPosition([[maybe_unused]]int16_t sm_width, [[maybe_unused]]int16_t sm_height, [[maybe_unused]]int window_number)
1712{
1713 return LocalGetWindowPlacement(this->window_desc, sm_width, sm_height, window_number);
1714}
1715
1723 void Window::CreateNestedTree()
1724{
1725 this->nested_root = MakeWindowNWidgetTree(this->window_desc.nwid_parts, &this->shade_select);
1726 this->nested_root->FillWidgetLookup(this->widget_lookup);
1727}
1728
1733 void Window::FinishInitNested(WindowNumber window_number)
1734{
1735 this->InitializeData(window_number);
1736 this->ApplyDefaults();
1737 Point pt = this->OnInitialPosition(this->nested_root->smallest_x, this->nested_root->smallest_y, window_number);
1738 this->InitializePositionSize(pt.x, pt.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
1739 this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight());
1740}
1741
1746 void Window::InitNested(WindowNumber window_number)
1747{
1748 this->CreateNestedTree();
1749 this->FinishInitNested(window_number);
1750}
1751
1756Window::Window(WindowDesc &desc) : window_desc(desc), scale(_gui_scale), mouse_capture_widget(-1)
1757{
1758 this->z_position = _z_windows.insert(_z_windows.end(), this);
1759}
1760
1768 Window *FindWindowFromPt(int x, int y)
1769{
1770 for (Window *w : Window::IterateFromFront()) {
1771 if (MayBeShown(w) && IsInsideBS(x, w->left, w->width) && IsInsideBS(y, w->top, w->height)) {
1772 return w;
1773 }
1774 }
1775
1776 return nullptr;
1777}
1778
1782 void InitWindowSystem()
1783{
1784 IConsoleClose();
1785
1786 _focused_window = nullptr;
1787 _mouseover_last_w = nullptr;
1788 _last_scroll_window = nullptr;
1789 _scrolling_viewport = false;
1790 _mouse_hovering = false;
1791
1792 SetupWidgetDimensions();
1793 NWidgetLeaf::InvalidateDimensionCache(); // Reset cached sizes of several widgets.
1794 NWidgetScrollbar::InvalidateDimensionCache();
1795
1796 InitDepotWindowBlockSizes();
1797
1798 ShowFirstError();
1799}
1800
1804 void UnInitWindowSystem()
1805{
1806 UnshowCriticalError();
1807
1808 for (Window *w : Window::Iterate()) w->Close();
1809
1810 Window::DeleteClosedWindows();
1811
1812 assert(_z_windows.empty());
1813}
1814
1818 void ResetWindowSystem()
1819{
1820 UnInitWindowSystem();
1821 InitWindowSystem();
1822 _thd.Reset();
1823}
1824
1825static void DecreaseWindowCounters()
1826{
1827 if (_scroller_click_timeout != 0) _scroller_click_timeout--;
1828
1829 for (Window *w : Window::Iterate()) {
1830 if (_scroller_click_timeout == 0) {
1831 /* Unclick scrollbar buttons if they are pressed. */
1832 for (auto &pair : w->widget_lookup) {
1833 NWidgetBase *nwid = pair.second;
1834 if (nwid->type == NWID_HSCROLLBAR || nwid->type == NWID_VSCROLLBAR) {
1835 NWidgetScrollbar *sb = static_cast<NWidgetScrollbar*>(nwid);
1836 if (sb->disp_flags & (ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN)) {
1837 sb->disp_flags &= ~(ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN);
1838 w->mouse_capture_widget = -1;
1839 sb->SetDirty(w);
1840 }
1841 }
1842 }
1843 }
1844
1845 /* Handle editboxes */
1846 for (auto &pair : w->querystrings) {
1847 pair.second->HandleEditBox(w, pair.first);
1848 }
1849
1850 w->OnMouseLoop();
1851 }
1852
1853 for (Window *w : Window::Iterate()) {
1854 if ((w->flags & WF_TIMEOUT) && --w->timeout_timer == 0) {
1855 CLRBITS(w->flags, WF_TIMEOUT);
1856
1857 w->OnTimeout();
1858 w->RaiseButtons(true);
1859 }
1860 }
1861}
1862
1863static void HandlePlacePresize()
1864{
1865 if (_special_mouse_mode != WSM_PRESIZE) return;
1866
1867 Window *w = _thd.GetCallbackWnd();
1868 if (w == nullptr) return;
1869
1870 Point pt = GetTileBelowCursor();
1871 if (pt.x == -1) {
1872 _thd.selend.x = -1;
1873 return;
1874 }
1875
1876 w->OnPlacePresize(pt, TileVirtXY(pt.x, pt.y));
1877}
1878
1883 static EventState HandleMouseDragDrop()
1884{
1885 if (_special_mouse_mode != WSM_DRAGDROP) return ES_NOT_HANDLED;
1886
1887 if (_left_button_down && _cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED; // Dragging, but the mouse did not move.
1888
1889 Window *w = _thd.GetCallbackWnd();
1890 if (w != nullptr) {
1891 /* Send an event in client coordinates. */
1892 Point pt;
1893 pt.x = _cursor.pos.x - w->left;
1894 pt.y = _cursor.pos.y - w->top;
1895 if (_left_button_down) {
1896 w->OnMouseDrag(pt, GetWidgetFromPos(w, pt.x, pt.y));
1897 } else {
1898 w->OnDragDrop(pt, GetWidgetFromPos(w, pt.x, pt.y));
1899 }
1900 }
1901
1902 if (!_left_button_down) ResetObjectToPlace(); // Button released, finished dragging.
1903 return ES_HANDLED;
1904}
1905
1907 static void HandleMouseOver()
1908{
1909 Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
1910
1911 /* We changed window, put an OnMouseOver event to the last window */
1912 if (_mouseover_last_w != nullptr && _mouseover_last_w != w) {
1913 /* Reset mouse-over coordinates of previous window */
1914 Point pt = { -1, -1 };
1915 _mouseover_last_w->OnMouseOver(pt, 0);
1916 }
1917
1918 /* _mouseover_last_w will get reset when the window is deleted, see DeleteWindow() */
1919 _mouseover_last_w = w;
1920
1921 if (w != nullptr) {
1922 /* send an event in client coordinates. */
1923 Point pt = { _cursor.pos.x - w->left, _cursor.pos.y - w->top };
1924 const NWidgetCore *widget = w->nested_root->GetWidgetFromPos(pt.x, pt.y);
1925 if (widget != nullptr) w->OnMouseOver(pt, widget->index);
1926 }
1927}
1928
1930 enum PreventHideDirection {
1931 PHD_UP,
1932 PHD_DOWN,
1933};
1934
1945 static void PreventHiding(int *nx, int *ny, const Rect &rect, const Window *v, int px, PreventHideDirection dir)
1946{
1947 if (v == nullptr) return;
1948
1949 const int min_visible = rect.Height();
1950
1951 int v_bottom = v->top + v->height - 1;
1952 int v_right = v->left + v->width - 1;
1953 int safe_y = (dir == PHD_UP) ? (v->top - min_visible - rect.top) : (v_bottom + min_visible - rect.bottom); // Compute safe vertical position.
1954
1955 if (*ny + rect.top <= v->top - min_visible) return; // Above v is enough space
1956 if (*ny + rect.bottom >= v_bottom + min_visible) return; // Below v is enough space
1957
1958 /* Vertically, the rectangle is hidden behind v. */
1959 if (*nx + rect.left + min_visible < v->left) { // At left of v.
1960 if (v->left < min_visible) *ny = safe_y; // But enough room, force it to a safe position.
1961 return;
1962 }
1963 if (*nx + rect.right - min_visible > v_right) { // At right of v.
1964 if (v_right > _screen.width - min_visible) *ny = safe_y; // Not enough room, force it to a safe position.
1965 return;
1966 }
1967
1968 /* Horizontally also hidden, force movement to a safe area. */
1969 if (px + rect.left < v->left && v->left >= min_visible) { // Coming from the left, and enough room there.
1970 *nx = v->left - min_visible - rect.left;
1971 } else if (px + rect.right > v_right && v_right <= _screen.width - min_visible) { // Coming from the right, and enough room there.
1972 *nx = v_right + min_visible - rect.right;
1973 } else {
1974 *ny = safe_y;
1975 }
1976}
1977
1985 static void EnsureVisibleCaption(Window *w, int nx, int ny)
1986{
1987 /* Search for the title bar rectangle. */
1988 const NWidgetBase *caption = w->nested_root->GetWidgetOfType(WWT_CAPTION);
1989 if (caption != nullptr) {
1990 const Rect caption_rect = caption->GetCurrentRect();
1991
1992 const int min_visible = caption_rect.Height();
1993
1994 /* Make sure the window doesn't leave the screen */
1995 nx = Clamp(nx, min_visible - caption_rect.right, _screen.width - min_visible - caption_rect.left);
1996 ny = Clamp(ny, 0, _screen.height - min_visible);
1997
1998 /* Make sure the title bar isn't hidden behind the main tool bar or the status bar. */
1999 PreventHiding(&nx, &ny, caption_rect, FindWindowById(WC_MAIN_TOOLBAR, 0), w->left, PHD_DOWN);
2000 PreventHiding(&nx, &ny, caption_rect, FindWindowById(WC_STATUS_BAR, 0), w->left, PHD_UP);
2001 }
2002
2003 if (w->viewport != nullptr) {
2004 w->viewport->left += nx - w->left;
2005 w->viewport->top += ny - w->top;
2006 }
2007
2008 w->left = nx;
2009 w->top = ny;
2010}
2011
2022 void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen, bool schedule_resize)
2023{
2024 if (delta_x != 0 || delta_y != 0) {
2025 if (clamp_to_screen) {
2026 /* Determine the new right/bottom position. If that is outside of the bounds of
2027 * the resolution clamp it in such a manner that it stays within the bounds. */
2028 int new_right = w->left + w->width + delta_x;
2029 int new_bottom = w->top + w->height + delta_y;
2030 if (new_right >= (int)_screen.width) delta_x -= Ceil(new_right - _screen.width, std::max(1U, w->nested_root->resize_x));
2031 if (new_bottom >= (int)_screen.height) delta_y -= Ceil(new_bottom - _screen.height, std::max(1U, w->nested_root->resize_y));
2032 }
2033
2034 w->SetDirty();
2035
2036 uint new_xinc = std::max(0, (w->nested_root->resize_x == 0) ? 0 : (int)(w->nested_root->current_x - w->nested_root->smallest_x) + delta_x);
2037 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);
2038 assert(w->nested_root->resize_x == 0 || new_xinc % w->nested_root->resize_x == 0);
2039 assert(w->nested_root->resize_y == 0 || new_yinc % w->nested_root->resize_y == 0);
2040
2041 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);
2042 w->width = w->nested_root->current_x;
2043 w->height = w->nested_root->current_y;
2044 }
2045
2046 EnsureVisibleCaption(w, w->left, w->top);
2047
2048 /* Schedule OnResize to make sure everything is initialised correctly if it needs to be. */
2049 if (schedule_resize) {
2050 w->ScheduleResize();
2051 } else {
2052 w->OnResize();
2053 }
2054 w->SetDirty();
2055}
2056
2062 int GetMainViewTop()
2063{
2064 Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
2065 return (w == nullptr) ? 0 : w->top + w->height;
2066}
2067
2073 int GetMainViewBottom()
2074{
2075 Window *w = FindWindowById(WC_STATUS_BAR, 0);
2076 return (w == nullptr) ? _screen.height : w->top;
2077}
2078
2079 static bool _dragging_window;
2080
2085 static EventState HandleWindowDragging()
2086{
2087 /* Get out immediately if no window is being dragged at all. */
2088 if (!_dragging_window) return ES_NOT_HANDLED;
2089
2090 /* If button still down, but cursor hasn't moved, there is nothing to do. */
2091 if (_left_button_down && _cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED;
2092
2093 /* Otherwise find the window... */
2094 for (Window *w : Window::Iterate()) {
2095 if (w->flags & WF_DRAGGING) {
2096 /* Stop the dragging if the left mouse button was released */
2097 if (!_left_button_down) {
2098 w->flags &= ~WF_DRAGGING;
2099 break;
2100 }
2101
2102 w->SetDirty();
2103
2104 int x = _cursor.pos.x + _drag_delta.x;
2105 int y = _cursor.pos.y + _drag_delta.y;
2106 int nx = x;
2107 int ny = y;
2108
2109 if (_settings_client.gui.window_snap_radius != 0) {
2110 int hsnap = _settings_client.gui.window_snap_radius;
2111 int vsnap = _settings_client.gui.window_snap_radius;
2112 int delta;
2113
2114 for (const Window *v : Window::Iterate()) {
2115 if (v == w) continue; // Don't snap at yourself
2116
2117 if (y + w->height > v->top && y < v->top + v->height) {
2118 /* Your left border <-> other right border */
2119 delta = abs(v->left + v->width - x);
2120 if (delta <= hsnap) {
2121 nx = v->left + v->width;
2122 hsnap = delta;
2123 }
2124
2125 /* Your right border <-> other left border */
2126 delta = abs(v->left - x - w->width);
2127 if (delta <= hsnap) {
2128 nx = v->left - w->width;
2129 hsnap = delta;
2130 }
2131 }
2132
2133 if (w->top + w->height >= v->top && w->top <= v->top + v->height) {
2134 /* Your left border <-> other left border */
2135 delta = abs(v->left - x);
2136 if (delta <= hsnap) {
2137 nx = v->left;
2138 hsnap = delta;
2139 }
2140
2141 /* Your right border <-> other right border */
2142 delta = abs(v->left + v->width - x - w->width);
2143 if (delta <= hsnap) {
2144 nx = v->left + v->width - w->width;
2145 hsnap = delta;
2146 }
2147 }
2148
2149 if (x + w->width > v->left && x < v->left + v->width) {
2150 /* Your top border <-> other bottom border */
2151 delta = abs(v->top + v->height - y);
2152 if (delta <= vsnap) {
2153 ny = v->top + v->height;
2154 vsnap = delta;
2155 }
2156
2157 /* Your bottom border <-> other top border */
2158 delta = abs(v->top - y - w->height);
2159 if (delta <= vsnap) {
2160 ny = v->top - w->height;
2161 vsnap = delta;
2162 }
2163 }
2164
2165 if (w->left + w->width >= v->left && w->left <= v->left + v->width) {
2166 /* Your top border <-> other top border */
2167 delta = abs(v->top - y);
2168 if (delta <= vsnap) {
2169 ny = v->top;
2170 vsnap = delta;
2171 }
2172
2173 /* Your bottom border <-> other bottom border */
2174 delta = abs(v->top + v->height - y - w->height);
2175 if (delta <= vsnap) {
2176 ny = v->top + v->height - w->height;
2177 vsnap = delta;
2178 }
2179 }
2180 }
2181 }
2182
2183 EnsureVisibleCaption(w, nx, ny);
2184
2185 w->SetDirty();
2186 return ES_HANDLED;
2187 } else if (w->flags & WF_SIZING) {
2188 /* Stop the sizing if the left mouse button was released */
2189 if (!_left_button_down) {
2190 w->flags &= ~WF_SIZING;
2191 w->SetDirty();
2192 break;
2193 }
2194
2195 /* Compute difference in pixels between cursor position and reference point in the window.
2196 * If resizing the left edge of the window, moving to the left makes the window bigger not smaller.
2197 */
2198 int x, y = _cursor.pos.y - _drag_delta.y;
2199 if (w->flags & WF_SIZING_LEFT) {
2200 x = _drag_delta.x - _cursor.pos.x;
2201 } else {
2202 x = _cursor.pos.x - _drag_delta.x;
2203 }
2204
2205 /* resize.step_width and/or resize.step_height may be 0, which means no resize is possible. */
2206 if (w->resize.step_width == 0) x = 0;
2207 if (w->resize.step_height == 0) y = 0;
2208
2209 /* Check the resize button won't go past the bottom of the screen */
2210 if (w->top + w->height + y > _screen.height) {
2211 y = _screen.height - w->height - w->top;
2212 }
2213
2214 /* X and Y has to go by step.. calculate it.
2215 * The cast to int is necessary else x/y are implicitly casted to
2216 * unsigned int, which won't work. */
2217 if (w->resize.step_width > 1) x -= x % (int)w->resize.step_width;
2218 if (w->resize.step_height > 1) y -= y % (int)w->resize.step_height;
2219
2220 /* Check that we don't go below the minimum set size */
2221 if ((int)w->width + x < (int)w->nested_root->smallest_x) {
2222 x = w->nested_root->smallest_x - w->width;
2223 }
2224 if ((int)w->height + y < (int)w->nested_root->smallest_y) {
2225 y = w->nested_root->smallest_y - w->height;
2226 }
2227
2228 /* Window already on size */
2229 if (x == 0 && y == 0) return ES_HANDLED;
2230
2231 /* Now find the new cursor pos.. this is NOT _cursor, because we move in steps. */
2232 _drag_delta.y += y;
2233 if ((w->flags & WF_SIZING_LEFT) && x != 0) {
2234 _drag_delta.x -= x; // x > 0 -> window gets longer -> left-edge moves to left -> subtract x to get new position.
2235 w->SetDirty();
2236 w->left -= x; // If dragging left edge, move left window edge in opposite direction by the same amount.
2237 /* ResizeWindow() below ensures marking new position as dirty. */
2238 } else {
2239 _drag_delta.x += x;
2240 }
2241
2242 /* ResizeWindow sets both pre- and after-size to dirty for redrawal */
2243 ResizeWindow(w, x, y);
2244 return ES_HANDLED;
2245 }
2246 }
2247
2248 _dragging_window = false;
2249 return ES_HANDLED;
2250}
2251
2256 static void StartWindowDrag(Window *w)
2257{
2258 w->flags |= WF_DRAGGING;
2259 w->flags &= ~WF_CENTERED;
2260 _dragging_window = true;
2261
2262 _drag_delta.x = w->left - _cursor.pos.x;
2263 _drag_delta.y = w->top - _cursor.pos.y;
2264
2265 BringWindowToFront(w);
2266}
2267
2273 static void StartWindowSizing(Window *w, bool to_left)
2274{
2275 w->flags |= to_left ? WF_SIZING_LEFT : WF_SIZING_RIGHT;
2276 w->flags &= ~WF_CENTERED;
2277 _dragging_window = true;
2278
2279 _drag_delta.x = _cursor.pos.x;
2280 _drag_delta.y = _cursor.pos.y;
2281
2282 BringWindowToFront(w);
2283}
2284
2289 static void HandleScrollbarScrolling(Window *w)
2290{
2291 int i;
2292 NWidgetScrollbar *sb = w->GetWidget<NWidgetScrollbar>(w->mouse_capture_widget);
2293 bool rtl = false;
2294
2295 if (sb->type == NWID_HSCROLLBAR) {
2296 i = _cursor.pos.x - _cursorpos_drag_start.x;
2297 rtl = _current_text_dir == TD_RTL;
2298 } else {
2299 i = _cursor.pos.y - _cursorpos_drag_start.y;
2300 }
2301
2302 if (sb->disp_flags & ND_SCROLLBAR_BTN) {
2303 if (_scroller_click_timeout == 1) {
2304 _scroller_click_timeout = 3;
2305 if (sb->UpdatePosition(rtl == HasBit(sb->disp_flags, NDB_SCROLLBAR_UP) ? 1 : -1)) w->SetDirty();
2306 }
2307 return;
2308 }
2309
2310 /* Find the item we want to move to. SetPosition will make sure it's inside bounds. */
2311 int range = sb->GetCount() - sb->GetCapacity();
2312 if (range <= 0) return;
2313
2314 int pos = RoundDivSU((i + _scrollbar_start_pos) * range, _scrollbar_size);
2315 if (rtl) pos = range - pos;
2316 if (sb->SetPosition(pos)) w->SetDirty();
2317}
2318
2323 static EventState HandleActiveWidget()
2324{
2325 for (Window *w : Window::Iterate()) {
2326 if (w->mouse_capture_widget >= 0) {
2327 /* Abort if no button is clicked any more. */
2328 if (!_left_button_down) {
2329 w->SetWidgetDirty(w->mouse_capture_widget);
2330 w->mouse_capture_widget = -1;
2331 return ES_HANDLED;
2332 }
2333
2334 /* Handle scrollbar internally, or dispatch click event */
2335 WidgetType type = w->GetWidget<NWidgetBase>(w->mouse_capture_widget)->type;
2336 if (type == NWID_VSCROLLBAR || type == NWID_HSCROLLBAR) {
2337 HandleScrollbarScrolling(w);
2338 } else {
2339 /* If cursor hasn't moved, there is nothing to do. */
2340 if (_cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED;
2341
2342 Point pt = { _cursor.pos.x - w->left, _cursor.pos.y - w->top };
2343 w->OnClick(pt, w->mouse_capture_widget, 0);
2344 }
2345 return ES_HANDLED;
2346 }
2347 }
2348
2349 return ES_NOT_HANDLED;
2350}
2351
2356 static EventState HandleViewportScroll()
2357{
2358 bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == SWS_SCROLL_MAP && _cursor.wheel_moved;
2359
2360 if (!_scrolling_viewport) return ES_NOT_HANDLED;
2361
2362 /* When we don't have a last scroll window we are starting to scroll.
2363 * When the last scroll window and this are not the same we went
2364 * outside of the window and should not left-mouse scroll anymore. */
2365 if (_last_scroll_window == nullptr) _last_scroll_window = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
2366
2367 if (_last_scroll_window == nullptr || !((_settings_client.gui.scroll_mode != VSM_MAP_LMB && _right_button_down) || scrollwheel_scrolling || (_settings_client.gui.scroll_mode == VSM_MAP_LMB && _left_button_down))) {
2368 _cursor.fix_at = false;
2369 _scrolling_viewport = false;
2370 _last_scroll_window = nullptr;
2371 return ES_NOT_HANDLED;
2372 }
2373
2374 if (_last_scroll_window == GetMainWindow() && _last_scroll_window->viewport->follow_vehicle != INVALID_VEHICLE) {
2375 /* If the main window is following a vehicle, then first let go of it! */
2376 const Vehicle *veh = Vehicle::Get(_last_scroll_window->viewport->follow_vehicle);
2377 ScrollMainWindowTo(veh->x_pos, veh->y_pos, veh->z_pos, true); // This also resets follow_vehicle
2378 return ES_NOT_HANDLED;
2379 }
2380
2381 Point delta;
2382 if (scrollwheel_scrolling) {
2383 /* We are using scrollwheels for scrolling */
2384 /* Use the integer part for movement */
2385 delta.x = static_cast<int>(_cursor.h_wheel);
2386 delta.y = static_cast<int>(_cursor.v_wheel);
2387 /* Keep the fractional part so that subtle movement is accumulated */
2388 float temp;
2389 _cursor.v_wheel = std::modf(_cursor.v_wheel, &temp);
2390 _cursor.h_wheel = std::modf(_cursor.h_wheel, &temp);
2391 } else {
2392 if (_settings_client.gui.scroll_mode != VSM_VIEWPORT_RMB_FIXED) {
2393 delta.x = -_cursor.delta.x;
2394 delta.y = -_cursor.delta.y;
2395 } else {
2396 delta.x = _cursor.delta.x;
2397 delta.y = _cursor.delta.y;
2398 }
2399 }
2400
2401 /* Create a scroll-event and send it to the window */
2402 if (delta.x != 0 || delta.y != 0) _last_scroll_window->OnScroll(delta);
2403
2404 _cursor.delta.x = 0;
2405 _cursor.delta.y = 0;
2406 _cursor.wheel_moved = false;
2407 return ES_HANDLED;
2408}
2409
2420 static bool MaybeBringWindowToFront(Window *w)
2421{
2422 bool bring_to_front = false;
2423
2424 if (w->window_class == WC_MAIN_WINDOW ||
2425 IsVitalWindow(w) ||
2426 w->window_class == WC_TOOLTIPS ||
2427 w->window_class == WC_DROPDOWN_MENU) {
2428 return true;
2429 }
2430
2431 /* Use unshaded window size rather than current size for shaded windows. */
2432 int w_width = w->width;
2433 int w_height = w->height;
2434 if (w->IsShaded()) {
2435 w_width = w->unshaded_size.width;
2436 w_height = w->unshaded_size.height;
2437 }
2438
2439 Window::IteratorToFront it(w);
2440 ++it;
2441 for (; !it.IsEnd(); ++it) {
2442 Window *u = *it;
2443 /* A modal child will prevent the activation of the parent window */
2444 if (u->parent == w && (u->window_desc.flags & WDF_MODAL)) {
2445 u->SetWhiteBorder();
2446 u->SetDirty();
2447 return false;
2448 }
2449
2450 if (u->window_class == WC_MAIN_WINDOW ||
2451 IsVitalWindow(u) ||
2452 u->window_class == WC_TOOLTIPS ||
2453 u->window_class == WC_DROPDOWN_MENU) {
2454 continue;
2455 }
2456
2457 /* Window sizes don't interfere, leave z-order alone */
2458 if (w->left + w_width <= u->left ||
2459 u->left + u->width <= w->left ||
2460 w->top + w_height <= u->top ||
2461 u->top + u->height <= w->top) {
2462 continue;
2463 }
2464
2465 bring_to_front = true;
2466 }
2467
2468 if (bring_to_front) BringWindowToFront(w);
2469 return true;
2470}
2471
2480 EventState Window::HandleEditBoxKey(WidgetID wid, char32_t key, uint16_t keycode)
2481{
2482 QueryString *query = this->GetQueryString(wid);
2483 if (query == nullptr) return ES_NOT_HANDLED;
2484
2485 int action = QueryString::ACTION_NOTHING;
2486
2487 switch (query->text.HandleKeyPress(key, keycode)) {
2488 case HKPR_EDITING:
2489 this->SetWidgetDirty(wid);
2490 this->OnEditboxChanged(wid);
2491 break;
2492
2493 case HKPR_CURSOR:
2494 this->SetWidgetDirty(wid);
2495 /* For the OSK also invalidate the parent window */
2496 if (this->window_class == WC_OSK) this->InvalidateData();
2497 break;
2498
2499 case HKPR_CONFIRM:
2500 if (this->window_class == WC_OSK) {
2501 this->OnClick(Point(), WID_OSK_OK, 1);
2502 } else if (query->ok_button >= 0) {
2503 this->OnClick(Point(), query->ok_button, 1);
2504 } else {
2505 action = query->ok_button;
2506 }
2507 break;
2508
2509 case HKPR_CANCEL:
2510 if (this->window_class == WC_OSK) {
2511 this->OnClick(Point(), WID_OSK_CANCEL, 1);
2512 } else if (query->cancel_button >= 0) {
2513 this->OnClick(Point(), query->cancel_button, 1);
2514 } else {
2515 action = query->cancel_button;
2516 }
2517 break;
2518
2519 case HKPR_NOT_HANDLED:
2520 return ES_NOT_HANDLED;
2521
2522 default: break;
2523 }
2524
2525 switch (action) {
2526 case QueryString::ACTION_DESELECT:
2527 this->UnfocusFocusedWidget();
2528 break;
2529
2530 case QueryString::ACTION_CLEAR:
2531 if (query->text.bytes <= 1) {
2532 /* If already empty, unfocus instead */
2533 this->UnfocusFocusedWidget();
2534 } else {
2535 query->text.DeleteAll();
2536 this->SetWidgetDirty(wid);
2537 this->OnEditboxChanged(wid);
2538 }
2539 break;
2540
2541 default:
2542 break;
2543 }
2544
2545 return ES_HANDLED;
2546}
2547
2552 void HandleToolbarHotkey(int hotkey)
2553{
2554 assert(HasModalProgress() || IsLocalCompany());
2555
2556 Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
2557 if (w != nullptr) {
2558 if (w->window_desc.hotkeys != nullptr) {
2559 if (hotkey >= 0 && w->OnHotkey(hotkey) == ES_HANDLED) return;
2560 }
2561 }
2562}
2563
2569 void HandleKeypress(uint keycode, char32_t key)
2570{
2571 /* World generation is multithreaded and messes with companies.
2572 * But there is no company related window open anyway, so _current_company is not used. */
2573 assert(HasModalProgress() || IsLocalCompany());
2574
2575 /*
2576 * The Unicode standard defines an area called the private use area. Code points in this
2577 * area are reserved for private use and thus not portable between systems. For instance,
2578 * Apple defines code points for the arrow keys in this area, but these are only printable
2579 * on a system running OS X. We don't want these keys to show up in text fields and such,
2580 * and thus we have to clear the unicode character when we encounter such a key.
2581 */
2582 if (key >= 0xE000 && key <= 0xF8FF) key = 0;
2583
2584 /*
2585 * If both key and keycode is zero, we don't bother to process the event.
2586 */
2587 if (key == 0 && keycode == 0) return;
2588
2589 /* Check if the focused window has a focused editbox */
2590 if (EditBoxInGlobalFocus()) {
2591 /* All input will in this case go to the focused editbox */
2592 if (_focused_window->window_class == WC_CONSOLE) {
2593 if (_focused_window->OnKeyPress(key, keycode) == ES_HANDLED) return;
2594 } else {
2595 if (_focused_window->HandleEditBoxKey(_focused_window->nested_focus->index, key, keycode) == ES_HANDLED) return;
2596 }
2597 }
2598
2599 /* Call the event, start with the uppermost window, but ignore the toolbar. */
2600 for (Window *w : Window::IterateFromFront()) {
2601 if (w->window_class == WC_MAIN_TOOLBAR) continue;
2602 if (w->window_desc.hotkeys != nullptr) {
2603 int hotkey = w->window_desc.hotkeys->CheckMatch(keycode);
2604 if (hotkey >= 0 && w->OnHotkey(hotkey) == ES_HANDLED) return;
2605 }
2606 if (w->OnKeyPress(key, keycode) == ES_HANDLED) return;
2607 }
2608
2609 Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
2610 /* When there is no toolbar w is null, check for that */
2611 if (w != nullptr) {
2612 if (w->window_desc.hotkeys != nullptr) {
2613 int hotkey = w->window_desc.hotkeys->CheckMatch(keycode);
2614 if (hotkey >= 0 && w->OnHotkey(hotkey) == ES_HANDLED) return;
2615 }
2616 if (w->OnKeyPress(key, keycode) == ES_HANDLED) return;
2617 }
2618
2619 HandleGlobalHotkeys(key, keycode);
2620}
2621
2625 void HandleCtrlChanged()
2626{
2627 /* Call the event, start with the uppermost window. */
2628 for (Window *w : Window::IterateFromFront()) {
2629 if (w->OnCTRLStateChange() == ES_HANDLED) return;
2630 }
2631}
2632
2638/* virtual */ void Window::InsertTextString(WidgetID wid, const char *str, bool marked, const char *caret, const char *insert_location, const char *replacement_end)
2639{
2640 QueryString *query = this->GetQueryString(wid);
2641 if (query == nullptr) return;
2642
2643 if (query->text.InsertString(str, marked, caret, insert_location, replacement_end) || marked) {
2644 this->SetWidgetDirty(wid);
2645 this->OnEditboxChanged(wid);
2646 }
2647}
2648
2655 void HandleTextInput(const char *str, bool marked, const char *caret, const char *insert_location, const char *replacement_end)
2656{
2657 if (!EditBoxInGlobalFocus()) return;
2658
2659 _focused_window->InsertTextString(_focused_window->window_class == WC_CONSOLE ? 0 : _focused_window->nested_focus->index, str, marked, caret, insert_location, replacement_end);
2660}
2661
2668 static int _input_events_this_tick = 0;
2669
2674 static void HandleAutoscroll()
2675{
2676 if (_game_mode == GM_MENU || HasModalProgress()) return;
2677 if (_settings_client.gui.auto_scrolling == VA_DISABLED) return;
2678 if (_settings_client.gui.auto_scrolling == VA_MAIN_VIEWPORT_FULLSCREEN && !_fullscreen) return;
2679
2680 int x = _cursor.pos.x;
2681 int y = _cursor.pos.y;
2682 Window *w = FindWindowFromPt(x, y);
2683 if (w == nullptr || w->flags & WF_DISABLE_VP_SCROLL) return;
2684 if (_settings_client.gui.auto_scrolling != VA_EVERY_VIEWPORT && w->window_class != WC_MAIN_WINDOW) return;
2685
2686 Viewport *vp = IsPtInWindowViewport(w, x, y);
2687 if (vp == nullptr) return;
2688
2689 x -= vp->left;
2690 y -= vp->top;
2691
2692 /* here allows scrolling in both x and y axis */
2693 /* If we succeed at scrolling in any direction, stop following a vehicle. */
2694 static const int SCROLLSPEED = 3;
2695 if (x - 15 < 0) {
2696 w->viewport->follow_vehicle = INVALID_VEHICLE;
2697 w->viewport->dest_scrollpos_x += ScaleByZoom((x - 15) * SCROLLSPEED, vp->zoom);
2698 } else if (15 - (vp->width - x) > 0) {
2699 w->viewport->follow_vehicle = INVALID_VEHICLE;
2700 w->viewport->dest_scrollpos_x += ScaleByZoom((15 - (vp->width - x)) * SCROLLSPEED, vp->zoom);
2701 }
2702 if (y - 15 < 0) {
2703 w->viewport->follow_vehicle = INVALID_VEHICLE;
2704 w->viewport->dest_scrollpos_y += ScaleByZoom((y - 15) * SCROLLSPEED, vp->zoom);
2705 } else if (15 - (vp->height - y) > 0) {
2706 w->viewport->follow_vehicle = INVALID_VEHICLE;
2707 w->viewport->dest_scrollpos_y += ScaleByZoom((15 - (vp->height - y)) * SCROLLSPEED, vp->zoom);
2708 }
2709}
2710
2711enum MouseClick {
2712 MC_NONE = 0,
2713 MC_LEFT,
2714 MC_RIGHT,
2715 MC_DOUBLE_LEFT,
2716 MC_HOVER,
2717};
2718
2719 static constexpr int MAX_OFFSET_DOUBLE_CLICK = 5;
2720 static constexpr int MAX_OFFSET_HOVER = 5;
2721
2722extern EventState VpHandlePlaceSizingDrag();
2723
2724 const std::chrono::milliseconds TIME_BETWEEN_DOUBLE_CLICK(500);
2725
2726static void ScrollMainViewport(int x, int y)
2727{
2728 if (_game_mode != GM_MENU && _game_mode != GM_BOOTSTRAP) {
2729 Window *w = GetMainWindow();
2730 w->viewport->dest_scrollpos_x += ScaleByZoom(x, w->viewport->zoom);
2731 w->viewport->dest_scrollpos_y += ScaleByZoom(y, w->viewport->zoom);
2732 }
2733}
2734
2744 static const int8_t scrollamt[16][2] = {
2745 { 0, 0},
2746 {-2, 0},
2747 { 0, -2},
2748 {-2, -1},
2749 { 2, 0},
2750 { 0, 0},
2751 { 2, -1},
2752 { 0, -2},
2753 { 0, 2},
2754 {-2, 1},
2755 { 0, 0},
2756 {-2, 0},
2757 { 2, 1},
2758 { 0, 2},
2759 { 2, 0},
2760 { 0, 0},
2761};
2762
2763static void HandleKeyScrolling()
2764{
2765 /*
2766 * Check that any of the dirkeys is pressed and that the focused window
2767 * doesn't have an edit-box as focused widget.
2768 */
2769 if (_dirkeys && !EditBoxInGlobalFocus()) {
2770 int factor = _shift_pressed ? 50 : 10;
2771
2772 if (_game_mode != GM_MENU && _game_mode != GM_BOOTSTRAP) {
2773 /* Key scrolling stops following a vehicle. */
2774 GetMainWindow()->viewport->follow_vehicle = INVALID_VEHICLE;
2775 }
2776
2777 ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor);
2778 }
2779}
2780
2781static void MouseLoop(MouseClick click, int mousewheel)
2782{
2783 /* World generation is multithreaded and messes with companies.
2784 * But there is no company related window open anyway, so _current_company is not used. */
2785 assert(HasModalProgress() || IsLocalCompany());
2786
2787 HandlePlacePresize();
2788 UpdateTileSelection();
2789
2790 if (VpHandlePlaceSizingDrag() == ES_HANDLED) return;
2791 if (HandleMouseDragDrop() == ES_HANDLED) return;
2792 if (HandleWindowDragging() == ES_HANDLED) return;
2793 if (HandleActiveWidget() == ES_HANDLED) return;
2794 if (HandleViewportScroll() == ES_HANDLED) return;
2795
2796 HandleMouseOver();
2797
2798 bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == SWS_SCROLL_MAP && _cursor.wheel_moved;
2799 if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return;
2800
2801 int x = _cursor.pos.x;
2802 int y = _cursor.pos.y;
2803 Window *w = FindWindowFromPt(x, y);
2804 if (w == nullptr) return;
2805
2806 if (click != MC_HOVER && !MaybeBringWindowToFront(w)) return;
2807 Viewport *vp = IsPtInWindowViewport(w, x, y);
2808
2809 /* Don't allow any action in a viewport if either in menu or when having a modal progress window */
2810 if (vp != nullptr && (_game_mode == GM_MENU || HasModalProgress())) return;
2811
2812 if (mousewheel != 0) {
2813 /* Send mousewheel event to window, unless we're scrolling a viewport or the map */
2814 if (!scrollwheel_scrolling || (vp == nullptr && w->window_class != WC_SMALLMAP)) w->OnMouseWheel(mousewheel);
2815
2816 /* Dispatch a MouseWheelEvent for widgets if it is not a viewport */
2817 if (vp == nullptr) DispatchMouseWheelEvent(w, w->nested_root->GetWidgetFromPos(x - w->left, y - w->top), mousewheel);
2818 }
2819
2820 if (vp != nullptr) {
2821 if (scrollwheel_scrolling && !(w->flags & WF_DISABLE_VP_SCROLL)) {
2822 _scrolling_viewport = true;
2823 _cursor.fix_at = true;
2824 return;
2825 }
2826
2827 switch (click) {
2828 case MC_DOUBLE_LEFT:
2829 case MC_LEFT:
2830 if (HandleViewportClicked(vp, x, y)) return;
2831 if (!(w->flags & WF_DISABLE_VP_SCROLL) &&
2832 _settings_client.gui.scroll_mode == VSM_MAP_LMB) {
2833 _scrolling_viewport = true;
2834 _cursor.fix_at = false;
2835 return;
2836 }
2837 break;
2838
2839 case MC_RIGHT:
2840 if (!(w->flags & WF_DISABLE_VP_SCROLL) &&
2841 _settings_client.gui.scroll_mode != VSM_MAP_LMB) {
2842 _scrolling_viewport = true;
2843 _cursor.fix_at = (_settings_client.gui.scroll_mode == VSM_VIEWPORT_RMB_FIXED ||
2844 _settings_client.gui.scroll_mode == VSM_MAP_RMB_FIXED);
2845 DispatchRightClickEvent(w, x - w->left, y - w->top);
2846 return;
2847 }
2848 break;
2849
2850 default:
2851 break;
2852 }
2853 }
2854
2855 switch (click) {
2856 case MC_LEFT:
2857 case MC_DOUBLE_LEFT:
2858 DispatchLeftClickEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1);
2859 return;
2860
2861 default:
2862 if (!scrollwheel_scrolling || w == nullptr || w->window_class != WC_SMALLMAP) break;
2863 /* We try to use the scrollwheel to scroll since we didn't touch any of the buttons.
2864 * Simulate a right button click so we can get started. */
2865 [[fallthrough]];
2866
2867 case MC_RIGHT:
2868 DispatchRightClickEvent(w, x - w->left, y - w->top);
2869 return;
2870
2871 case MC_HOVER:
2872 DispatchHoverEvent(w, x - w->left, y - w->top);
2873 break;
2874 }
2875
2876 /* We're not doing anything with 2D scrolling, so reset the value. */
2877 _cursor.h_wheel = 0.0f;
2878 _cursor.v_wheel = 0.0f;
2879 _cursor.wheel_moved = false;
2880}
2881
2885 void HandleMouseEvents()
2886{
2887 /* World generation is multithreaded and messes with companies.
2888 * But there is no company related window open anyway, so _current_company is not used. */
2889 assert(HasModalProgress() || IsLocalCompany());
2890
2891 /* Handle sprite picker before any GUI interaction */
2892 if (_newgrf_debug_sprite_picker.mode == SPM_REDRAW && _input_events_this_tick == 0) {
2893 /* We are done with the last draw-frame, so we know what sprites we
2894 * clicked on. Reset the picker mode and invalidate the window. */
2895 _newgrf_debug_sprite_picker.mode = SPM_NONE;
2896 InvalidateWindowData(WC_SPRITE_ALIGNER, 0, 1);
2897 }
2898
2899 static std::chrono::steady_clock::time_point double_click_time = {};
2900 static Point double_click_pos = {0, 0};
2901
2902 /* Mouse event? */
2903 MouseClick click = MC_NONE;
2904 if (_left_button_down && !_left_button_clicked) {
2905 click = MC_LEFT;
2906 if (std::chrono::steady_clock::now() <= double_click_time + TIME_BETWEEN_DOUBLE_CLICK &&
2907 double_click_pos.x != 0 && abs(_cursor.pos.x - double_click_pos.x) < MAX_OFFSET_DOUBLE_CLICK &&
2908 double_click_pos.y != 0 && abs(_cursor.pos.y - double_click_pos.y) < MAX_OFFSET_DOUBLE_CLICK) {
2909 click = MC_DOUBLE_LEFT;
2910 }
2911 double_click_time = std::chrono::steady_clock::now();
2912 double_click_pos = _cursor.pos;
2913 _left_button_clicked = true;
2914 _input_events_this_tick++;
2915 } else if (_right_button_clicked) {
2916 _right_button_clicked = false;
2917 click = MC_RIGHT;
2918 _input_events_this_tick++;
2919 }
2920
2921 int mousewheel = 0;
2922 if (_cursor.wheel) {
2923 mousewheel = _cursor.wheel;
2924 _cursor.wheel = 0;
2925 _input_events_this_tick++;
2926 }
2927
2928 static std::chrono::steady_clock::time_point hover_time = {};
2929 static Point hover_pos = {0, 0};
2930
2931 if (_settings_client.gui.hover_delay_ms > 0) {
2932 if (!_cursor.in_window || click != MC_NONE || mousewheel != 0 || _left_button_down || _right_button_down ||
2933 hover_pos.x == 0 || abs(_cursor.pos.x - hover_pos.x) >= MAX_OFFSET_HOVER ||
2934 hover_pos.y == 0 || abs(_cursor.pos.y - hover_pos.y) >= MAX_OFFSET_HOVER) {
2935 hover_pos = _cursor.pos;
2936 hover_time = std::chrono::steady_clock::now();
2937 _mouse_hovering = false;
2938 } else if (!_mouse_hovering) {
2939 if (std::chrono::steady_clock::now() > hover_time + std::chrono::milliseconds(_settings_client.gui.hover_delay_ms)) {
2940 click = MC_HOVER;
2941 _input_events_this_tick++;
2942 _mouse_hovering = true;
2943 hover_time = std::chrono::steady_clock::now();
2944 }
2945 }
2946 }
2947
2948 if (click == MC_LEFT && _newgrf_debug_sprite_picker.mode == SPM_WAIT_CLICK) {
2949 /* Mark whole screen dirty, and wait for the next realtime tick, when drawing is finished. */
2950 Blitter *blitter = BlitterFactory::GetCurrentBlitter();
2951 _newgrf_debug_sprite_picker.clicked_pixel = blitter->MoveTo(_screen.dst_ptr, _cursor.pos.x, _cursor.pos.y);
2952 _newgrf_debug_sprite_picker.sprites.clear();
2953 _newgrf_debug_sprite_picker.mode = SPM_REDRAW;
2954 MarkWholeScreenDirty();
2955 } else {
2956 MouseLoop(click, mousewheel);
2957 }
2958
2959 /* We have moved the mouse the required distance,
2960 * no need to move it at any later time. */
2961 _cursor.delta.x = 0;
2962 _cursor.delta.y = 0;
2963}
2964
2968 static void CheckSoftLimit()
2969{
2970 if (_settings_client.gui.window_soft_limit == 0) return;
2971
2972 for (;;) {
2973 uint deletable_count = 0;
2974 Window *last_deletable = nullptr;
2975 for (Window *w : Window::IterateFromFront()) {
2976 if (w->window_class == WC_MAIN_WINDOW || IsVitalWindow(w) || (w->flags & WF_STICKY)) continue;
2977
2978 last_deletable = w;
2979 deletable_count++;
2980 }
2981
2982 /* We've not reached the soft limit yet. */
2983 if (deletable_count <= _settings_client.gui.window_soft_limit) break;
2984
2985 assert(last_deletable != nullptr);
2986 last_deletable->Close();
2987 }
2988}
2989
2993 void InputLoop()
2994{
2995 /* World generation is multithreaded and messes with companies.
2996 * But there is no company related window open anyway, so _current_company is not used. */
2997 assert(HasModalProgress() || IsLocalCompany());
2998
2999 CheckSoftLimit();
3000
3001 /* Process scheduled window deletion. */
3002 Window::DeleteClosedWindows();
3003
3004 if (_input_events_this_tick != 0) {
3005 /* The input loop is called only once per GameLoop() - so we can clear the counter here */
3006 _input_events_this_tick = 0;
3007 /* there were some inputs this tick, don't scroll ??? */
3008 return;
3009 }
3010
3011 /* HandleMouseEvents was already called for this tick */
3012 HandleMouseEvents();
3013}
3014
3018 void CallWindowRealtimeTickEvent(uint delta_ms)
3019{
3020 for (Window *w : Window::Iterate()) {
3021 w->OnRealtimeTick(delta_ms);
3022 }
3023}
3024
3026 static IntervalTimer<TimerWindow> window_interval(std::chrono::milliseconds(30), [](auto) {
3027 extern int _caret_timer;
3028 _caret_timer += 3;
3029 CursorTick();
3030
3031 HandleKeyScrolling();
3032 HandleAutoscroll();
3033 DecreaseWindowCounters();
3034});
3035
3037 static IntervalTimer<TimerWindow> highlight_interval(std::chrono::milliseconds(450), [](auto) {
3038 _window_highlight_colour = !_window_highlight_colour;
3039});
3040
3042 static IntervalTimer<TimerWindow> white_border_interval(std::chrono::milliseconds(30), [](auto) {
3043 if (_network_dedicated) return;
3044
3045 for (Window *w : Window::Iterate()) {
3046 if ((w->flags & WF_WHITE_BORDER) && --w->white_border_timer == 0) {
3047 CLRBITS(w->flags, WF_WHITE_BORDER);
3048 w->SetDirty();
3049 }
3050 }
3051});
3052
3056 void UpdateWindows()
3057{
3058 static auto last_time = std::chrono::steady_clock::now();
3059 auto now = std::chrono::steady_clock::now();
3060 auto delta_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_time);
3061
3062 if (delta_ms.count() == 0) return;
3063
3064 last_time = now;
3065
3066 PerformanceMeasurer framerate(PFE_DRAWING);
3067 PerformanceAccumulator::Reset(PFE_DRAWWORLD);
3068
3069 ProcessPendingPerformanceMeasurements();
3070
3071 TimerManager<TimerWindow>::Elapsed(delta_ms);
3072 CallWindowRealtimeTickEvent(delta_ms.count());
3073
3074 /* Process invalidations before anything else. */
3075 for (Window *w : Window::Iterate()) {
3076 w->ProcessScheduledResize();
3077 w->ProcessScheduledInvalidations();
3078 w->ProcessHighlightedInvalidations();
3079 }
3080
3081 /* Skip the actual drawing on dedicated servers without screen.
3082 * But still empty the invalidation queues above. */
3083 if (_network_dedicated) return;
3084
3085 DrawDirtyBlocks();
3086
3087 for (Window *w : Window::Iterate()) {
3088 /* Update viewport only if window is not shaded. */
3089 if (w->viewport != nullptr && !w->IsShaded()) UpdateViewportPosition(w, delta_ms.count());
3090 }
3091 NetworkDrawChatMessage();
3092 /* Redraw mouse cursor in case it was hidden */
3093 DrawMouseCursor();
3094}
3095
3101 void SetWindowDirty(WindowClass cls, WindowNumber number)
3102{
3103 for (const Window *w : Window::Iterate()) {
3104 if (w->window_class == cls && w->window_number == number) w->SetDirty();
3105 }
3106}
3107
3114 void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
3115{
3116 for (const Window *w : Window::Iterate()) {
3117 if (w->window_class == cls && w->window_number == number) {
3118 w->SetWidgetDirty(widget_index);
3119 }
3120 }
3121}
3122
3127 void SetWindowClassesDirty(WindowClass cls)
3128{
3129 for (const Window *w : Window::Iterate()) {
3130 if (w->window_class == cls) w->SetDirty();
3131 }
3132}
3133
3137 void Window::ScheduleResize()
3138{
3139 this->scheduled_resize = true;
3140}
3141
3145 void Window::ProcessScheduledResize()
3146{
3147 /* Sometimes OnResize() resizes the window again, in which case we can reprocess immediately. */
3148 while (this->scheduled_resize) {
3149 this->scheduled_resize = false;
3150 this->OnResize();
3151 }
3152}
3153
3159 void Window::InvalidateData(int data, bool gui_scope)
3160{
3161 this->SetDirty();
3162 if (!gui_scope) {
3163 /* Schedule GUI-scope invalidation for next redraw. */
3164 this->scheduled_invalidation_data.push_back(data);
3165 }
3166 this->OnInvalidateData(data, gui_scope);
3167}
3168
3172 void Window::ProcessScheduledInvalidations()
3173{
3174 for (int data : this->scheduled_invalidation_data) {
3175 if (this->window_class == WC_INVALID) break;
3176 this->OnInvalidateData(data, true);
3177 }
3178 this->scheduled_invalidation_data.clear();
3179}
3180
3184 void Window::ProcessHighlightedInvalidations()
3185{
3186 if ((this->flags & WF_HIGHLIGHTED) == 0) return;
3187
3188 for (const auto &pair : this->widget_lookup) {
3189 if (pair.second->IsHighlighted()) pair.second->SetDirty(this);
3190 }
3191}
3192
3219 void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
3220{
3221 for (Window *w : Window::Iterate()) {
3222 if (w->window_class == cls && w->window_number == number) {
3223 w->InvalidateData(data, gui_scope);
3224 }
3225 }
3226}
3227
3236 void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
3237{
3238 for (Window *w : Window::Iterate()) {
3239 if (w->window_class == cls) {
3240 w->InvalidateData(data, gui_scope);
3241 }
3242 }
3243}
3244
3248 void CallWindowGameTickEvent()
3249{
3250 for (Window *w : Window::Iterate()) {
3251 w->OnGameTick();
3252 }
3253}
3254
3261 void CloseNonVitalWindows()
3262{
3263 /* Note: the container remains stable, even when deleting windows. */
3264 for (Window *w : Window::Iterate()) {
3265 if ((w->window_desc.flags & WDF_NO_CLOSE) == 0 &&
3266 (w->flags & WF_STICKY) == 0) { // do not delete windows which are 'pinned'
3267
3268 w->Close();
3269 }
3270 }
3271}
3272
3280 void CloseAllNonVitalWindows()
3281{
3282 /* Note: the container remains stable, even when closing windows. */
3283 for (Window *w : Window::Iterate()) {
3284 if ((w->window_desc.flags & WDF_NO_CLOSE) == 0) {
3285 w->Close();
3286 }
3287 }
3288}
3289
3293 void DeleteAllMessages()
3294{
3295 InitNewsItemStructs();
3296 InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED); // invalidate the statusbar
3297 InvalidateWindowData(WC_MESSAGE_HISTORY, 0); // invalidate the message history
3298 CloseWindowById(WC_NEWS_WINDOW, 0); // close newspaper or general message window if shown
3299}
3300
3305 void CloseConstructionWindows()
3306{
3307 /* Note: the container remains stable, even when deleting windows. */
3308 for (Window *w : Window::Iterate()) {
3309 if (w->window_desc.flags & WDF_CONSTRUCTION) {
3310 w->Close();
3311 }
3312 }
3313
3314 for (const Window *w : Window::Iterate()) w->SetDirty();
3315}
3316
3318 void HideVitalWindows()
3319{
3320 CloseWindowById(WC_MAIN_TOOLBAR, 0);
3321 CloseWindowById(WC_STATUS_BAR, 0);
3322}
3323
3324void ReInitWindow(Window *w, bool zoom_changed)
3325{
3326 if (w == nullptr) return;
3327 if (zoom_changed) {
3328 w->nested_root->AdjustPaddingForZoom();
3329 w->UpdateQueryStringSize();
3330 }
3331 w->ReInit();
3332}
3333
3335 void ReInitAllWindows(bool zoom_changed)
3336{
3337 SetupWidgetDimensions();
3338 NWidgetLeaf::InvalidateDimensionCache(); // Reset cached sizes of several widgets.
3339 NWidgetScrollbar::InvalidateDimensionCache();
3340
3341 InitDepotWindowBlockSizes();
3342
3343 /* When _gui_zoom has changed, we need to resize toolbar and statusbar first,
3344 * so EnsureVisibleCaption uses the updated size information. */
3345 ReInitWindow(FindWindowById(WC_MAIN_TOOLBAR, 0), zoom_changed);
3346 ReInitWindow(FindWindowById(WC_STATUS_BAR, 0), zoom_changed);
3347 for (Window *w : Window::Iterate()) {
3348 if (w->window_class == WC_MAIN_TOOLBAR || w->window_class == WC_STATUS_BAR) continue;
3349 ReInitWindow(w, zoom_changed);
3350 }
3351
3352 if (_networking) NetworkUndrawChatMessage();
3353 NetworkReInitChatBoxSize();
3354
3355 /* Make sure essential parts of all windows are visible */
3356 RelocateAllWindows(_screen.width, _screen.height);
3357 MarkWholeScreenDirty();
3358}
3359
3367 static int PositionWindow(Window *w, WindowClass clss, int setting)
3368{
3369 if (w == nullptr || w->window_class != clss) {
3370 w = FindWindowById(clss, 0);
3371 }
3372 if (w == nullptr) return 0;
3373
3374 int old_left = w->left;
3375 switch (setting) {
3376 case 1: w->left = (_screen.width - w->width) / 2; break;
3377 case 2: w->left = _screen.width - w->width; break;
3378 default: w->left = 0; break;
3379 }
3380 if (w->viewport != nullptr) w->viewport->left += w->left - old_left;
3381 AddDirtyBlock(0, w->top, _screen.width, w->top + w->height); // invalidate the whole row
3382 return w->left;
3383}
3384
3390 int PositionMainToolbar(Window *w)
3391{
3392 Debug(misc, 5, "Repositioning Main Toolbar...");
3393 return PositionWindow(w, WC_MAIN_TOOLBAR, _settings_client.gui.toolbar_pos);
3394}
3395
3401 int PositionStatusbar(Window *w)
3402{
3403 Debug(misc, 5, "Repositioning statusbar...");
3404 return PositionWindow(w, WC_STATUS_BAR, _settings_client.gui.statusbar_pos);
3405}
3406
3412 int PositionNewsMessage(Window *w)
3413{
3414 Debug(misc, 5, "Repositioning news message...");
3415 return PositionWindow(w, WC_NEWS_WINDOW, _settings_client.gui.statusbar_pos);
3416}
3417
3423 int PositionNetworkChatWindow(Window *w)
3424{
3425 Debug(misc, 5, "Repositioning network chat window...");
3426 return PositionWindow(w, WC_SEND_NETWORK_MSG, _settings_client.gui.statusbar_pos);
3427}
3428
3429
3435 void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index)
3436{
3437 for (const Window *w : Window::Iterate()) {
3438 if (w->viewport != nullptr && w->viewport->follow_vehicle == from_index) {
3439 w->viewport->follow_vehicle = to_index;
3440 w->SetDirty();
3441 }
3442 }
3443}
3444
3445
3451 void RelocateAllWindows(int neww, int newh)
3452{
3453 CloseWindowByClass(WC_DROPDOWN_MENU);
3454
3455 /* Reposition toolbar then status bar before other all windows. */
3456 if (Window *wt = FindWindowById(WC_MAIN_TOOLBAR, 0); wt != nullptr) {
3457 ResizeWindow(wt, std::min<uint>(neww, _toolbar_width) - wt->width, 0, false);
3458 wt->left = PositionMainToolbar(wt);
3459 }
3460
3461 if (Window *ws = FindWindowById(WC_STATUS_BAR, 0); ws != nullptr) {
3462 ResizeWindow(ws, std::min<uint>(neww, _toolbar_width) - ws->width, 0, false);
3463 ws->top = newh - ws->height;
3464 ws->left = PositionStatusbar(ws);
3465 }
3466
3467 for (Window *w : Window::Iterate()) {
3468 int left, top;
3469 /* XXX - this probably needs something more sane. For example specifying
3470 * in a 'backup'-desc that the window should always be centered. */
3471 switch (w->window_class) {
3472 case WC_MAIN_WINDOW:
3473 case WC_BOOTSTRAP:
3474 case WC_HIGHSCORE:
3475 case WC_ENDSCREEN:
3476 ResizeWindow(w, neww, newh);
3477 continue;
3478
3479 case WC_MAIN_TOOLBAR:
3480 case WC_STATUS_BAR:
3481 continue;
3482
3483 case WC_NEWS_WINDOW:
3484 top = newh - w->height;
3485 left = PositionNewsMessage(w);
3486 break;
3487
3488 case WC_SEND_NETWORK_MSG:
3489 ResizeWindow(w, std::min<uint>(neww, _toolbar_width) - w->width, 0, false);
3490
3491 top = newh - w->height - FindWindowById(WC_STATUS_BAR, 0)->height;
3492 left = PositionNetworkChatWindow(w);
3493 break;
3494
3495 case WC_CONSOLE:
3496 IConsoleResize(w);
3497 continue;
3498
3499 default: {
3500 if (w->flags & WF_CENTERED) {
3501 top = (newh - w->height) >> 1;
3502 left = (neww - w->width) >> 1;
3503 break;
3504 }
3505
3506 left = w->left;
3507 if (left + (w->width >> 1) >= neww) left = neww - w->width;
3508 if (left < 0) left = 0;
3509
3510 top = w->top;
3511 if (top + (w->height >> 1) >= newh) top = newh - w->height;
3512 break;
3513 }
3514 }
3515
3516 EnsureVisibleCaption(w, left, top);
3517 }
3518}
3519
3524 void PickerWindowBase::Close([[maybe_unused]] int data)
3525{
3526 ResetObjectToPlace();
3527 this->Window::Close();
3528}
HasBit
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition bitmath_func.hpp:103
CLRBITS
#define CLRBITS(x, y)
Clears several bits in a variable.
Definition bitmath_func.hpp:166
ClrBit
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Definition bitmath_func.hpp:151
BlitterFactory::GetCurrentBlitter
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:138
Blitter
How all blitters should look like.
Definition base.hpp:29
Blitter::MoveTo
virtual void * MoveTo(void *video, int x, int y)=0
Move the destination pointer the requested amount x and y, keeping in mind any pitch and bpp of the r...
Game::NewEvent
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition game_core.cpp:146
IntervalTimer
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
NWidgetBase
Baseclass for nested widgets.
Definition widget_type.h:145
NWidgetBase::SetDirty
virtual void SetDirty(const Window *w) const
Mark the widget as 'dirty' (in need of repaint).
Definition widget.cpp:904
NWidgetBase::type
WidgetType type
Type of the widget / nested widget.
Definition widget_type.h:233
NWidgetBase::pos_x
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition widget_type.h:249
NWidgetCore
Base class for a 'real' widget.
Definition widget_type.h:371
NWidgetCore::IsDisabled
bool IsDisabled() const
Return whether the widget is disabled.
Definition widget_type.h:450
NWidgetCore::disp_flags
NWidgetDisplay disp_flags
Flags that affect display and interaction with the widget.
Definition widget_type.h:391
NWidgetCore::index
const WidgetID index
Index of the nested widget (-1 means 'not used').
Definition widget_type.h:393
NWidgetCore::scrollbar_index
WidgetID scrollbar_index
Index of an attached scrollbar.
Definition widget_type.h:396
NWidgetCore::SetLowered
void SetLowered(bool lowered)
Lower or raise the widget.
Definition widget_type.h:429
NWidgetCore::tool_tip
StringID tool_tip
Tooltip of the widget.
Definition widget_type.h:395
NWidgetLeaf::InvalidateDimensionCache
static void InvalidateDimensionCache()
Reset the cached dimensions.
Definition widget.cpp:2594
NWidgetLeaf::resizebox_dimension
static Dimension resizebox_dimension
Cached size of a resizebox widget.
Definition widget_type.h:2609
NWidgetLeaf::closebox_dimension
static Dimension closebox_dimension
Cached size of a closebox widget.
Definition widget_type.h:2610
NWidgetScrollbar
Nested widget to display and control a scrollbar in a window.
Definition widget_type.h:896
NWidgetStacked::shown_plane
int shown_plane
Plane being displayed (for NWID_SELECTION only).
Definition widget_type.h:512
NWidgetStacked::SetDisplayedPlane
bool SetDisplayedPlane(int plane)
Select which plane to show (for NWID_SELECTION only).
Definition widget.cpp:1335
PerformanceAccumulator::Reset
static void Reset(PerformanceElement elem)
Store the previous accumulator value and reset for a new cycle of accumulating measurements.
Definition framerate_gui.cpp:328
PerformanceMeasurer
RAII class for measuring simple elements of performance.
Definition framerate_type.h:92
PickerWindowBase::Close
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:3524
Scrollbar
Scrollbar data structure.
Definition widget_type.h:694
Scrollbar::GetCapacity
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition widget_type.h:731
Scrollbar::UpdatePosition
bool UpdatePosition(int difference, ScrollbarStepping unit=SS_SMALL)
Updates the position of the first visible element by the given amount.
Definition widget_type.h:824
Scrollbar::SetPosition
bool SetPosition(size_type position)
Sets the position of the first visible element.
Definition widget_type.h:810
Scrollbar::GetCount
size_type GetCount() const
Gets the number of elements in the list.
Definition widget_type.h:722
TimerManager::Elapsed
static bool Elapsed(TElapsed value)
Called when time for this timer elapsed.
VideoDriver::EditBoxLostFocus
virtual void EditBoxLostFocus()
An edit box lost the input focus.
Definition video_driver.hpp:152
VideoDriver::GetInstance
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
Definition video_driver.hpp:201
VideoDriver::EditBoxGainedFocus
virtual void EditBoxGainedFocus()
An edit box gained the input focus.
Definition video_driver.hpp:157
WidgetDimensions::scaled
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:28
company_func.h
Functions related to companies.
IsLocalCompany
bool IsLocalCompany()
Is the current company the local company?
Definition company_func.h:47
Owner
Owner
Enum for all companies/owners.
Definition company_type.h:18
INVALID_OWNER
@ INVALID_OWNER
An invalid owner.
Definition company_type.h:29
console_func.h
Console functions used outside of the console code.
IConsoleClose
void IConsoleClose()
Close the in-game console.
Definition console_gui.cpp:445
IConsoleResize
void IConsoleResize(Window *w)
Change the size of the in-game console window after the screen size changed, or the window state chan...
Definition console_gui.cpp:411
console_gui.h
GUI related functions in the console.
Debug
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition debug.h:37
depot_func.h
Functions related to depots.
InitDepotWindowBlockSizes
void InitDepotWindowBlockSizes()
Set the size of the blocks in the window so we can be sure that they are big enough for the vehicle s...
Definition depot_gui.cpp:218
error.h
Functions related to errors.
UnshowCriticalError
void UnshowCriticalError()
Unshow the critical error.
Definition error_gui.cpp:349
ShowFirstError
void ShowFirstError()
Show the first error of the queue.
Definition error_gui.cpp:335
factory.hpp
Factory to 'query' all available blitters.
NO_DIRECTORY
@ NO_DIRECTORY
A path without any base directory.
Definition fileio_type.h:133
GetCharacterHeight
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
ProcessPendingPerformanceMeasurements
void ProcessPendingPerformanceMeasurements()
This drains the PFE_SOUND measurement data queue into _pf_data.
Definition framerate_gui.cpp:1105
framerate_type.h
Types for recording game performance data.
PFE_DRAWING
@ PFE_DRAWING
Speed of drawing world and GUI.
Definition framerate_type.h:57
PFE_DRAWWORLD
@ PFE_DRAWWORLD
Time spent drawing world viewports in GUI.
Definition framerate_type.h:58
game.hpp
Base functions for all Games.
_shift_pressed
bool _shift_pressed
Is Shift pressed?
Definition gfx.cpp:39
_left_button_down
bool _left_button_down
Is left mouse button pressed?
Definition gfx.cpp:41
_ctrl_pressed
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
_dirkeys
uint8_t _dirkeys
1 = left, 2 = up, 4 = right, 8 = down
Definition gfx.cpp:34
_left_button_clicked
bool _left_button_clicked
Is left mouse button clicked?
Definition gfx.cpp:42
_right_button_clicked
bool _right_button_clicked
Is right mouse button clicked?
Definition gfx.cpp:44
_right_button_down
bool _right_button_down
Is right mouse button pressed?
Definition gfx.cpp:43
_gui_scale
int _gui_scale
GUI scale, 100 is 100%.
Definition gfx.cpp:63
gfx_func.h
Functions related to the gfx engine.
FS_NORMAL
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:209
TextColour
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:260
MakeWindowNWidgetTree
std::unique_ptr< NWidgetBase > MakeWindowNWidgetTree(std::span< const NWidgetPart > nwid_parts, NWidgetStacked **shade_select)
Make a nested widget tree for a window from a parts array.
Definition widget.cpp:3316
Window::SetDirty
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:940
AddDirtyBlock
void AddDirtyBlock(int left, int top, int right, int bottom)
Extend the internal _invalid_rect rectangle to contain the rectangle defined by the given parameters.
Definition gfx.cpp:1486
DrawDirtyBlocks
void DrawDirtyBlocks()
Repaints the rectangle blocks which are marked as 'dirty'.
Definition gfx.cpp:1397
MarkWholeScreenDirty
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1529
hotkeys.h
Hotkey related functions.
ini_type.h
Types related to reading/writing '*.ini' files.
TileVirtXY
static debug_inline TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:404
IsInsideBS
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
Definition math_func.hpp:252
abs
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
RoundDivSU
constexpr int RoundDivSU(int a, uint b)
Computes round(a / b) for signed a and unsigned b.
Definition math_func.hpp:342
Ceil
constexpr uint Ceil(uint a, uint b)
Computes ceil(a / b) * b for non-negative a and b.
Definition math_func.hpp:331
Clamp
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
GuiShowTooltips
void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, uint paramcount)
Shows a tooltip.
Definition misc_gui.cpp:740
_networking
bool _networking
are we in networking mode?
Definition network.cpp:65
_network_dedicated
bool _network_dedicated
are we a dedicated server?
Definition network.cpp:68
network.h
Basic functions/variables used all over the place.
NetworkDrawChatMessage
void NetworkDrawChatMessage()
Draw the chat message-box.
Definition network_chat_gui.cpp:181
NetworkReInitChatBoxSize
void NetworkReInitChatBoxSize()
Initialize all font-dependent chat box sizes.
Definition network_chat_gui.cpp:102
NetworkUndrawChatMessage
void NetworkUndrawChatMessage()
Hide the chatbox.
Definition network_chat_gui.cpp:121
network_func.h
Network functions used by other parts of OpenTTD.
newgrf_debug.h
Functions/types related to NewGRF debugging.
_newgrf_debug_sprite_picker
NewGrfDebugSpritePicker _newgrf_debug_sprite_picker
The sprite picker.
Definition newgrf_debug_gui.cpp:51
valid
uint8_t valid
Bits indicating what variable is valid (for each bit, 0 is invalid, 1 is valid).
Definition newgrf_station.cpp:247
news_func.h
Functions related to news.
InitNewsItemStructs
void InitNewsItemStructs()
Initialize the news-items data structures.
Definition news_gui.cpp:719
WID_OSK_CANCEL
@ WID_OSK_CANCEL
Cancel key.
Definition osk_widget.h:17
WID_OSK_OK
@ WID_OSK_OK
Ok key.
Definition osk_widget.h:18
progress.h
Functions related to modal progress.
HasModalProgress
bool HasModalProgress()
Check if we are currently in a modal progress state.
Definition progress.h:17
querystring_gui.h
Base for the GUIs that have an edit box in them.
safeguards.h
A number of safeguards to prevent using unsafe methods.
IniLoadWindowSettings
void IniLoadWindowSettings(IniFile &ini, const char *grpname, void *desc)
Load a WindowDesc from config.
Definition settings.cpp:862
IniSaveWindowSettings
void IniSaveWindowSettings(IniFile &ini, const char *grpname, void *desc)
Save a WindowDesc to config.
Definition settings.cpp:873
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
settings_func.h
Functions related to setting/changing the settings.
settings_type.h
Types related to global configuration settings.
VSM_VIEWPORT_RMB_FIXED
@ VSM_VIEWPORT_RMB_FIXED
Viewport moves with mouse movement on holding right mouse button, cursor position is fixed.
Definition settings_type.h:122
VSM_MAP_RMB_FIXED
@ VSM_MAP_RMB_FIXED
Map moves with mouse movement on holding right mouse button, cursor position is fixed.
Definition settings_type.h:123
VSM_MAP_LMB
@ VSM_MAP_LMB
Map moves with mouse movement on holding left mouse button, cursor moves.
Definition settings_type.h:125
SWS_SCROLL_MAP
@ SWS_SCROLL_MAP
Scroll wheel scrolls the map.
Definition settings_type.h:132
ScrollMainWindowTo
bool ScrollMainWindowTo(int x, int y, int z, bool instant)
Scrolls the main window to given coordinates.
Definition smallmap_gui.cpp:2077
statusbar_gui.h
Functions, definitions and such used only by the GUI.
SBI_NEWS_DELETED
@ SBI_NEWS_DELETED
abort current news display (active news were deleted)
Definition statusbar_gui.h:19
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
_current_text_dir
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
strings_func.h
Functions related to OTTD's strings.
TD_RTL
@ TD_RTL
Text is written right-to-left by default.
Definition strings_type.h:24
AutoRestoreBackup
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Definition backup_type.hpp:150
ClientSettings::gui
GUISettings gui
settings related to the GUI
Definition settings_type.h:610
CursorVars::fix_at
bool fix_at
mouse is moving, but cursor is not (used for scrolling)
Definition gfx_type.h:128
CursorVars::pos
Point pos
logical mouse position
Definition gfx_type.h:125
CursorVars::in_window
bool in_window
mouse inside this window, determines drawing logic
Definition gfx_type.h:147
CursorVars::wheel
int wheel
mouse wheel movement
Definition gfx_type.h:127
CursorVars::delta
Point delta
relative mouse movement in this tick
Definition gfx_type.h:126
DrawPixelInfo
Data about how and where to blit pixels.
Definition gfx_type.h:157
GUISettings::window_snap_radius
uint8_t window_snap_radius
windows snap at each other if closer than this
Definition settings_type.h:163
GUISettings::hover_delay_ms
uint16_t hover_delay_ms
time required to activate a hover event, in milliseconds
Definition settings_type.h:149
GUISettings::auto_scrolling
uint8_t auto_scrolling
scroll when moving mouse to the edge (see ViewportAutoscrolling)
Definition settings_type.h:147
GUISettings::scroll_mode
uint8_t scroll_mode
viewport scroll mode
Definition settings_type.h:153
GUISettings::right_click_wnd_close
RightClickClose right_click_wnd_close
close window with right click
Definition settings_type.h:180
GUISettings::window_soft_limit
uint8_t window_soft_limit
soft limit of maximum number of non-stickied non-vital windows (0 = no limit)
Definition settings_type.h:164
GUISettings::toolbar_pos
uint8_t toolbar_pos
position of toolbars, 0=left, 1=center, 2=right
Definition settings_type.h:161
GUISettings::statusbar_pos
uint8_t statusbar_pos
position of statusbar, 0=left, 1=center, 2=right
Definition settings_type.h:162
GUISettings::scrollwheel_scrolling
uint8_t scrollwheel_scrolling
scrolling using the scroll wheel?
Definition settings_type.h:177
HotkeyList
List of hotkeys for a window.
Definition hotkeys.h:37
HotkeyList::CheckMatch
int CheckMatch(uint16_t keycode, bool global_only=false) const
Check if a keycode is bound to something.
Definition hotkeys.cpp:309
IniFile
Ini file that supports both loading and saving.
Definition ini_type.h:88
IniFile::SaveToDisk
bool SaveToDisk(const std::string &filename)
Save the Ini file's data to the disk.
Definition ini.cpp:42
IniLoadFile::LoadFromDisk
void LoadFromDisk(const std::string &filename, Subdirectory subdir)
Load the Ini file's data from the disk.
Definition ini_load.cpp:187
NewGrfDebugSpritePicker::mode
NewGrfDebugSpritePickerMode mode
Current state.
Definition newgrf_debug.h:26
NewGrfDebugSpritePicker::clicked_pixel
void * clicked_pixel
Clicked pixel (pointer to blitter buffer)
Definition newgrf_debug.h:27
NewGrfDebugSpritePicker::sprites
std::vector< SpriteID > sprites
Sprites found.
Definition newgrf_debug.h:28
Point
Coordinates of a point in 2D.
Definition geometry_type.hpp:21
Pool::PoolItem<&_vehicle_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition pool_type.hpp:339
QueryString
Data stored about a string that can be modified in the GUI.
Definition querystring_gui.h:20
QueryString::ok_button
int ok_button
Widget button of parent window to simulate when pressing OK in OSK.
Definition querystring_gui.h:27
QueryString::ACTION_DESELECT
static const int ACTION_DESELECT
Deselect editbox.
Definition querystring_gui.h:23
QueryString::cancel_button
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
Definition querystring_gui.h:28
QueryString::GetCharAtPosition
ptrdiff_t GetCharAtPosition(const Window *w, WidgetID wid, const Point &pt) const
Get the character that is rendered at a position.
Definition misc_gui.cpp:898
QueryString::GetBoundingRect
Rect GetBoundingRect(const Window *w, WidgetID wid, const char *from, const char *to) const
Get the bounding rectangle for a range of the query string.
Definition misc_gui.cpp:868
QueryString::ACTION_NOTHING
static const int ACTION_NOTHING
Nothing.
Definition querystring_gui.h:22
QueryString::ACTION_CLEAR
static const int ACTION_CLEAR
Clear editbox.
Definition querystring_gui.h:24
QueryString::GetCaretPosition
Point GetCaretPosition(const Window *w, WidgetID wid) const
Get the current caret position.
Definition misc_gui.cpp:840
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition geometry_type.hpp:75
Rect::Height
int Height() const
Get height of Rect.
Definition geometry_type.hpp:91
ResizeInfo::step_height
uint step_height
Step-size of height resize changes.
Definition window_gui.h:214
ResizeInfo::step_width
uint step_width
Step-size of width resize changes.
Definition window_gui.h:213
Textbuf
Helper/buffer for input fields.
Definition textbuf_type.h:30
Textbuf::UpdateSize
void UpdateSize()
Update Textbuf type with its actual physical character and screenlength Get the count of characters i...
Definition textbuf.cpp:463
Textbuf::DeleteAll
void DeleteAll()
Delete every character in the textbuffer.
Definition textbuf.cpp:114
Textbuf::InsertString
bool InsertString(const char *str, bool marked, const char *caret=nullptr, const char *insert_location=nullptr, const char *replacement_end=nullptr)
Insert a string into the text buffer.
Definition textbuf.cpp:160
Textbuf::bytes
uint16_t bytes
the current size of the string in bytes (including terminating '\0')
Definition textbuf_type.h:35
TileHighlightData::GetCallbackWnd
Window * GetCallbackWnd()
Get the window that started the current highlighting.
Definition viewport.cpp:2588
TileHighlightData::window_class
WindowClass window_class
The WindowClass of the window that is responsible for the selection mode.
Definition tilehighlight_type.h:68
TileHighlightData::Reset
void Reset()
Reset tile highlighting.
Definition viewport.cpp:2567
TileHighlightData::selend
Point selend
The location where the drag currently ends.
Definition tilehighlight_type.h:61
TileHighlightData::window_number
WindowNumber window_number
The WindowNumber of the window that is responsible for the selection mode.
Definition tilehighlight_type.h:69
Vehicle
Vehicle data structure.
Definition vehicle_base.h:244
Vehicle::z_pos
int32_t z_pos
z coordinate.
Definition vehicle_base.h:306
Vehicle::y_pos
int32_t y_pos
y coordinate.
Definition vehicle_base.h:305
Vehicle::x_pos
int32_t x_pos
x coordinate.
Definition vehicle_base.h:304
ViewportData::dest_scrollpos_y
int32_t dest_scrollpos_y
Current destination y coordinate to display (virtual screen coordinate of topleft corner of the viewp...
Definition window_gui.h:257
ViewportData::dest_scrollpos_x
int32_t dest_scrollpos_x
Current destination x coordinate to display (virtual screen coordinate of topleft corner of the viewp...
Definition window_gui.h:256
ViewportData::follow_vehicle
VehicleID follow_vehicle
VehicleID to follow if following a vehicle, INVALID_VEHICLE otherwise.
Definition window_gui.h:253
Viewport
Data structure for viewport, display of a part of the world.
Definition viewport_type.h:22
Viewport::top
int top
Screen coordinate top edge of the viewport.
Definition viewport_type.h:24
Viewport::width
int width
Screen width of the viewport.
Definition viewport_type.h:25
Viewport::zoom
ZoomLevel zoom
The zoom level of the viewport.
Definition viewport_type.h:33
Viewport::left
int left
Screen coordinate left edge of the viewport.
Definition viewport_type.h:23
Viewport::height
int height
Screen height of the viewport.
Definition viewport_type.h:26
WindowDesc
High level window description.
Definition window_gui.h:159
WindowDesc::flags
uint32_t flags
Flags.
Definition window_gui.h:173
WindowDesc::GetDefaultWidth
int16_t GetDefaultWidth() const
Determine default width of window.
Definition window.cpp:137
WindowDesc::SaveToConfig
static void SaveToConfig()
Save all WindowDesc settings to _windows_file.
Definition window.cpp:177
WindowDesc::pref_width
int16_t pref_width
User-preferred width of the window. Zero if unset.
Definition window_gui.h:178
WindowDesc::pref_sticky
bool pref_sticky
Preferred stickyness.
Definition window_gui.h:177
WindowDesc::hotkeys
HotkeyList * hotkeys
Hotkeys for the window.
Definition window_gui.h:175
WindowDesc::pref_height
int16_t pref_height
User-preferred height of the window. Zero if unset.
Definition window_gui.h:179
WindowDesc::GetDefaultHeight
int16_t GetDefaultHeight() const
Determine default height of window.
Definition window.cpp:147
WindowDesc::cls
WindowClass cls
Class of the window,.
Definition window_gui.h:170
WindowDesc::WindowDesc
WindowDesc(WindowPosition default_pos, const char *ini_key, int16_t def_width_trad, int16_t def_height_trad, WindowClass window_class, WindowClass parent_class, uint32_t flags, const std::span< const NWidgetPart > nwid_parts, HotkeyList *hotkeys=nullptr, const std::source_location location=std::source_location::current())
Window description constructor.
Definition window.cpp:105
WindowDesc::default_pos
WindowPosition default_pos
Preferred position of the window.
Definition window_gui.h:169
WindowDesc::ini_key
const char * ini_key
Key to store window defaults in openttd.cfg. nullptr if nothing shall be stored.
Definition window_gui.h:172
WindowDesc::default_height_trad
int16_t default_height_trad
Preferred initial height of the window (pixels at 1x zoom).
Definition window_gui.h:189
WindowDesc::parent_cls
WindowClass parent_cls
Class of the parent window.
Definition window_gui.h:171
WindowDesc::default_width_trad
int16_t default_width_trad
Preferred initial width of the window (pixels at 1x zoom).
Definition window_gui.h:188
WindowDesc::LoadFromConfig
static void LoadFromConfig()
Load all WindowDesc settings from _windows_file.
Definition window.cpp:155
WindowDesc::nwid_parts
const std::span< const NWidgetPart > nwid_parts
Span of nested widget parts describing the window.
Definition window_gui.h:174
Window::WindowIterator
Iterator to iterate all valid Windows.
Definition window_gui.h:868
Window
Data structure for an opened window.
Definition window_gui.h:273
Window::GetFocusedTextbuf
virtual const struct Textbuf * GetFocusedTextbuf() const
Get the current input text buffer.
Definition window.cpp:365
Window::SetWidgetHighlight
void SetWidgetHighlight(WidgetID widget_index, TextColour highlighted_colour)
Sets the highlighted status of a widget.
Definition window.cpp:242
Window::ReInit
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:952
Window::Close
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1047
Window::OnInvalidateData
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Definition window_gui.h:786
Window::FinishInitNested
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1733
Window::querystrings
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:320
Window::ApplyDefaults
virtual void ApplyDefaults()
Read default values from WindowDesc configuration an apply them to the window.
Definition window.cpp:194
Window::white_border_timer
uint8_t white_border_timer
Timer value of the WF_WHITE_BORDER for flags.
Definition window_gui.h:307
Window::shade_select
NWidgetStacked * shade_select
Selection widget (NWID_SELECTION) to use for shading the window. If nullptr, window cannot shade.
Definition window_gui.h:323
Window::InitializePositionSize
void InitializePositionSize(int x, int y, int min_width, int min_height)
Set the position and smallest size of the window.
Definition window.cpp:1402
Window::unshaded_size
Dimension unshaded_size
Last known unshaded size (only valid while shaded).
Definition window_gui.h:324
Window::InvalidateData
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3159
Window::OnKeyPress
virtual EventState OnKeyPress(char32_t key, uint16_t keycode)
A key has been pressed.
Definition window_gui.h:652
Window::parent
Window * parent
Parent window.
Definition window_gui.h:328
Window::IterateFromBack
AllWindows< false > IterateFromBack
Iterate all windows in Z order from back to front.
Definition window_gui.h:928
Window::~Window
virtual ~Window()
Remove window and all its child windows from the window stack.
Definition window.cpp:1084
Window::RaiseWidget
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:475
Window::SetWidgetDirty
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:551
Window::timeout_timer
uint8_t timeout_timer
Timer value of the WF_TIMEOUT for flags.
Definition window_gui.h:306
Window::mouse_capture_widget
WidgetID mouse_capture_widget
ID of current mouse capture widget (e.g. dragged scrollbar). -1 if no widget has mouse capture.
Definition window_gui.h:326
Window::OnGameTick
virtual void OnGameTick()
Called once per (game) tick.
Definition window_gui.h:739
Window::ShowNewGRFInspectWindow
virtual void ShowNewGRFInspectWindow() const
Show the NewGRF inspection window.
Definition window_gui.h:861
Window::OnRightClick
virtual bool OnRightClick(Point pt, WidgetID widget)
A click with the right mouse button has been made on the window.
Definition window_gui.h:679
Window::ProcessScheduledInvalidations
void ProcessScheduledInvalidations()
Process all scheduled invalidations.
Definition window.cpp:3172
Window::CloseChildWindows
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1035
Window::resize
ResizeInfo resize
Resize information.
Definition window_gui.h:314
Window::UnfocusFocusedWidget
void UnfocusFocusedWidget()
Makes no widget on this window have focus.
Definition window.cpp:470
Window::OnMouseLoop
virtual void OnMouseLoop()
Called for every mouse loop run, which is at least once per (game) tick.
Definition window_gui.h:734
Window::SetShaded
void SetShaded(bool make_shaded)
Set the shaded state of the window to make_shaded.
Definition window.cpp:995
Window::scale
int scale
Scale of this window – used to determine how to resize.
Definition window_gui.h:304
Window::ScheduleResize
void ScheduleResize()
Mark this window as resized and in need of OnResize() event.
Definition window.cpp:3137
Window::OnPaint
virtual void OnPaint()
The window must be repainted.
Definition window_gui.h:599
Window::OnDragDrop
virtual void OnDragDrop(Point pt, WidgetID widget)
A dragged 'object' has been released.
Definition window_gui.h:708
Window::CreateNestedTree
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1723
Window::window_desc
WindowDesc & window_desc
Window description.
Definition window_gui.h:299
Window::window_class
WindowClass window_class
Window class.
Definition window_gui.h:301
Window::OnRealtimeTick
virtual void OnRealtimeTick(uint delta_ms)
Called periodically.
Definition window_gui.h:744
Window::IterateFromFront
AllWindows< true > IterateFromFront
Iterate all windows in Z order from front to back.
Definition window_gui.h:929
Window::viewport
ViewportData * viewport
Pointer to viewport data, if present.
Definition window_gui.h:318
Window::SetWhiteBorder
void SetWhiteBorder()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:370
Window::SetFocusedWidget
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:486
Window::OnFocusLost
virtual void OnFocusLost(bool closing)
The window has lost focus.
Definition window.cpp:516
Window::OnDropdownClose
virtual void OnDropdownClose(Point pt, WidgetID widget, int index, bool instant_close)
A dropdown window associated to this window has been closed.
Definition window.cpp:287
Window::closed_windows
static std::vector< Window * > closed_windows
List of closed windows to delete.
Definition window_gui.h:275
Window::RaiseButtons
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition window.cpp:525
Window::OnInitialPosition
virtual Point OnInitialPosition(int16_t sm_width, int16_t sm_height, int window_number)
Compute the initial position of the window.
Definition window.cpp:1711
Window::owner
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:316
Window::OnDropdownSelect
virtual void OnDropdownSelect(WidgetID widget, int index)
A dropdown option associated to this window has been selected.
Definition window_gui.h:763
Window::OnMouseWheel
virtual void OnMouseWheel(int wheel)
The mouse wheel has been turned.
Definition window_gui.h:728
Window::GetCaretPosition
virtual Point GetCaretPosition() const
Get the current caret position if an edit box has the focus.
Definition window.cpp:378
Window::left
int left
x position of left edge of the window
Definition window_gui.h:309
Window::IsShaded
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:563
Window::FindChildWindow
Window * FindChildWindow(WindowClass wc=WC_INVALID) const
Find the Window whose parent pointer points to this window.
Definition window.cpp:1022
Window::SetTimeout
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:361
Window::nested_focus
const NWidgetCore * nested_focus
Currently focused nested widget, or nullptr if no nested widget has focus.
Definition window_gui.h:319
Window::OnEditboxChanged
virtual void OnEditboxChanged(WidgetID widget)
The text in an editbox has been edited.
Definition window_gui.h:771
Window::UpdateQueryStringSize
void UpdateQueryStringSize()
Update size of all QueryStrings of this window.
Definition window.cpp:354
Window::OnScroll
virtual void OnScroll(Point delta)
Handle the request for (viewport) scrolling.
Definition window_gui.h:714
Window::top
int top
y position of top edge of the window
Definition window_gui.h:310
Window::OnClick
virtual void OnClick(Point pt, WidgetID widget, int click_count)
A click with the left mouse button has been made on the window.
Definition window_gui.h:670
Window::GetQueryString
const QueryString * GetQueryString(WidgetID widnum) const
Return the querystring associated to a editbox.
Definition window.cpp:334
Window::widget_lookup
WidgetLookup widget_lookup
Indexed access to the nested widget tree. Do not access directly, use Window::GetWidget() instead.
Definition window_gui.h:322
Window::GetTextCharacterAtPosition
virtual ptrdiff_t GetTextCharacterAtPosition(const Point &pt) const
Get the character that is rendered at a position by the focused edit box.
Definition window.cpp:409
Window::scheduled_invalidation_data
std::vector< int > scheduled_invalidation_data
Data of scheduled OnInvalidateData() calls.
Definition window_gui.h:282
Window::InitializeData
void InitializeData(WindowNumber window_number)
Initializes the data (except the position and initial size) of a new Window.
Definition window.cpp:1364
Window::OnMouseOver
virtual void OnMouseOver(Point pt, WidgetID widget)
The mouse is currently moving over the window or has just moved outside of the window.
Definition window_gui.h:722
Window::Window
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1756
Window::GetRowFromWidget
int GetRowFromWidget(int clickpos, WidgetID widget, int padding, int line_height=-1) const
Compute the row of a widget that a user clicked in.
Definition window.cpp:213
Window::GetWidget
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:977
Window::OnTooltip
virtual bool OnTooltip(Point pt, WidgetID widget, TooltipCloseCondition close_cond)
Event to display a custom tooltip.
Definition window_gui.h:694
Window::LowerWidget
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:466
Window::OnCTRLStateChange
virtual EventState OnCTRLStateChange()
The state of the control key has changed.
Definition window_gui.h:661
Window::ProcessScheduledResize
void ProcessScheduledResize()
Process scheduled OnResize() event.
Definition window.cpp:3145
Window::HandleEditBoxKey
EventState HandleEditBoxKey(WidgetID wid, char32_t key, uint16_t keycode)
Process keypress for editbox widget.
Definition window.cpp:2480
Window::InsertTextString
virtual void InsertTextString(WidgetID wid, const char *str, bool marked, const char *caret, const char *insert_location, const char *replacement_end)
Insert a text string at the cursor position into the edit box widget.
Definition window.cpp:2638
Window::OnMouseDrag
virtual void OnMouseDrag(Point pt, WidgetID widget)
An 'object' is being dragged at the provided position, highlight the target if possible.
Definition window_gui.h:701
Window::HandleButtonClick
void HandleButtonClick(WidgetID widget)
Do all things to make a button look clicked and mark it to be unclicked in a few ticks.
Definition window.cpp:590
Window::OnResize
virtual void OnResize()
Called after the window got resized.
Definition window_gui.h:756
Window::OnFocus
virtual void OnFocus()
The window has gained focus.
Definition window.cpp:508
Window::InitNested
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1746
Window::OnTimeout
virtual void OnTimeout()
Called when this window's timeout has been reached.
Definition window_gui.h:749
Window::flags
WindowFlags flags
Window flags.
Definition window_gui.h:300
Window::GetScrollbar
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:314
Window::ProcessHighlightedInvalidations
void ProcessHighlightedInvalidations()
Process all invalidation of highlighted widgets.
Definition window.cpp:3184
Window::GetTextBoundingRect
virtual Rect GetTextBoundingRect(const char *from, const char *to) const
Get the bounding rectangle for a text range if an edit box has the focus.
Definition window.cpp:394
Window::OnHotkey
virtual EventState OnHotkey(int hotkey)
A hotkey has been pressed.
Definition window.cpp:565
Window::DeleteClosedWindows
static void DeleteClosedWindows()
Delete all closed windows.
Definition window.cpp:65
Window::nested_root
std::unique_ptr< NWidgetBase > nested_root
Root of the nested tree.
Definition window_gui.h:321
Window::scheduled_resize
bool scheduled_resize
Set if window has been resized.
Definition window_gui.h:283
Window::IsWidgetHighlighted
bool IsWidgetHighlighted(WidgetID widget_index) const
Gets the highlighted status of a widget.
Definition window.cpp:272
Window::DisableAllWidgetHighlight
void DisableAllWidgetHighlight()
Disable the highlighted status of all widgets.
Definition window.cpp:224
Window::OnPlacePresize
virtual void OnPlacePresize(Point pt, TileIndex tile)
The user moves over the map when a tile highlight mode has been set when the special mouse mode has b...
Definition window_gui.h:845
Window::Iterate
AllWindows< false > Iterate
Iterate all windows in whatever order is easiest.
Definition window_gui.h:927
Window::height
int height
Height of the window (number of pixels down in y direction)
Definition window_gui.h:312
Window::OnHover
virtual void OnHover(Point pt, WidgetID widget)
The mouse is hovering over a widget in the window, perform an action for it.
Definition window_gui.h:686
Window::width
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:311
Window::OnInit
virtual void OnInit()
Notification that the nested widget tree gets initialized.
Definition window_gui.h:582
Window::FindWindowPlacementAndResize
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
Definition window.cpp:1420
Window::window_number
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
_window_descs
std::vector< WindowDesc * > * _window_descs
List of WindowDescs.
Definition window.cpp:99
HKPR_NOT_HANDLED
@ HKPR_NOT_HANDLED
Key does not affect editboxes.
Definition textbuf_type.h:26
HKPR_CANCEL
@ HKPR_CANCEL
Escape key pressed.
Definition textbuf_type.h:25
HKPR_EDITING
@ HKPR_EDITING
Textbuf content changed.
Definition textbuf_type.h:22
HKPR_CONFIRM
@ HKPR_CONFIRM
Return or enter key pressed.
Definition textbuf_type.h:24
HKPR_CURSOR
@ HKPR_CURSOR
Non-text change, e.g. cursor position.
Definition textbuf_type.h:23
tilehighlight_func.h
Functions related to tile highlights.
ResetObjectToPlace
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
Definition viewport.cpp:3498
UpdateTileSelection
void UpdateTileSelection()
Updates tile highlighting for all cases.
Definition viewport.cpp:2602
timer.h
Definition of Interval and OneShot timers.
timer_window.h
Definition of the Window system.
_toolbar_width
uint _toolbar_width
Width of the toolbar, shared by statusbar.
Definition toolbar_gui.cpp:74
toolbar_gui.h
Stuff related to the (main) toolbar.
vehicle_base.h
Base class for all vehicles.
VehicleID
uint32_t VehicleID
The type all our vehicle IDs have.
Definition vehicle_type.h:16
INVALID_VEHICLE
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition vehicle_type.h:54
video_driver.hpp
Base of all video drivers.
IsPtInWindowViewport
Viewport * IsPtInWindowViewport(const Window *w, int x, int y)
Is a xy position inside the viewport of the window?
Definition viewport.cpp:411
UpdateViewportPosition
void UpdateViewportPosition(Window *w, uint32_t delta_ms)
Update the viewport position being displayed.
Definition viewport.cpp:1916
viewport_func.h
Functions related to (drawing on) viewports.
SetupWidgetDimensions
void SetupWidgetDimensions()
Set up pre-scaled versions of Widget Dimensions.
Definition widget.cpp:66
GetWidgetFromPos
WidgetID GetWidgetFromPos(const Window *w, int x, int y)
Returns the index for the widget located at the given position relative to the window.
Definition widget.cpp:268
ScrollbarClickHandler
void ScrollbarClickHandler(Window *w, NWidgetCore *nw, int x, int y)
Special handling for the scrollbar widget type.
Definition widget.cpp:244
ScaleGUITrad
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:35
SZSP_HORIZONTAL
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
Definition widget_type.h:483
ND_SCROLLBAR_UP
@ ND_SCROLLBAR_UP
Bit value of the 'scrollbar up' flag.
Definition widget_type.h:360
NDB_SCROLLBAR_UP
@ NDB_SCROLLBAR_UP
Up-button is lowered bit.
Definition widget_type.h:347
ND_SCROLLBAR_BTN
@ ND_SCROLLBAR_BTN
Bit value of the 'scrollbar up' or 'scrollbar down' flag.
Definition widget_type.h:362
NDB_DROPDOWN_CLOSED
@ NDB_DROPDOWN_CLOSED
Dropdown menu of the dropdown widget has closed.
Definition widget_type.h:351
ND_SCROLLBAR_DOWN
@ ND_SCROLLBAR_DOWN
Bit value of the 'scrollbar down' flag.
Definition widget_type.h:361
WidgetType
WidgetType
Window widget types, nested widget types, and nested widget part types.
Definition widget_type.h:46
NWID_BUTTON_DROPDOWN
@ NWID_BUTTON_DROPDOWN
Button with a drop-down.
Definition widget_type.h:83
WWT_EDITBOX
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:71
WWT_STICKYBOX
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:66
WWT_SHADEBOX
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:64
WWT_CAPTION
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:61
NWID_VSCROLLBAR
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:85
WWT_CLOSEBOX
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:69
WWT_EMPTY
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:48
WWT_LAST
@ WWT_LAST
Last Item. use WIDGETS_END to fill up padding!!
Definition widget_type.h:72
NWID_HSCROLLBAR
@ NWID_HSCROLLBAR
Horizontal scrollbar.
Definition widget_type.h:84
WWT_RESIZEBOX
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:68
WWT_DEFSIZEBOX
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:65
WWT_DEBUGBOX
@ WWT_DEBUGBOX
NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX)
Definition widget_type.h:63
ST_RESIZE
@ ST_RESIZE
Resize the nested widget tree.
Definition widget_type.h:122
ST_SMALLEST
@ ST_SMALLEST
Initialize nested widget tree to smallest size. Also updates current_x and current_y.
Definition widget_type.h:121
PositionStatusbar
int PositionStatusbar(Window *w)
(Re)position statusbar window at the screen.
Definition window.cpp:3401
white_border_interval
static IntervalTimer< TimerWindow > white_border_interval(std::chrono::milliseconds(30), [](auto) { if(_network_dedicated) return;for(Window *w :Window::Iterate()) { if((w->flags &WF_WHITE_BORDER) &&--w->white_border_timer==0) { CLRBITS(w->flags, WF_WHITE_BORDER);w->SetDirty();} } })
Blink all windows marked with a white border.
PreventHiding
static void PreventHiding(int *nx, int *ny, const Rect &rect, const Window *v, int px, PreventHideDirection dir)
Do not allow hiding of the rectangle with base coordinates nx and ny behind window v.
Definition window.cpp:1945
_dragging_window
static bool _dragging_window
A window is being dragged or resized.
Definition window.cpp:2079
CloseConstructionWindows
void CloseConstructionWindows()
Close all windows that are used for construction of vehicle etc.
Definition window.cpp:3305
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1140
LocalGetWindowPlacement
static Point LocalGetWindowPlacement(const WindowDesc &desc, int16_t sm_width, int16_t sm_height, int window_number)
Compute the position of the top-left corner of a new window that is opened.
Definition window.cpp:1652
GetMainWindow
Window * GetMainWindow()
Get the main window, i.e.
Definition window.cpp:1127
_drag_delta
static Point _drag_delta
delta between mouse cursor and upper left corner of dragged window
Definition window.cpp:52
MayBeShown
static bool MayBeShown(const Window *w)
Returns whether a window may be shown or not.
Definition window.cpp:829
CloseCompanyWindows
void CloseCompanyWindows(CompanyID id)
Close all windows of a company.
Definition window.cpp:1168
HandleCtrlChanged
void HandleCtrlChanged()
State of CONTROL key has changed.
Definition window.cpp:2625
DrawOverlappedWindow
static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom)
Generate repaint events for the visible part of window w within the rectangle.
Definition window.cpp:857
_scrolling_viewport
bool _scrolling_viewport
A viewport is being scrolled with the mouse.
Definition window.cpp:90
InputLoop
void InputLoop()
Regular call from the global game loop.
Definition window.cpp:2993
UpdateWindows
void UpdateWindows()
Update the continuously changing contents of the windows, such as the viewports.
Definition window.cpp:3056
PositionMainToolbar
int PositionMainToolbar(Window *w)
(Re)position main toolbar window at the screen.
Definition window.cpp:3390
CloseNonVitalWindows
void CloseNonVitalWindows()
Try to close a non-vital window.
Definition window.cpp:3261
DrawOverlappedWindowForAll
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
From a rectangle that needs redrawing, find the windows that intersect with the rectangle.
Definition window.cpp:919
ResizeWindow
void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen, bool schedule_resize)
Resize the window.
Definition window.cpp:2022
IsGoodAutoPlace2
static bool IsGoodAutoPlace2(int left, int top, int width, int height, int toolbar_y, Point &pos)
Decide whether a given rectangle is a good place to open a mostly visible new window.
Definition window.cpp:1520
PositionNetworkChatWindow
int PositionNetworkChatWindow(Window *w)
(Re)position network chat window at the screen.
Definition window.cpp:3423
StartWindowSizing
static void StartWindowSizing(Window *w, bool to_left)
Start resizing a window.
Definition window.cpp:2273
GetAutoPlacePosition
static Point GetAutoPlacePosition(int width, int height)
Find a good place for opening a new window of a given width and height.
Definition window.cpp:1559
HandleAutoscroll
static void HandleAutoscroll()
If needed and switched on, perform auto scrolling (automatically moving window contents when mouse is...
Definition window.cpp:2674
_window_highlight_colour
bool _window_highlight_colour
If false, highlight is white, otherwise the by the widget defined colour.
Definition window.cpp:75
HandleToolbarHotkey
void HandleToolbarHotkey(int hotkey)
Handle Toolbar hotkey events - can come from a source like the MacBook Touch Bar.
Definition window.cpp:2552
PositionWindow
static int PositionWindow(Window *w, WindowClass clss, int setting)
(Re)position a window at the screen.
Definition window.cpp:3367
SetFocusedWindow
void SetFocusedWindow(Window *w)
Set the window that has the focus.
Definition window.cpp:422
IsGoodAutoPlace1
static bool IsGoodAutoPlace1(int left, int top, int width, int height, int toolbar_y, Point &pos)
Decide whether a given rectangle is a good place to open a completely visible new window.
Definition window.cpp:1484
MAX_OFFSET_DOUBLE_CLICK
static constexpr int MAX_OFFSET_DOUBLE_CLICK
How much the mouse is allowed to move to call it a double click.
Definition window.cpp:2719
_input_events_this_tick
static int _input_events_this_tick
Local counter that is incremented each time an mouse input event is detected.
Definition window.cpp:2668
FindWindowByClass
Window * FindWindowByClass(WindowClass cls)
Find any window by its class.
Definition window.cpp:1113
ChangeVehicleViewports
void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index)
Switches viewports following vehicles, which get autoreplaced.
Definition window.cpp:3435
TIME_BETWEEN_DOUBLE_CLICK
const std::chrono::milliseconds TIME_BETWEEN_DOUBLE_CLICK(500)
Time between 2 left clicks before it becoming a double click.
HandleViewportScroll
static EventState HandleViewportScroll()
Handle viewport scrolling with the mouse.
Definition window.cpp:2356
DispatchMouseWheelEvent
static void DispatchMouseWheelEvent(Window *w, NWidgetCore *nwid, int wheel)
Dispatch the mousewheel-action to the window.
Definition window.cpp:798
DispatchLeftClickEvent
static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count)
Dispatch left mouse-button (possibly double) click in window.
Definition window.cpp:607
FindWindowFromPt
Window * FindWindowFromPt(int x, int y)
Do a search for a window at specific coordinates.
Definition window.cpp:1768
highlight_interval
static IntervalTimer< TimerWindow > highlight_interval(std::chrono::milliseconds(450), [](auto) { _window_highlight_colour=!_window_highlight_colour;})
Blink the window highlight colour constantly.
DeleteAllMessages
void DeleteAllMessages()
Delete all messages and close their corresponding window (if any).
Definition window.cpp:3293
_last_scroll_window
static Window * _last_scroll_window
Window of the last scroll event.
Definition window.cpp:54
GetMainViewTop
int GetMainViewTop()
Return the top of the main view available for general use.
Definition window.cpp:2062
BringWindowToFront
static void BringWindowToFront(Window *w, bool dirty=true)
On clicking on a window, make it the frontmost window of all windows with an equal or lower z-priorit...
Definition window.cpp:1344
ReInitAllWindows
void ReInitAllWindows(bool zoom_changed)
Re-initialize all windows.
Definition window.cpp:3335
EnsureVisibleCaption
static void EnsureVisibleCaption(Window *w, int nx, int ny)
Make sure at least a part of the caption bar is still visible by moving the window if necessary.
Definition window.cpp:1985
CloseWindowByClass
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1152
HandleMouseEvents
void HandleMouseEvents()
Handle a mouse event from the video driver.
Definition window.cpp:2885
GetToolbarAlignedWindowPosition
Point GetToolbarAlignedWindowPosition(int window_width)
Computer the position of the top-left corner of a window to be opened right under the toolbar.
Definition window.cpp:1627
HandleWindowDragging
static EventState HandleWindowDragging()
Handle dragging/resizing of a window.
Definition window.cpp:2085
PositionNewsMessage
int PositionNewsMessage(Window *w)
(Re)position news message window at the screen.
Definition window.cpp:3412
GetMainViewBottom
int GetMainViewBottom()
Return the bottom of the main view available for general use.
Definition window.cpp:2073
DispatchHoverEvent
static void DispatchHoverEvent(Window *w, int x, int y)
Dispatch hover of the mouse over a window.
Definition window.cpp:770
ChangeWindowOwner
void ChangeWindowOwner(Owner old_owner, Owner new_owner)
Change the owner of all the windows one company can take over from another company in the case of a c...
Definition window.cpp:1188
HandleKeypress
void HandleKeypress(uint keycode, char32_t key)
Handle keyboard input.
Definition window.cpp:2569
SetWindowClassesDirty
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3127
HandleTextInput
void HandleTextInput(const char *str, bool marked, const char *caret, const char *insert_location, const char *replacement_end)
Handle text input.
Definition window.cpp:2655
VpHandlePlaceSizingDrag
EventState VpHandlePlaceSizingDrag()
Handle the mouse while dragging for placement/resizing.
Definition viewport.cpp:3381
PreventHideDirection
PreventHideDirection
Direction for moving the window.
Definition window.cpp:1930
PHD_DOWN
@ PHD_DOWN
Below v is a safe position.
Definition window.cpp:1932
PHD_UP
@ PHD_UP
Above v is a safe position.
Definition window.cpp:1931
MAX_OFFSET_HOVER
static constexpr int MAX_OFFSET_HOVER
Maximum mouse movement before stopping a hover event.
Definition window.cpp:2720
FocusedWindowIsConsole
bool FocusedWindowIsConsole()
Check if a console is focused.
Definition window.cpp:462
ResetWindowSystem
void ResetWindowSystem()
Reset the windowing system, by means of shutting it down followed by re-initialization.
Definition window.cpp:1818
GetWindowZPriority
static uint GetWindowZPriority(WindowClass wc)
Get the z-priority for a given window.
Definition window.cpp:1260
EditBoxInGlobalFocus
bool EditBoxInGlobalFocus()
Check if an edit box is in global focus.
Definition window.cpp:448
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3219
HideVitalWindows
void HideVitalWindows()
Close all always on-top windows to get an empty screen.
Definition window.cpp:3318
window_interval
static IntervalTimer< TimerWindow > window_interval(std::chrono::milliseconds(30), [](auto) { extern int _caret_timer;_caret_timer+=3;CursorTick();HandleKeyScrolling();HandleAutoscroll();DecreaseWindowCounters();})
Update various of window-related information on a regular interval.
DescSorter
static bool DescSorter(WindowDesc *const &a, WindowDesc *const &b)
Sort WindowDesc by ini_key.
Definition window.cpp:168
BringWindowToFrontById
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1223
RelocateAllWindows
void RelocateAllWindows(int neww, int newh)
Relocate all windows to fit the new size of the game application screen.
Definition window.cpp:3451
_windows_file
std::string _windows_file
Config file to store WindowDesc.
Definition window.cpp:102
HandleScrollbarScrolling
static void HandleScrollbarScrolling(Window *w)
Handle scrollbar scrolling with the mouse.
Definition window.cpp:2289
_mouse_hovering
bool _mouse_hovering
The mouse is hovering over the same point.
Definition window.cpp:91
StartWindowDrag
static void StartWindowDrag(Window *w)
Start window dragging.
Definition window.cpp:2256
CallWindowGameTickEvent
void CallWindowGameTickEvent()
Dispatch OnGameTick event over all windows.
Definition window.cpp:3248
HandleActiveWidget
static EventState HandleActiveWidget()
Handle active widget (mouse draggin on widget) with the mouse.
Definition window.cpp:2323
_window_descs
std::vector< WindowDesc * > * _window_descs
List of all WindowDescs.
Definition window.cpp:99
DispatchRightClickEvent
static void DispatchRightClickEvent(Window *w, int x, int y)
Dispatch right mouse-button click in window.
Definition window.cpp:741
scrollamt
static const int8_t scrollamt[16][2]
Describes all the different arrow key combinations the game allows when it is in scrolling mode.
Definition window.cpp:2744
MaybeBringWindowToFront
static bool MaybeBringWindowToFront(Window *w)
Check if a window can be made relative top-most window, and if so do it.
Definition window.cpp:2420
_z_windows
WindowList _z_windows
List of windows opened at the screen sorted from the front to back.
Definition window.cpp:57
CallWindowRealtimeTickEvent
void CallWindowRealtimeTickEvent(uint delta_ms)
Dispatch OnRealtimeTick event over all windows.
Definition window.cpp:3018
_special_mouse_mode
SpecialMouseMode _special_mouse_mode
Mode of the mouse.
Definition window.cpp:93
ViewportAutoscrolling
ViewportAutoscrolling
Values for _settings_client.gui.auto_scrolling.
Definition window.cpp:45
VA_MAIN_VIEWPORT_FULLSCREEN
@ VA_MAIN_VIEWPORT_FULLSCREEN
Scroll main viewport at edge when using fullscreen.
Definition window.cpp:47
VA_MAIN_VIEWPORT
@ VA_MAIN_VIEWPORT
Scroll main viewport at edge.
Definition window.cpp:48
VA_EVERY_VIEWPORT
@ VA_EVERY_VIEWPORT
Scroll all viewports at their edges.
Definition window.cpp:49
VA_DISABLED
@ VA_DISABLED
Do not autoscroll when mouse is at edge of viewport.
Definition window.cpp:46
HandleMouseDragDrop
static EventState HandleMouseDragDrop()
Handle dragging and dropping in mouse dragging mode (WSM_DRAGDROP).
Definition window.cpp:1883
CloseAllNonVitalWindows
void CloseAllNonVitalWindows()
It is possible that a stickied window gets to a position where the 'close' button is outside the gami...
Definition window.cpp:3280
HandleMouseOver
static void HandleMouseOver()
Report position of the mouse to the underlying window.
Definition window.cpp:1907
_mouseover_last_w
static Window * _mouseover_last_w
Window of the last OnMouseOver event.
Definition window.cpp:53
CheckSoftLimit
static void CheckSoftLimit()
Check the soft limit of deletable (non vital, non sticky) windows.
Definition window.cpp:2968
FindWindowById
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1098
UnInitWindowSystem
void UnInitWindowSystem()
Close down the windowing system.
Definition window.cpp:1804
InitWindowSystem
void InitWindowSystem()
(re)initialize the windowing system
Definition window.cpp:1782
SetWindowWidgetDirty
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition window.cpp:3114
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3101
InvalidateWindowClassesData
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3236
window_func.h
Window functions not directly related to making/drawing windows.
SpecialMouseMode
SpecialMouseMode
Mouse modes.
Definition window_gui.h:1039
WSM_DRAGDROP
@ WSM_DRAGDROP
Drag&drop an object.
Definition window_gui.h:1041
WSM_PRESIZE
@ WSM_PRESIZE
Presizing mode (docks, tunnels).
Definition window_gui.h:1043
SetFocusedWindow
void SetFocusedWindow(Window *w)
Set the window that has the focus.
Definition window.cpp:422
GetWidgetFromPos
WidgetID GetWidgetFromPos(const Window *w, int x, int y)
Returns the index for the widget located at the given position relative to the window.
Definition widget.cpp:268
WF_DRAGGING
@ WF_DRAGGING
Window is being dragged.
Definition window_gui.h:230
WF_WHITE_BORDER
@ WF_WHITE_BORDER
Window white border counter bit mask.
Definition window_gui.h:236
WF_TIMEOUT
@ WF_TIMEOUT
Window timeout counter.
Definition window_gui.h:228
WF_SIZING_LEFT
@ WF_SIZING_LEFT
Window is being resized towards the left.
Definition window_gui.h:232
WF_DISABLE_VP_SCROLL
@ WF_DISABLE_VP_SCROLL
Window does not do autoscroll,.
Definition window_gui.h:235
WF_SIZING
@ WF_SIZING
Window is being resized.
Definition window_gui.h:233
WF_HIGHLIGHTED
@ WF_HIGHLIGHTED
Window has a widget that has a highlight.
Definition window_gui.h:237
WF_STICKY
@ WF_STICKY
Window is made sticky by user.
Definition window_gui.h:234
WF_SIZING_RIGHT
@ WF_SIZING_RIGHT
Window is being resized towards the right.
Definition window_gui.h:231
WF_CENTERED
@ WF_CENTERED
Window is centered and shall stay centered after ReInit.
Definition window_gui.h:238
WDF_NO_CLOSE
@ WDF_NO_CLOSE
This window can't be interactively closed.
Definition window_gui.h:206
WDF_CONSTRUCTION
@ WDF_CONSTRUCTION
This window is used for construction; close it whenever changing company.
Definition window_gui.h:203
WDF_MODAL
@ WDF_MODAL
The window is a modal child of some other window, meaning the parent is 'inactive'.
Definition window_gui.h:204
WDF_NO_FOCUS
@ WDF_NO_FOCUS
This window won't get focus/make any other window lose focus when click.
Definition window_gui.h:205
_z_windows
WindowList _z_windows
List of windows opened at the screen sorted from the front to back.
Definition window.cpp:57
WindowPosition
WindowPosition
How do we the window to be placed?
Definition window_gui.h:145
WDP_CENTER
@ WDP_CENTER
Center the window.
Definition window_gui.h:148
WDP_AUTO
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:147
WDP_ALIGN_TOOLBAR
@ WDP_ALIGN_TOOLBAR
Align toward the toolbar.
Definition window_gui.h:149
WDP_MANUAL
@ WDP_MANUAL
Manually align the window (so no automatic location finding)
Definition window_gui.h:146
WidgetID
int WidgetID
Widget ID.
Definition window_type.h:18
WindowNumber
int32_t WindowNumber
Number to differentiate different windows of the same class.
Definition window_type.h:740
EventState
EventState
State of handling an event.
Definition window_type.h:743
ES_HANDLED
@ ES_HANDLED
The passed event is handled.
Definition window_type.h:744
ES_NOT_HANDLED
@ ES_NOT_HANDLED
The passed event is not handled.
Definition window_type.h:745
WindowClass
WindowClass
Window classes.
Definition window_type.h:44
WC_INVALID
@ WC_INVALID
Invalid window.
Definition window_type.h:724
WC_OSK
@ WC_OSK
On Screen Keyboard; Window numbers:
Definition window_type.h:162
WC_CONSOLE
@ WC_CONSOLE
Console; Window numbers:
Definition window_type.h:649
WC_NEWS_WINDOW
@ WC_NEWS_WINDOW
News window; Window numbers:
Definition window_type.h:248
WC_HIGHSCORE
@ WC_HIGHSCORE
Highscore; Window numbers:
Definition window_type.h:661
WC_BUY_COMPANY
@ WC_BUY_COMPANY
Buyout company (merger); Window numbers:
Definition window_type.h:594
WC_SPRITE_ALIGNER
@ WC_SPRITE_ALIGNER
Sprite aligner (debug); Window numbers:
Definition window_type.h:686
WC_COMPANY_INFRASTRUCTURE
@ WC_COMPANY_INFRASTRUCTURE
Company infrastructure overview; Window numbers:
Definition window_type.h:587
WC_ENDSCREEN
@ WC_ENDSCREEN
Endscreen; Window numbers:
Definition window_type.h:667
WC_COMPANY_COLOUR
@ WC_COMPANY_COLOUR
Company colour selection; Window numbers:
Definition window_type.h:230
WC_STATION_LIST
@ WC_STATION_LIST
Station list; Window numbers:
Definition window_type.h:302
WC_ROADVEH_LIST
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
Definition window_type.h:314
WC_STATUS_BAR
@ WC_STATUS_BAR
Statusbar (at the bottom of your screen); Window numbers:
Definition window_type.h:64
WC_VEHICLE_ORDERS
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
Definition window_type.h:212
WC_SEND_NETWORK_MSG
@ WC_SEND_NETWORK_MSG
Chatbox; Window numbers:
Definition window_type.h:509
WC_ERRMSG
@ WC_ERRMSG
Error message; Window numbers:
Definition window_type.h:110
WC_BUILD_TOOLBAR
@ WC_BUILD_TOOLBAR
Build toolbar; Window numbers:
Definition window_type.h:73
WC_NETWORK_ASK_RELAY
@ WC_NETWORK_ASK_RELAY
Network ask relay window; Window numbers:
Definition window_type.h:497
WC_SCRIPT_SETTINGS
@ WC_SCRIPT_SETTINGS
Script settings; Window numbers:
Definition window_type.h:175
WC_NONE
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:45
WC_SCEN_LAND_GEN
@ WC_SCEN_LAND_GEN
Landscape generation (in Scenario Editor); Window numbers:
Definition window_type.h:455
WC_SCRIPT_LIST
@ WC_SCRIPT_LIST
Scripts list; Window numbers:
Definition window_type.h:284
WC_SAVE_PRESET
@ WC_SAVE_PRESET
Save preset; Window numbers:
Definition window_type.h:698
WC_SHIPS_LIST
@ WC_SHIPS_LIST
Ships list; Window numbers:
Definition window_type.h:320
WC_MESSAGE_HISTORY
@ WC_MESSAGE_HISTORY
News history list; Window numbers:
Definition window_type.h:272
WC_CONFIRM_POPUP_QUERY
@ WC_CONFIRM_POPUP_QUERY
Popup with confirm question; Window numbers:
Definition window_type.h:130
WC_GENERATE_LANDSCAPE
@ WC_GENERATE_LANDSCAPE
Generate landscape (newgame); Window numbers:
Definition window_type.h:462
WC_CUSTOM_CURRENCY
@ WC_CUSTOM_CURRENCY
Custom currency; Window numbers:
Definition window_type.h:630
WC_MAIN_WINDOW
@ WC_MAIN_WINDOW
Main window; Window numbers:
Definition window_type.h:51
WC_TRAINS_LIST
@ WC_TRAINS_LIST
Trains list; Window numbers:
Definition window_type.h:308
WC_GAME_OPTIONS
@ WC_GAME_OPTIONS
Game options window; Window numbers:
Definition window_type.h:624
WC_NETWORK_WINDOW
@ WC_NETWORK_WINDOW
Network window; Window numbers:
Definition window_type.h:478
WC_FINANCES
@ WC_FINANCES
Finances of a company; Window numbers:
Definition window_type.h:527
WC_TEXTFILE
@ WC_TEXTFILE
textfile; Window numbers:
Definition window_type.h:187
WC_DROPDOWN_MENU
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
Definition window_type.h:156
WC_QUERY_STRING
@ WC_QUERY_STRING
Query string window; Window numbers:
Definition window_type.h:123
WC_SMALLMAP
@ WC_SMALLMAP
Small map; Window numbers:
Definition window_type.h:104
WC_BOOTSTRAP
@ WC_BOOTSTRAP
Bootstrap; Window numbers:
Definition window_type.h:655
WC_SAVELOAD
@ WC_SAVELOAD
Saveload window; Window numbers:
Definition window_type.h:144
WC_GRF_PARAMETERS
@ WC_GRF_PARAMETERS
NewGRF parameters; Window numbers:
Definition window_type.h:181
WC_MODAL_PROGRESS
@ WC_MODAL_PROGRESS
Progress report of landscape generation; Window numbers:
Definition window_type.h:469
WC_MAIN_TOOLBAR
@ WC_MAIN_TOOLBAR
Main toolbar (the long bar at the top); Window numbers:
Definition window_type.h:58
WC_TOOLTIPS
@ WC_TOOLTIPS
Tooltip window; Window numbers:
Definition window_type.h:116
WC_COMPANY
@ WC_COMPANY
Company view; Window numbers:
Definition window_type.h:369
WC_NETWORK_STATUS_WINDOW
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers:
Definition window_type.h:491
WC_AIRCRAFT_LIST
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers:
Definition window_type.h:326
zoom_func.h
Functions related to zooming.
ScaleByZoom
int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZOOM_LVL_MIN) When shifting right,...
Definition zoom_func.h:22
ZOOM_LVL_MIN
@ ZOOM_LVL_MIN
Minimum zoom level.
Definition zoom_type.h:41