mirror of https://github.com/OpenTTD/OpenTTD
(svn r1225) -Feature: SHIFT+DEL now deletes all non-vital windows (only status bar and main bar remain)
-Fix: For everyone who tried to crash the game by opening a huge amount of windows and stickying all of them; bad luck. It's fixed now (thanks Tron for the helpful criticism). First all normal windows are a candidate for replacement, then if none are found, sticky windows. Then..well that should not happen :)release/0.4.5
parent
b7f71b026d
commit
ed0a42f940
23
main_gui.c
23
main_gui.c
|
@ -152,26 +152,6 @@ static void ToolbarFastForwardClick(Window *w)
|
||||||
SndPlayFx(SND_15_BEEP);
|
SndPlayFx(SND_15_BEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It is possible that a stickied window gets to a position where the
|
|
||||||
* 'close' button is outside the gaming area. You cannot close it then; except
|
|
||||||
* with this function. It closes all windows calling the standard function,
|
|
||||||
* then, does a little hacked loop of closing all stickied windows. Note
|
|
||||||
* that standard windows (status bar, etc.) are not stickied, so these aren't affected */
|
|
||||||
static void CloseEveryWindow(void)
|
|
||||||
{
|
|
||||||
Window *w;
|
|
||||||
// Delete every window except for stickied ones
|
|
||||||
DeleteNonVitalWindows();
|
|
||||||
// Delete all sticked windows
|
|
||||||
for (w = _windows; w != _last_window;) {
|
|
||||||
if (w->flags4 & WF_STICKY) {
|
|
||||||
DeleteWindow(w);
|
|
||||||
w = _windows;
|
|
||||||
} else
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef void MenuClickedProc(int index);
|
typedef void MenuClickedProc(int index);
|
||||||
|
|
||||||
|
|
||||||
|
@ -183,7 +163,7 @@ static void MenuClickSettings(int index)
|
||||||
case 2: ShowPatchesSelection(); return;
|
case 2: ShowPatchesSelection(); return;
|
||||||
case 3: ShowNewgrf(); return;
|
case 3: ShowNewgrf(); return;
|
||||||
|
|
||||||
case 5: CloseEveryWindow(); return;
|
case 5: DeleteAllNonVitalWindows(); return;
|
||||||
case 6: _display_opt ^= DO_SHOW_TOWN_NAMES; MarkWholeScreenDirty(); return;
|
case 6: _display_opt ^= DO_SHOW_TOWN_NAMES; MarkWholeScreenDirty(); return;
|
||||||
case 7: _display_opt ^= DO_SHOW_STATION_NAMES; MarkWholeScreenDirty(); return;
|
case 7: _display_opt ^= DO_SHOW_STATION_NAMES; MarkWholeScreenDirty(); return;
|
||||||
case 8: _display_opt ^= DO_SHOW_SIGNS; MarkWholeScreenDirty(); return;
|
case 8: _display_opt ^= DO_SHOW_SIGNS; MarkWholeScreenDirty(); return;
|
||||||
|
@ -2330,6 +2310,7 @@ static void MainWindowWndProc(Window *w, WindowEvent *e) {
|
||||||
|
|
||||||
case WKC_ESC: ResetObjectToPlace(); break;
|
case WKC_ESC: ResetObjectToPlace(); break;
|
||||||
case WKC_DELETE: DeleteNonVitalWindows(); break;
|
case WKC_DELETE: DeleteNonVitalWindows(); break;
|
||||||
|
case WKC_DELETE | WKC_SHIFT: DeleteAllNonVitalWindows(); break;
|
||||||
case 'Q' | WKC_CTRL: AskExitGame(); break;
|
case 'Q' | WKC_CTRL: AskExitGame(); break;
|
||||||
case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac
|
case 'Q' | WKC_META: AskExitGame(); break; // this enables command + Q on mac
|
||||||
case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break;
|
case 'R' | WKC_CTRL: MarkWholeScreenDirty(); break;
|
||||||
|
|
63
window.c
63
window.c
|
@ -285,6 +285,34 @@ Window *BringWindowToFront(Window *w)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We have run out of windows, so find a suitable candidate for replacement.
|
||||||
|
* Keep all important windows intact */
|
||||||
|
static Window *FindDeletableWindow(void)
|
||||||
|
{
|
||||||
|
Window *w;
|
||||||
|
for (w = _windows; w < endof(_windows); w++) {
|
||||||
|
if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR &&
|
||||||
|
w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW &&
|
||||||
|
!(w->flags4 & WF_STICKY) )
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A window must be freed, and all are marked as important windows. Ease the
|
||||||
|
* restriction a bit by allowing to delete sticky windows */
|
||||||
|
static Window *ForceFindDeletableWindow(void)
|
||||||
|
{
|
||||||
|
Window *w;
|
||||||
|
for (w = _windows;; w++) {
|
||||||
|
assert(w < _last_window);
|
||||||
|
|
||||||
|
if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR &&
|
||||||
|
w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW)
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Window *AllocateWindow(
|
Window *AllocateWindow(
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
|
@ -296,21 +324,16 @@ Window *AllocateWindow(
|
||||||
{
|
{
|
||||||
Window *w;
|
Window *w;
|
||||||
|
|
||||||
restart:;
|
|
||||||
w = _last_window;
|
w = _last_window;
|
||||||
|
|
||||||
if (w >= endof(_windows)) {
|
if (w >= endof(_windows)) {
|
||||||
for(w=_windows; ;w++) {
|
w = FindDeletableWindow();
|
||||||
assert(w < _last_window);
|
|
||||||
|
|
||||||
if (w->window_class != WC_MAIN_WINDOW && w->window_class != WC_MAIN_TOOLBAR &&
|
if (w == NULL) // no window found, force it!
|
||||||
w->window_class != WC_STATUS_BAR && w->window_class != WC_NEWS_WINDOW &&
|
w = ForceFindDeletableWindow();
|
||||||
!(w->flags4 & WF_STICKY) ) {
|
|
||||||
|
|
||||||
DeleteWindow(w);
|
DeleteWindow(w);
|
||||||
goto restart;
|
w = _last_window;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w != _windows && cls != WC_NEWS_WINDOW) {
|
if (w != _windows && cls != WC_NEWS_WINDOW) {
|
||||||
|
@ -1343,6 +1366,26 @@ void DeleteNonVitalWindows()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* It is possible that a stickied window gets to a position where the
|
||||||
|
* 'close' button is outside the gaming area. You cannot close it then; except
|
||||||
|
* with this function. It closes all windows calling the standard function,
|
||||||
|
* then, does a little hacked loop of closing all stickied windows. Note
|
||||||
|
* that standard windows (status bar, etc.) are not stickied, so these aren't affected */
|
||||||
|
void DeleteAllNonVitalWindows(void)
|
||||||
|
{
|
||||||
|
Window *w;
|
||||||
|
// Delete every window except for stickied ones
|
||||||
|
DeleteNonVitalWindows();
|
||||||
|
// Delete all sticked windows
|
||||||
|
for (w = _windows; w != _last_window;) {
|
||||||
|
if (w->flags4 & WF_STICKY) {
|
||||||
|
DeleteWindow(w);
|
||||||
|
w = _windows;
|
||||||
|
} else
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int PositionMainToolbar(Window *w)
|
int PositionMainToolbar(Window *w)
|
||||||
{
|
{
|
||||||
DEBUG(misc, 1) ("Repositioning Main Toolbar...");
|
DEBUG(misc, 1) ("Repositioning Main Toolbar...");
|
||||||
|
|
1
window.h
1
window.h
|
@ -459,6 +459,7 @@ void HandleButtonClick(Window *w, byte widget);
|
||||||
|
|
||||||
Window *GetCallbackWnd();
|
Window *GetCallbackWnd();
|
||||||
void DeleteNonVitalWindows();
|
void DeleteNonVitalWindows();
|
||||||
|
void DeleteAllNonVitalWindows(void);
|
||||||
|
|
||||||
/* window.c */
|
/* window.c */
|
||||||
VARDEF Window _windows[25];
|
VARDEF Window _windows[25];
|
||||||
|
|
Loading…
Reference in New Issue