Merge 1.9.0-beta2
This commit is contained in:
172
src/window.cpp
172
src/window.cpp
@@ -1,4 +1,4 @@
|
||||
/* $Id: window.cpp 27934 2017-12-09 19:21:41Z michi_cc $ */
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
@@ -38,6 +38,9 @@
|
||||
#include "error.h"
|
||||
#include "game/game.hpp"
|
||||
#include "video/video_driver.hpp"
|
||||
#include "framerate_type.h"
|
||||
#include "network/network_func.h"
|
||||
#include "guitimer_func.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
@@ -50,7 +53,7 @@ enum ViewportAutoscrolling {
|
||||
};
|
||||
|
||||
static Point _drag_delta; ///< delta between mouse cursor and upper left corner of dragged window
|
||||
static Window *_mouseover_last_w = NULL; ///< Window of the last #MOUSEOVER event.
|
||||
static Window *_mouseover_last_w = NULL; ///< Window of the last OnMouseOver event.
|
||||
static Window *_last_scroll_window = NULL; ///< Window of the last scroll event.
|
||||
|
||||
/** List of windows opened at the screen sorted from the front. */
|
||||
@@ -654,7 +657,7 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count)
|
||||
|
||||
/* Clicked on a widget that is not disabled.
|
||||
* So unless the clicked widget is the caption bar, change focus to this widget.
|
||||
* Exception: In the OSK we always want the editbox to stay focussed. */
|
||||
* Exception: In the OSK we always want the editbox to stay focused. */
|
||||
if (widget_type != WWT_CAPTION && w->window_class != WC_OSK) {
|
||||
/* focused_widget_changed is 'now' only true if the window this widget
|
||||
* is in gained focus. In that case it must remain true, also if the
|
||||
@@ -939,6 +942,8 @@ static void DrawOverlappedWindow(Window *w, int left, int top, int right, int bo
|
||||
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
|
||||
{
|
||||
Window *w;
|
||||
|
||||
DrawPixelInfo *old_dpi = _cur_dpi;
|
||||
DrawPixelInfo bk;
|
||||
_cur_dpi = &bk;
|
||||
|
||||
@@ -952,6 +957,7 @@ void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
|
||||
DrawOverlappedWindow(w, max(left, w->left), max(top, w->top), min(right, w->left + w->width), min(bottom, w->top + w->height));
|
||||
}
|
||||
}
|
||||
_cur_dpi = old_dpi;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1116,7 +1122,7 @@ Window *FindWindowById(WindowClass cls, WindowNumber number)
|
||||
|
||||
/**
|
||||
* Find any window by its class. Useful when searching for a window that uses
|
||||
* the window number as a #WindowType, like #WC_SEND_NETWORK_MSG.
|
||||
* the window number as a #WindowClass, like #WC_SEND_NETWORK_MSG.
|
||||
* @param cls Window class
|
||||
* @return Pointer to the found window, or \c NULL if not available
|
||||
*/
|
||||
@@ -1432,7 +1438,6 @@ static void BringWindowToFront(Window *w)
|
||||
|
||||
/**
|
||||
* Initializes the data (except the position and initial size) of a new Window.
|
||||
* @param desc Window description.
|
||||
* @param window_number Number being assigned to the new window
|
||||
* @return Window pointer of the newly created window
|
||||
* @pre If nested widgets are used (\a widget is \c NULL), #nested_root and #nested_array_size must be initialized.
|
||||
@@ -1741,7 +1746,7 @@ static Point LocalGetWindowPlacement(const WindowDesc *desc, int16 sm_width, int
|
||||
int16 default_width = max(desc->GetDefaultWidth(), sm_width);
|
||||
int16 default_height = max(desc->GetDefaultHeight(), sm_height);
|
||||
|
||||
if (desc->parent_cls != 0 /* WC_MAIN_WINDOW */ && (w = FindWindowById(desc->parent_cls, window_number)) != NULL) {
|
||||
if (desc->parent_cls != WC_NONE && (w = FindWindowById(desc->parent_cls, window_number)) != NULL) {
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
if (desc->parent_cls == WC_BUILD_TOOLBAR || desc->parent_cls == WC_SCEN_LAND_GEN) {
|
||||
pt.x = w->left + (rtl ? w->width - default_width : 0);
|
||||
@@ -1921,6 +1926,8 @@ void ResetWindowSystem()
|
||||
|
||||
static void DecreaseWindowCounters()
|
||||
{
|
||||
if (_scroller_click_timeout != 0) _scroller_click_timeout--;
|
||||
|
||||
Window *w;
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) {
|
||||
if (_scroller_click_timeout == 0) {
|
||||
@@ -2004,7 +2011,7 @@ static void HandleMouseOver()
|
||||
{
|
||||
Window *w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
|
||||
|
||||
/* We changed window, put a MOUSEOVER event to the last window */
|
||||
/* We changed window, put an OnMouseOver event to the last window */
|
||||
if (_mouseover_last_w != NULL && _mouseover_last_w != w) {
|
||||
/* Reset mouse-over coordinates of previous window */
|
||||
Point pt = { -1, -1 };
|
||||
@@ -2447,7 +2454,7 @@ static EventState HandleViewportScroll()
|
||||
* outside of the window and should not left-mouse scroll anymore. */
|
||||
if (_last_scroll_window == NULL) _last_scroll_window = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
|
||||
|
||||
if (_last_scroll_window == NULL || !(_right_button_down || scrollwheel_scrolling || (_settings_client.gui.left_mouse_btn_scrolling && _left_button_down))) {
|
||||
if (_last_scroll_window == NULL || !((_settings_client.gui.scroll_mode != VSM_MAP_LMB && _right_button_down) || scrollwheel_scrolling || (_settings_client.gui.scroll_mode == VSM_MAP_LMB && _left_button_down))) {
|
||||
_cursor.fix_at = false;
|
||||
_scrolling_viewport = false;
|
||||
_last_scroll_window = NULL;
|
||||
@@ -2462,20 +2469,20 @@ static EventState HandleViewportScroll()
|
||||
}
|
||||
|
||||
Point delta;
|
||||
if (_settings_client.gui.reverse_scroll || (_settings_client.gui.left_mouse_btn_scrolling && _left_button_down)) {
|
||||
delta.x = -_cursor.delta.x;
|
||||
delta.y = -_cursor.delta.y;
|
||||
} else {
|
||||
delta.x = _cursor.delta.x;
|
||||
delta.y = _cursor.delta.y;
|
||||
}
|
||||
|
||||
if (scrollwheel_scrolling) {
|
||||
/* We are using scrollwheels for scrolling */
|
||||
delta.x = _cursor.h_wheel;
|
||||
delta.y = _cursor.v_wheel;
|
||||
_cursor.v_wheel = 0;
|
||||
_cursor.h_wheel = 0;
|
||||
} else {
|
||||
if (_settings_client.gui.scroll_mode != VSM_VIEWPORT_RMB_FIXED) {
|
||||
delta.x = -_cursor.delta.x;
|
||||
delta.y = -_cursor.delta.y;
|
||||
} else {
|
||||
delta.x = _cursor.delta.x;
|
||||
delta.y = _cursor.delta.y;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a scroll-event and send it to the window */
|
||||
@@ -2753,18 +2760,17 @@ static void HandleAutoscroll()
|
||||
y -= vp->top;
|
||||
|
||||
/* here allows scrolling in both x and y axis */
|
||||
#define scrollspeed 3
|
||||
static const int SCROLLSPEED = 3;
|
||||
if (x - 15 < 0) {
|
||||
w->viewport->dest_scrollpos_x += ScaleByZoom((x - 15) * scrollspeed, vp->zoom);
|
||||
w->viewport->dest_scrollpos_x += ScaleByZoom((x - 15) * SCROLLSPEED, vp->zoom);
|
||||
} else if (15 - (vp->width - x) > 0) {
|
||||
w->viewport->dest_scrollpos_x += ScaleByZoom((15 - (vp->width - x)) * scrollspeed, vp->zoom);
|
||||
w->viewport->dest_scrollpos_x += ScaleByZoom((15 - (vp->width - x)) * SCROLLSPEED, vp->zoom);
|
||||
}
|
||||
if (y - 15 < 0) {
|
||||
w->viewport->dest_scrollpos_y += ScaleByZoom((y - 15) * scrollspeed, vp->zoom);
|
||||
w->viewport->dest_scrollpos_y += ScaleByZoom((y - 15) * SCROLLSPEED, vp->zoom);
|
||||
} else if (15 - (vp->height - y) > 0) {
|
||||
w->viewport->dest_scrollpos_y += ScaleByZoom((15 - (vp->height - y)) * scrollspeed, vp->zoom);
|
||||
w->viewport->dest_scrollpos_y += ScaleByZoom((15 - (vp->height - y)) * SCROLLSPEED, vp->zoom);
|
||||
}
|
||||
#undef scrollspeed
|
||||
}
|
||||
|
||||
enum MouseClick {
|
||||
@@ -2863,21 +2869,26 @@ static void MouseLoop(MouseClick click, int mousewheel)
|
||||
if (vp != NULL && (_game_mode == GM_MENU || HasModalProgress())) return;
|
||||
|
||||
if (mousewheel != 0) {
|
||||
/* Send mousewheel event to window */
|
||||
w->OnMouseWheel(mousewheel);
|
||||
/* Send mousewheel event to window, unless we're scrolling a viewport or the map */
|
||||
if (!scrollwheel_scrolling || (vp == NULL && w->window_class != WC_SMALLMAP)) w->OnMouseWheel(mousewheel);
|
||||
|
||||
/* Dispatch a MouseWheelEvent for widgets if it is not a viewport */
|
||||
if (vp == NULL) DispatchMouseWheelEvent(w, w->nested_root->GetWidgetFromPos(x - w->left, y - w->top), mousewheel);
|
||||
}
|
||||
|
||||
if (vp != NULL) {
|
||||
if (scrollwheel_scrolling) click = MC_RIGHT; // we are using the scrollwheel in a viewport, so we emulate right mouse button
|
||||
if (scrollwheel_scrolling && !(w->flags & WF_DISABLE_VP_SCROLL)) {
|
||||
_scrolling_viewport = true;
|
||||
_cursor.fix_at = true;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (click) {
|
||||
case MC_DOUBLE_LEFT:
|
||||
case MC_LEFT:
|
||||
if (HandleViewportClicked(vp, x, y, click == MC_DOUBLE_LEFT)) return;
|
||||
if (!(w->flags & WF_DISABLE_VP_SCROLL) &&
|
||||
_settings_client.gui.left_mouse_btn_scrolling) {
|
||||
_settings_client.gui.scroll_mode == VSM_MAP_LMB) {
|
||||
_scrolling_viewport = true;
|
||||
_cursor.fix_at = false;
|
||||
return;
|
||||
@@ -2885,13 +2896,11 @@ static void MouseLoop(MouseClick click, int mousewheel)
|
||||
break;
|
||||
|
||||
case MC_RIGHT:
|
||||
if (!(w->flags & WF_DISABLE_VP_SCROLL)) {
|
||||
if (!(w->flags & WF_DISABLE_VP_SCROLL) &&
|
||||
_settings_client.gui.scroll_mode != VSM_MAP_LMB) {
|
||||
_scrolling_viewport = true;
|
||||
_cursor.fix_at = true;
|
||||
|
||||
/* clear 2D scrolling caches before we start a 2D scroll */
|
||||
_cursor.h_wheel = 0;
|
||||
_cursor.v_wheel = 0;
|
||||
_cursor.fix_at = (_settings_client.gui.scroll_mode == VSM_VIEWPORT_RMB_FIXED ||
|
||||
_settings_client.gui.scroll_mode == VSM_MAP_RMB_FIXED);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -2906,7 +2915,7 @@ static void MouseLoop(MouseClick click, int mousewheel)
|
||||
case MC_LEFT:
|
||||
case MC_DOUBLE_LEFT:
|
||||
DispatchLeftClickEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1);
|
||||
break;
|
||||
return;
|
||||
|
||||
default:
|
||||
if (!scrollwheel_scrolling || w == NULL || w->window_class != WC_SMALLMAP) break;
|
||||
@@ -2914,11 +2923,19 @@ static void MouseLoop(MouseClick click, int mousewheel)
|
||||
* Simulate a right button click so we can get started. */
|
||||
FALLTHROUGH;
|
||||
|
||||
case MC_RIGHT: DispatchRightClickEvent(w, x - w->left, y - w->top); break;
|
||||
case MC_RIGHT:
|
||||
DispatchRightClickEvent(w, x - w->left, y - w->top);
|
||||
return;
|
||||
|
||||
case MC_HOVER: DispatchHoverEvent(w, x - w->left, y - w->top); break;
|
||||
case MC_HOVER:
|
||||
DispatchHoverEvent(w, x - w->left, y - w->top);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're not doing anything with 2D scrolling, so reset the value. */
|
||||
_cursor.h_wheel = 0;
|
||||
_cursor.v_wheel = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3038,7 +3055,6 @@ void InputLoop()
|
||||
assert(HasModalProgress() || IsLocalCompany());
|
||||
|
||||
CheckSoftLimit();
|
||||
HandleKeyScrolling();
|
||||
|
||||
/* Do the actual free of the deleted windows. */
|
||||
for (Window *v = _z_front_window; v != NULL; /* nothing */) {
|
||||
@@ -3051,9 +3067,6 @@ void InputLoop()
|
||||
free(w);
|
||||
}
|
||||
|
||||
if (_scroller_click_timeout != 0) _scroller_click_timeout--;
|
||||
DecreaseWindowCounters();
|
||||
|
||||
if (_input_events_this_tick != 0) {
|
||||
/* The input loop is called only once per GameLoop() - so we can clear the counter here */
|
||||
_input_events_this_tick = 0;
|
||||
@@ -3063,7 +3076,17 @@ void InputLoop()
|
||||
|
||||
/* HandleMouseEvents was already called for this tick */
|
||||
HandleMouseEvents();
|
||||
HandleAutoscroll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch OnRealtimeTick event over all windows
|
||||
*/
|
||||
void CallWindowRealtimeTickEvent(uint delta_ms)
|
||||
{
|
||||
Window *w;
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) {
|
||||
w->OnRealtimeTick(delta_ms);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3071,14 +3094,48 @@ void InputLoop()
|
||||
*/
|
||||
void UpdateWindows()
|
||||
{
|
||||
static uint32 last_realtime_tick = _realtime_tick;
|
||||
uint delta_ms = _realtime_tick - last_realtime_tick;
|
||||
last_realtime_tick = _realtime_tick;
|
||||
|
||||
if (delta_ms == 0) return;
|
||||
|
||||
PerformanceMeasurer framerate(PFE_DRAWING);
|
||||
PerformanceAccumulator::Reset(PFE_DRAWWORLD);
|
||||
|
||||
CallWindowRealtimeTickEvent(delta_ms);
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
static GUITimer network_message_timer = GUITimer(1);
|
||||
if (network_message_timer.Elapsed(delta_ms)) {
|
||||
network_message_timer.SetInterval(1000);
|
||||
NetworkChatMessageLoop();
|
||||
}
|
||||
#endif
|
||||
|
||||
Window *w;
|
||||
|
||||
static int highlight_timer = 1;
|
||||
if (--highlight_timer == 0) {
|
||||
highlight_timer = 15;
|
||||
static GUITimer window_timer = GUITimer(1);
|
||||
if (window_timer.Elapsed(delta_ms)) {
|
||||
if (_network_dedicated) window_timer.SetInterval(MILLISECONDS_PER_TICK);
|
||||
|
||||
extern int _caret_timer;
|
||||
_caret_timer += 3;
|
||||
CursorTick();
|
||||
|
||||
HandleKeyScrolling();
|
||||
HandleAutoscroll();
|
||||
DecreaseWindowCounters();
|
||||
}
|
||||
|
||||
static GUITimer highlight_timer = GUITimer(1);
|
||||
if (highlight_timer.Elapsed(delta_ms)) {
|
||||
highlight_timer.SetInterval(450);
|
||||
_window_highlight_colour = !_window_highlight_colour;
|
||||
}
|
||||
|
||||
if (!_pause_mode || _game_mode == GM_EDITOR || _settings_game.construction.command_pause_level > CMDPL_NO_CONSTRUCTION) MoveAllTextEffects(delta_ms);
|
||||
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) {
|
||||
w->ProcessScheduledInvalidations();
|
||||
w->ProcessHighlightedInvalidations();
|
||||
@@ -3088,21 +3145,23 @@ void UpdateWindows()
|
||||
* But still empty the invalidation queues above. */
|
||||
if (_network_dedicated) return;
|
||||
|
||||
static int we4_timer = 0;
|
||||
int t = we4_timer + 1;
|
||||
static GUITimer hundredth_timer = GUITimer(1);
|
||||
if (hundredth_timer.Elapsed(delta_ms)) {
|
||||
hundredth_timer.SetInterval(3000); // Historical reason: 100 * MILLISECONDS_PER_TICK
|
||||
|
||||
if (t >= 100) {
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) {
|
||||
w->OnHundredthTick();
|
||||
}
|
||||
t = 0;
|
||||
}
|
||||
we4_timer = t;
|
||||
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) {
|
||||
if ((w->flags & WF_WHITE_BORDER) && --w->white_border_timer == 0) {
|
||||
CLRBITS(w->flags, WF_WHITE_BORDER);
|
||||
w->SetDirty();
|
||||
if (window_timer.HasElapsed()) {
|
||||
window_timer.SetInterval(MILLISECONDS_PER_TICK);
|
||||
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) {
|
||||
if ((w->flags & WF_WHITE_BORDER) && --w->white_border_timer == 0) {
|
||||
CLRBITS(w->flags, WF_WHITE_BORDER);
|
||||
w->SetDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3252,13 +3311,13 @@ void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch WE_TICK event over all windows
|
||||
* Dispatch OnGameTick event over all windows
|
||||
*/
|
||||
void CallWindowTickEvent()
|
||||
void CallWindowGameTickEvent()
|
||||
{
|
||||
Window *w;
|
||||
FOR_ALL_WINDOWS_FROM_FRONT(w) {
|
||||
w->OnTick();
|
||||
w->OnGameTick();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3462,8 +3521,9 @@ void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index)
|
||||
*/
|
||||
void RelocateAllWindows(int neww, int newh)
|
||||
{
|
||||
Window *w;
|
||||
DeleteWindowById(WC_DROPDOWN_MENU, 0);
|
||||
|
||||
Window *w;
|
||||
FOR_ALL_WINDOWS_FROM_BACK(w) {
|
||||
int left, top;
|
||||
/* XXX - this probably needs something more sane. For example specifying
|
||||
|
||||
Reference in New Issue
Block a user