69 Point _cursorpos_drag_start;
71 int _scrollbar_start_pos;
73 byte _scroller_click_timeout = 0;
94 default_width(def_width),
95 default_height(def_height),
97 parent_cls(parent_class),
100 nwid_parts(nwid_parts),
101 nwid_length(nwid_length),
108 *_window_descs->
Append() =
this;
111 WindowDesc::~WindowDesc()
113 _window_descs->
Erase(_window_descs->
Find(
this));
124 if ((*it)->ini_key == NULL)
continue;
135 if ((*a)->ini_key != NULL && (*b)->ini_key != NULL)
return strcmp((*a)->ini_key, (*b)->ini_key);
136 return ((*b)->ini_key != NULL ? 1 : 0) - ((*a)->ini_key != NULL ? 1 : 0);
150 if ((*it)->ini_key == NULL)
continue;
181 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(widget);
182 if (line_height < 0) line_height = wid->
resize_y;
183 if (clickpos < (
int)wid->
pos_y + padding)
return INT_MAX;
184 return (clickpos - (
int)wid->
pos_y - padding) / line_height;
193 NWidgetBase *nwid = this->GetWidget<NWidgetBase>(i);
194 if (nwid == NULL)
continue;
196 if (nwid->IsHighlighted()) {
197 nwid->SetHighlighted(TC_INVALID);
214 NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget_index);
215 if (nwid == NULL)
return;
217 nwid->SetHighlighted(highlighted_colour);
220 if (highlighted_colour != TC_INVALID) {
227 NWidgetBase *nwid = this->GetWidget<NWidgetBase>(i);
228 if (nwid == NULL)
continue;
229 if (!nwid->IsHighlighted())
continue;
247 const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(widget_index);
248 if (nwid == NULL)
return false;
250 return nwid->IsHighlighted();
262 if (widget < 0)
return;
273 NWidgetCore *nwi2 = this->GetWidget<NWidgetCore>(widget);
289 return this->GetWidget<NWidgetScrollbar>(widnum);
299 return this->GetWidget<NWidgetScrollbar>(widnum);
390 Rect r = {0, 0, 0, 0};
414 if (_focused_window == w)
return;
417 if (_focused_window != NULL) {
422 Window *old_focused = _focused_window;
426 if (old_focused != NULL) old_focused->
OnFocusLost();
427 if (_focused_window != NULL) _focused_window->
OnFocus();
437 if (_focused_window == NULL)
return false;
471 if (this->GetWidget<NWidgetCore>(widget_index) == this->
nested_focus)
return false;
477 this->
nested_focus = this->GetWidget<NWidgetCore>(widget_index);
500 va_start(wdg_list, widgets);
504 widgets = va_arg(wdg_list,
int);
519 va_start(wdg_list, widgets);
523 widgets = va_arg(wdg_list,
int);
538 if (((type & ~WWB_PUSHBUTTON) <
WWT_LAST || type == NWID_PUSHBUTTON_DROPDOWN) &&
574 NWidgetCore *nw = this->GetWidget<NWidgetCore>(hotkey);
617 bool focused_widget_changed =
false;
619 if (_focused_window != w &&
622 focused_widget_changed =
true;
626 if (nw == NULL)
return;
631 int widget_index = nw->
index;
657 switch (widget_type) {
665 if (query != NULL) query->ClickEditBox(w, pt, widget_index, click_count, focused_widget_changed);
727 if (widget_index < 0)
return;
735 w->
OnClick(pt, widget_index, click_count);
747 if (wid == NULL)
return;
750 if (wid->
index >= 0) {
769 if (wid == NULL)
return;
778 if (wid->
index < 0)
return;
793 if (nwid == NULL)
return;
859 left < v->left + v->
width &&
860 top < v->top + v->
height) {
864 if (left < (x = v->
left)) {
876 if (top < (x = v->
top)) {
894 dp->width = right - left;
895 dp->height = bottom - top;
896 dp->left = left - w->
left;
897 dp->top = top - w->
top;
898 dp->pitch = _screen.pitch;
918 FOR_ALL_WINDOWS_FROM_BACK(w) {
922 left < w->left + w->
width &&
923 top < w->top + w->
height) {
950 int window_width = this->
width;
951 int window_height = this->
height;
963 window_width =
max(window_width + rx, this->
width);
964 window_height =
max(window_height + ry, this->
height);
1011 FOR_ALL_WINDOWS_FROM_BACK(v) {
1025 while (child != NULL) {
1038 ResetObjectToPlace();
1042 if (_mouseover_last_w ==
this) _mouseover_last_w = NULL;
1045 if (_last_scroll_window ==
this) _last_scroll_window = NULL;
1048 if (_focused_window ==
this) {
1050 _focused_window = NULL;
1055 if (this->
viewport != NULL) DeleteWindowViewport(
this);
1074 FOR_ALL_WINDOWS_FROM_BACK(w) {
1090 FOR_ALL_WINDOWS_FROM_BACK(w) {
1106 if (force || w == NULL ||
1124 FOR_ALL_WINDOWS_FROM_BACK(w) {
1127 goto restart_search;
1146 FOR_ALL_WINDOWS_FROM_BACK(w) {
1147 if (w->
owner ==
id) {
1149 goto restart_search;
1167 FOR_ALL_WINDOWS_FROM_BACK(w) {
1168 if (w->
owner != old_owner)
continue;
1184 w->
owner = new_owner;
1214 static inline bool IsVitalWindow(
const Window *w)
1240 uint z_priority = 0;
1306 if (_z_front_window == NULL) {
1308 _z_front_window = _z_back_window = w;
1313 uint last_z_priority = UINT_MAX;
1328 _z_back_window->
z_back = w;
1330 }
else if (v == _z_front_window) {
1335 _z_front_window = w;
1354 assert(_z_front_window == w);
1355 _z_front_window = w->
z_back;
1361 assert(_z_back_window == w);
1437 this->
width = sm_width;
1438 this->
height = sm_height;
1453 def_width =
max(def_width, this->
width);
1454 def_height =
max(def_height, this->
height);
1460 if (this->
width != def_width || this->
height != def_height) {
1462 int free_height = _screen.height;
1464 if (wt != NULL) free_height -= wt->
height;
1466 if (wt != NULL) free_height -= wt->
height;
1468 int enlarge_x =
max(
min(def_width - this->
width, _screen.width - this->width), 0);
1484 int nx = this->
left;
1487 if (nx + this->
width > _screen.width) nx -= (nx + this->
width - _screen.width);
1490 ny =
max(ny, (wt == NULL ||
this == wt || this->
top == 0) ? 0 : wt->
height);
1516 int right = width + left;
1517 int bottom = height + top;
1520 if (left < 0 || (main_toolbar != NULL && top < main_toolbar->height) || right > _screen.width || bottom > _screen.height)
return false;
1524 FOR_ALL_WINDOWS_FROM_BACK(w) {
1527 if (right > w->
left &&
1556 if (left < -(width >> 2) || left > _screen.width - (width >> 1))
return false;
1558 if (top < 22 || top > _screen.height - (height >> 2))
return false;
1562 FOR_ALL_WINDOWS_FROM_BACK(w) {
1565 if (left + width > w->
left &&
1567 top + height > w->
top &&
1590 if (
IsGoodAutoPlace1(0, main_toolbar != NULL ? main_toolbar->
height + 2 : 2, width, height, pt))
return pt;
1597 FOR_ALL_WINDOWS_FROM_BACK(w) {
1614 FOR_ALL_WINDOWS_FROM_BACK(w) {
1626 int left = 0, top = 24;
1629 FOR_ALL_WINDOWS_FROM_BACK(w) {
1630 if (w->
left == left && w->
top == top) {
1678 int16 default_width =
max(desc->GetDefaultWidth(), sm_width);
1679 int16 default_height =
max(desc->GetDefaultHeight(), sm_height);
1683 w->
left < _screen.width - 20 && w->
left > -60 && w->
top < _screen.height - 20) {
1686 if (pt.x > _screen.width + 10 - default_width) {
1687 pt.x = (_screen.width + 10 - default_width) - 20;
1701 pt.x = (_screen.width - default_width) / 2;
1702 pt.y = (_screen.height - default_height) / 2;
1731 int biggest_index = -1;
1782 FOR_ALL_WINDOWS_FROM_FRONT(w) {
1798 _z_back_window = NULL;
1799 _z_front_window = NULL;
1800 _focused_window = NULL;
1801 _mouseover_last_w = NULL;
1802 _last_scroll_window = NULL;
1807 NWidgetScrollbar::InvalidateDimensionCache();
1820 FOR_ALL_WINDOWS_FROM_FRONT(w)
delete w;
1822 for (w = _z_front_window; w != NULL; ) {
1828 _z_front_window = NULL;
1829 _z_back_window = NULL;
1842 static void DecreaseWindowCounters()
1845 FOR_ALL_WINDOWS_FROM_FRONT(w) {
1846 if (_scroller_click_timeout == 0) {
1863 it->second->HandleEditBox(w, it->first);
1869 FOR_ALL_WINDOWS_FROM_FRONT(w) {
1879 static void HandlePlacePresize()
1884 if (w == NULL)
return;
1886 Point pt = GetTileBelowCursor();
1909 pt.x = _cursor.pos.x - w->
left;
1910 pt.y = _cursor.pos.y - w->
top;
1928 if (_mouseover_last_w != NULL && _mouseover_last_w != w) {
1930 Point pt = { -1, -1 };
1935 _mouseover_last_w = w;
1939 Point pt = { _cursor.pos.x - w->
left, _cursor.pos.y - w->
top };
1966 if (v == NULL)
return;
1970 int safe_y = (dir ==
PHD_UP) ? (v->
top - MIN_VISIBLE_TITLE_BAR - rect.top) : (v_bottom + MIN_VISIBLE_TITLE_BAR - rect.bottom);
1972 if (*ny + rect.top <= v->
top - MIN_VISIBLE_TITLE_BAR)
return;
1973 if (*ny + rect.bottom >= v_bottom + MIN_VISIBLE_TITLE_BAR)
return;
1976 if (*nx + rect.left + MIN_VISIBLE_TITLE_BAR < v->left) {
1977 if (v->
left < MIN_VISIBLE_TITLE_BAR) *ny = safe_y;
1980 if (*nx + rect.right - MIN_VISIBLE_TITLE_BAR > v_right) {
1981 if (v_right > _screen.width - MIN_VISIBLE_TITLE_BAR) *ny = safe_y;
1986 if (px + rect.left < v->
left && v->
left >= MIN_VISIBLE_TITLE_BAR) {
1987 *nx = v->
left - MIN_VISIBLE_TITLE_BAR - rect.left;
1988 }
else if (px + rect.right > v_right && v_right <= _screen.width - MIN_VISIBLE_TITLE_BAR) {
1989 *nx = v_right + MIN_VISIBLE_TITLE_BAR - rect.right;
2007 if (caption != NULL) {
2008 caption_rect.left = caption->
pos_x;
2010 caption_rect.top = caption->
pos_y;
2014 nx =
Clamp(nx, MIN_VISIBLE_TITLE_BAR - caption_rect.right, _screen.width - MIN_VISIBLE_TITLE_BAR - caption_rect.left);
2015 ny =
Clamp(ny, 0, _screen.height - MIN_VISIBLE_TITLE_BAR);
2043 if (delta_x != 0 || delta_y != 0) {
2044 if (clamp_to_screen) {
2047 int new_right = w->
left + w->
width + delta_x;
2048 int new_bottom = w->
top + w->
height + delta_y;
2080 return (w == NULL) ? 0 : w->
top + w->
height;
2091 return (w == NULL) ? _screen.height : w->
top;
2110 FOR_ALL_WINDOWS_FROM_BACK(w) {
2120 int x = _cursor.pos.x + _drag_delta.x;
2121 int y = _cursor.pos.y + _drag_delta.y;
2132 FOR_ALL_WINDOWS_FROM_BACK(v) {
2133 if (v == w)
continue;
2138 if (delta <= hsnap) {
2145 if (delta <= hsnap) {
2154 if (delta <= hsnap) {
2161 if (delta <= hsnap) {
2170 if (delta <= vsnap) {
2177 if (delta <= vsnap) {
2186 if (delta <= vsnap) {
2193 if (delta <= vsnap) {
2216 int x, y = _cursor.pos.y - _drag_delta.y;
2218 x = _drag_delta.x - _cursor.pos.x;
2220 x = _cursor.pos.x - _drag_delta.x;
2228 if (w->
top + w->
height + y > _screen.height) {
2229 y = _screen.height - w->
height - w->
top;
2266 _dragging_window =
false;
2278 _dragging_window =
true;
2280 _drag_delta.x = w->
left - _cursor.pos.x;
2281 _drag_delta.y = w->
top - _cursor.pos.y;
2296 _dragging_window =
true;
2298 _drag_delta.x = _cursor.pos.x;
2299 _drag_delta.y = _cursor.pos.y;
2312 FOR_ALL_WINDOWS_FROM_BACK(w) {
2326 i = _cursor.pos.x - _cursorpos_drag_start.x;
2329 i = _cursor.pos.y - _cursorpos_drag_start.y;
2333 if (_scroller_click_timeout == 1) {
2334 _scroller_click_timeout = 3;
2368 if (_last_scroll_window == NULL) _last_scroll_window =
FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
2373 _last_scroll_window = NULL;
2386 delta.x = -_cursor.
delta.x;
2387 delta.y = -_cursor.
delta.y;
2389 delta.x = _cursor.
delta.x;
2390 delta.y = _cursor.
delta.y;
2393 if (scrollwheel_scrolling) {
2395 delta.x = _cursor.h_wheel;
2396 delta.y = _cursor.v_wheel;
2397 _cursor.v_wheel = 0;
2398 _cursor.h_wheel = 0;
2402 if (delta.x != 0 || delta.y != 0) _last_scroll_window->
OnScroll(delta);
2404 _cursor.
delta.x = 0;
2405 _cursor.
delta.y = 0;
2421 bool bring_to_front =
false;
2431 int w_width = w->
width;
2432 int w_height = w->
height;
2455 if (w->
left + w_width <= u->left ||
2457 w->
top + w_height <= u->top ||
2462 bring_to_front =
true;
2484 switch (query->text.HandleKeyPress(key, keycode)) {
2528 if (query->text.
bytes <= 1) {
2563 if (key >= 0xE000 && key <= 0xF8FF) key = 0;
2568 if (key == 0 && keycode == 0)
return;
2582 FOR_ALL_WINDOWS_FROM_FRONT(w) {
2601 HandleGlobalHotkeys(key, keycode);
2611 FOR_ALL_WINDOWS_FROM_FRONT(w) {
2621 void Window::InsertTextString(
int wid,
const char *str,
bool marked,
const char *caret,
const char *insert_location,
const char *replacement_end)
2624 if (query == NULL)
return;
2626 if (query->text.
InsertString(str, marked, caret, insert_location, replacement_end) || marked) {
2638 void HandleTextInput(
const char *str,
bool marked,
const char *caret,
const char *insert_location,
const char *replacement_end)
2663 int x = _cursor.pos.x;
2664 int y = _cursor.pos.y;
2670 if (vp == NULL)
return;
2676 #define scrollspeed 3
2679 }
else if (15 - (vp->
width - x) > 0) {
2684 }
else if (15 - (vp->
height - y) > 0) {
2703 static void ScrollMainViewport(
int x,
int y)
2705 if (_game_mode != GM_MENU) {
2742 static void HandleKeyScrolling()
2750 ScrollMainViewport(scrollamt[
_dirkeys][0] * factor, scrollamt[
_dirkeys][1] * factor);
2754 static void MouseLoop(
MouseClick click,
int mousewheel)
2760 HandlePlacePresize();
2772 if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling)
return;
2774 int x = _cursor.pos.x;
2775 int y = _cursor.pos.y;
2777 if (w == NULL)
return;
2785 if (mousewheel != 0) {
2794 if (scrollwheel_scrolling) click = MC_RIGHT;
2796 case MC_DOUBLE_LEFT:
2799 if (!HandleViewportClicked(vp, x, y) &&
2813 _cursor.h_wheel = 0;
2814 _cursor.v_wheel = 0;
2824 case MC_DOUBLE_LEFT:
2850 static int double_click_time = 0;
2851 static Point double_click_pos = {0, 0};
2860 click = MC_DOUBLE_LEFT;
2863 double_click_pos = _cursor.pos;
2865 _input_events_this_tick++;
2869 _input_events_this_tick++;
2873 if (_cursor.
wheel) {
2874 mousewheel = _cursor.
wheel;
2876 _input_events_this_tick++;
2879 static uint32 hover_time = 0;
2880 static Point hover_pos = {0, 0};
2886 hover_pos = _cursor.pos;
2892 _input_events_this_tick++;
2914 MouseLoop(click, mousewheel);
2919 _cursor.
delta.x = 0;
2920 _cursor.
delta.y = 0;
2931 uint deletable_count = 0;
2932 Window *w, *last_deletable = NULL;
2933 FOR_ALL_WINDOWS_FROM_FRONT(w) {
2943 assert(last_deletable != NULL);
2944 delete last_deletable;
2958 HandleKeyScrolling();
2961 for (
Window *v = _z_front_window; v != NULL; ) {
2971 if (_scroller_click_timeout != 0) _scroller_click_timeout--;
2972 DecreaseWindowCounters();
2974 if (_input_events_this_tick != 0) {
2976 _input_events_this_tick = 0;
2993 static int highlight_timer = 1;
2994 if (--highlight_timer == 0) {
2995 highlight_timer = 15;
2999 FOR_ALL_WINDOWS_FROM_FRONT(w) {
3004 static int we4_timer = 0;
3005 int t = we4_timer + 1;
3008 FOR_ALL_WINDOWS_FROM_FRONT(w) {
3015 FOR_ALL_WINDOWS_FROM_FRONT(w) {
3024 FOR_ALL_WINDOWS_FROM_BACK(w) {
3041 FOR_ALL_WINDOWS_FROM_BACK(w) {
3055 FOR_ALL_WINDOWS_FROM_BACK(w) {
3069 FOR_ALL_WINDOWS_FROM_BACK(w) {
3141 FOR_ALL_WINDOWS_FROM_BACK(w) {
3160 FOR_ALL_WINDOWS_FROM_BACK(w) {
3173 FOR_ALL_WINDOWS_FROM_FRONT(w) {
3192 FOR_ALL_WINDOWS_FROM_BACK(w) {
3201 goto restart_search;
3224 FOR_ALL_WINDOWS_FROM_BACK(w) {
3227 goto restart_search;
3244 FOR_ALL_WINDOWS_FROM_BACK(w) {
3247 goto restart_search;
3251 FOR_ALL_WINDOWS_FROM_BACK(w) w->
SetDirty();
3265 NWidgetScrollbar::InvalidateDimensionCache();
3271 FOR_ALL_WINDOWS_FROM_BACK(w) {
3274 #ifdef ENABLE_NETWORK
3296 if (w == NULL)
return 0;
3298 int old_left = w->
left;
3300 case 1: w->
left = (_screen.width - w->
width) / 2;
break;
3301 case 2: w->
left = _screen.width - w->
width;
break;
3302 default: w->
left = 0;
break;
3316 DEBUG(misc, 5,
"Repositioning Main Toolbar...");
3327 DEBUG(misc, 5,
"Repositioning statusbar...");
3338 DEBUG(misc, 5,
"Repositioning news message...");
3349 DEBUG(misc, 5,
"Repositioning network chat window...");
3362 FOR_ALL_WINDOWS_FROM_BACK(w) {
3380 FOR_ALL_WINDOWS_FROM_BACK(w) {
3421 top = (newh - w->
height) >> 1;
3422 left = (neww - w->
width) >> 1;
3427 if (left + (w->
width >> 1) >= neww) left = neww - w->
width;
3428 if (left < 0) left = 0;
3431 if (top + (w->
height >> 1) >= newh) top = newh - w->
height;
3448 ResetObjectToPlace();