summaryrefslogtreecommitdiff
path: root/src/window_gui.h
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2021-05-09 17:12:34 +0200
committerfrosch <github@elsenhans.name>2021-05-12 23:22:41 +0200
commitf6d5c0136e5ac130fd887daf1b07c13a160c7fc3 (patch)
tree783aa6614c892db50681bd25f1afacfb8c7d37b7 /src/window_gui.h
parentf96f11395162a8d57f5fdcef18c7a64f7acf76f8 (diff)
downloadopenttd-f6d5c0136e5ac130fd887daf1b07c13a160c7fc3.tar.xz
Codechange: make Window destruction not rely on undefined behavior.
Diffstat (limited to 'src/window_gui.h')
-rw-r--r--src/window_gui.h67
1 files changed, 39 insertions, 28 deletions
diff --git a/src/window_gui.h b/src/window_gui.h
index 2b7c69367..1195c6c49 100644
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -10,6 +10,8 @@
#ifndef WINDOW_GUI_H
#define WINDOW_GUI_H
+#include <list>
+
#include "vehicle_type.h"
#include "viewport_type.h"
#include "company_type.h"
@@ -143,8 +145,8 @@ void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, Fra
void DrawCaption(const Rect &r, Colours colour, Owner owner, TextColour text_colour, StringID str, StringAlignment align);
/* window.cpp */
-extern Window *_z_front_window;
-extern Window *_z_back_window;
+using WindowList = std::list<Window *>;
+extern WindowList _z_windows;
extern Window *_focused_window;
@@ -293,19 +295,7 @@ public:
* to destruct them all at the same time too, which is kinda hard.
* @param size the amount of space not to allocate
*/
- inline void *operator new[](size_t size)
- {
- NOT_REACHED();
- }
-
- /**
- * Helper allocation function to disallow something.
- * Don't free the window directly; it corrupts the linked list when iterating
- * @param ptr the pointer not to free
- */
- inline void operator delete(void *ptr)
- {
- }
+ inline void *operator new[](size_t size) = delete;
WindowDesc *window_desc; ///< Window description
WindowFlags flags; ///< Window flags
@@ -336,8 +326,7 @@ public:
int mouse_capture_widget; ///< Widgetindex of current mouse capture widget (e.g. dragged scrollbar). -1 if no widget has mouse capture.
Window *parent; ///< Parent window.
- Window *z_front; ///< The window in front of us in z-order.
- Window *z_back; ///< The window behind us in z-order.
+ WindowList::iterator z_position;
template <class NWID>
inline const NWID *GetWidget(uint widnum) const;
@@ -813,9 +802,9 @@ public:
/**
* Iterator to iterate all valid Windows
- * @tparam Tfront Wether we iterate from front
+ * @tparam TtoBack whether we iterate towards the back.
*/
- template <bool Tfront>
+ template <bool TtoBack>
struct WindowIterator {
typedef Window *value_type;
typedef value_type *pointer;
@@ -823,22 +812,35 @@ public:
typedef size_t difference_type;
typedef std::forward_iterator_tag iterator_category;
- explicit WindowIterator(const Window *start) : w(const_cast<Window *>(start))
+ explicit WindowIterator(WindowList::iterator start) : it(start)
{
this->Validate();
}
+ explicit WindowIterator(const Window *w) : it(w->z_position) {}
- bool operator==(const WindowIterator &other) const { return this->w == other.w; }
+ bool operator==(const WindowIterator &other) const { return this->it == other.it; }
bool operator!=(const WindowIterator &other) const { return !(*this == other); }
- Window * operator*() const { return this->w; }
+ Window * operator*() const { return *this->it; }
WindowIterator & operator++() { this->Next(); this->Validate(); return *this; }
- bool IsEnd() const { return this->w == nullptr; }
+ bool IsEnd() const { return this->it == _z_windows.end(); }
private:
- Window *w;
- void Validate() { while (this->w != nullptr && this->w->window_class == WC_INVALID) this->Next(); }
- void Next() { if (this->w != nullptr) this->w = Tfront ? this->w->z_back : this->w->z_front; }
+ WindowList::iterator it;
+ void Validate()
+ {
+ while (!this->IsEnd() && *this->it == nullptr) this->Next();
+ }
+ void Next()
+ {
+ if constexpr (!TtoBack) {
+ ++this->it;
+ } else if (this->it == _z_windows.begin()) {
+ this->it = _z_windows.end();
+ } else {
+ --this->it;
+ }
+ }
};
using IteratorToFront = WindowIterator<false>; //!< Iterate in Z order towards front.
using IteratorToBack = WindowIterator<true>; //!< Iterate in Z order towards back.
@@ -850,8 +852,17 @@ public:
template <bool Tfront>
struct AllWindows {
AllWindows() {}
- WindowIterator<Tfront> begin() { return WindowIterator<Tfront>(Tfront ? _z_front_window : _z_back_window); }
- WindowIterator<Tfront> end() { return WindowIterator<Tfront>(nullptr); }
+ WindowIterator<Tfront> begin()
+ {
+ if constexpr (Tfront) {
+ auto back = _z_windows.end();
+ if (back != _z_windows.begin()) --back;
+ return WindowIterator<Tfront>(back);
+ } else {
+ return WindowIterator<Tfront>(_z_windows.begin());
+ }
+ }
+ WindowIterator<Tfront> end() { return WindowIterator<Tfront>(_z_windows.end()); }
};
using Iterate = AllWindows<false>; //!< Iterate all windows in whatever order is easiest.
using IterateFromBack = AllWindows<false>; //!< Iterate all windows in Z order from back to front.