Skip to content

Commit b6b1f1f

Browse files
Allow excluding windows from being closed via Esc
Add a "pin" function to in-game windows. The function replaces the shade (aka. minimize) button and the window can instead be shaded by double-clicking the title bar. Pinned windows are excluded from being closed by the window manager when hitting the Escape key.
1 parent adb7189 commit b6b1f1f

3 files changed

Lines changed: 59 additions & 15 deletions

File tree

libs/s25main/WindowManager.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,14 @@ void WindowManager::RelayKeyboardMessage(KeyboardMsgHandler msg, const KeyEvent&
132132
return; // No windows -> nothing to do
133133

134134
// ESC or ALT+W closes the active window
135-
if(ke.kt == KeyType::Escape || (ke.c == 'w' && ke.alt))
135+
const auto escape = (ke.kt == KeyType::Escape);
136+
if(escape || (ke.c == 'w' && ke.alt))
136137
{
137138
// Find one which isn't yet marked for closing so multiple ESC in between draw calls can close multiple windows
138-
const auto itActiveWnd =
139-
std::find_if(windows.rbegin(), windows.rend(), [](const auto& wnd) { return !wnd->ShouldBeClosed(); });
139+
// ESC won't close pinned windows
140+
const auto itActiveWnd = std::find_if(windows.rbegin(), windows.rend(), [escape](const auto& wnd) {
141+
return !wnd->ShouldBeClosed() && !(escape && wnd->IsPinned());
142+
});
140143
if(itActiveWnd != windows.rend() && (*itActiveWnd)->getCloseBehavior() != CloseBehavior::Custom)
141144
(*itActiveWnd)->Close();
142145
} else if(!CALL_MEMBER_FN(*windows.back(), msg)(ke)) // send to active window

libs/s25main/ingameWindows/IngameWindow.cpp

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ constexpr Extent IngameWindow::ButtonSize;
3434
IngameWindow::IngameWindow(unsigned id, const DrawPoint& pos, const Extent& size, std::string title,
3535
glArchivItem_Bitmap* background, bool modal, CloseBehavior closeBehavior, Window* parent)
3636
: Window(parent, id, pos, size), title_(std::move(title)), background(background), lastMousePos(0, 0),
37-
isModal_(modal), closeme(false), isMinimized_(false), isMoving(false), closeBehavior_(closeBehavior),
38-
buttonStates_({ButtonState::Up, ButtonState::Up})
37+
isModal_(modal), closeme(false), isPinned_(false), isMinimized_(false), isMoving(false),
38+
closeBehavior_(closeBehavior), buttonStates_({ButtonState::Up, ButtonState::Up, ButtonState::Up})
3939
{
4040
contentOffset.x = LOADER.GetImageN("resource", 38)->getWidth(); // left border
4141
contentOffset.y = LOADER.GetImageN("resource", 42)->getHeight(); // title bar
@@ -168,14 +168,31 @@ void IngameWindow::MouseLeftUp(const MouseCoords& mc)
168168
buttonStates_[id] = ButtonState::Up;
169169

170170
if((id == IwButtonId::Close && closeBehavior_ == CloseBehavior::Custom) // no close button
171-
|| (id != IwButtonId::Close && isModal_)) // modal windows cannot be minimized
171+
|| (id != IwButtonId::Close && isModal_)) // modal windows cannot be pinned or minimized
172+
continue;
173+
174+
if(IsPointInRect(mc.GetPos(), GetButtonBounds(id)))
172175
{
173176
switch(id)
174177
{
175178
case IwButtonId::Close: Close(); break;
176-
case IwButtonId::Minimize:
177-
SetMinimized(!IsMinimized());
178-
LOADER.GetSoundN("sound", 113)->Play(255, false);
179+
case IwButtonId::Title:
180+
if(SETTINGS.interface.enableWindowPinning && mc.dbl_click)
181+
{
182+
SetMinimized(!IsMinimized());
183+
LOADER.GetSoundN("sound", 113)->Play(255, false);
184+
}
185+
break;
186+
case IwButtonId::PinOrMinimize:
187+
if(SETTINGS.interface.enableWindowPinning)
188+
{
189+
SetPinned(!IsPinned());
190+
LOADER.GetSoundN("sound", 111)->Play(255, false);
191+
} else
192+
{
193+
SetMinimized(!IsMinimized());
194+
LOADER.GetSoundN("sound", 113)->Play(255, false);
195+
}
179196
break;
180197
}
181198
}
@@ -248,11 +265,25 @@ void IngameWindow::Draw_()
248265
using ButtonStateResIds = helpers::EnumArray<uint16_t, ButtonState>;
249266
constexpr ButtonStateResIds closeButtonResIds = {47, 55, 51};
250267
constexpr ButtonStateResIds minimizeButtonResIds = {48, 56, 52};
268+
constexpr ButtonStateResIds pinButtonBaseResIds = {47, 47, 51};
269+
constexpr ButtonStateResIds pinButtonOverlayResIds = {0, 1, 2};
270+
constexpr ButtonStateResIds unpinButtonOverlayResIds = {3, 4, 5};
251271
if(closeBehavior_ != CloseBehavior::Custom)
252272
LOADER.GetImageN("resource", closeButtonResIds[buttonStates_[IwButtonId::Close]])->DrawFull(GetPos());
253273
if(!IsModal())
254-
LOADER.GetImageN("resource", minimizeButtonResIds[buttonStates_[IwButtonId::Minimize]])
255-
->DrawFull(GetButtonBounds(IwButtonId::Minimize));
274+
{
275+
const auto buttonState = buttonStates_[IwButtonId::PinOrMinimize];
276+
const auto bounds = GetButtonBounds(IwButtonId::PinOrMinimize);
277+
if(SETTINGS.interface.enableWindowPinning)
278+
{
279+
LOADER.GetImageN("resource", pinButtonBaseResIds[buttonState])->DrawFull(bounds);
280+
if(isPinned_)
281+
LOADER.GetImageN("resource_new", unpinButtonOverlayResIds[buttonState])->DrawFull(bounds);
282+
else
283+
LOADER.GetImageN("resource_new", pinButtonOverlayResIds[buttonState])->DrawFull(bounds);
284+
} else
285+
LOADER.GetImageN("resource", minimizeButtonResIds[buttonState])->DrawFull(bounds);
286+
}
256287

257288
// The title bar
258289
unsigned titleIndex;
@@ -367,10 +398,15 @@ void IngameWindow::SaveOpenStatus(bool isOpen) const
367398
Rect IngameWindow::GetButtonBounds(IwButtonId id) const
368399
{
369400
auto pos = GetPos();
401+
auto size = ButtonSize;
370402
switch(id)
371403
{
372404
case IwButtonId::Close: break;
373-
case IwButtonId::Minimize: pos.x += GetSize().x - ButtonSize.x; break;
405+
case IwButtonId::Title:
406+
pos.x += TitleMargin;
407+
size.x = GetSize().x - TitleMargin * 2;
408+
break;
409+
case IwButtonId::PinOrMinimize: pos.x += GetSize().x - ButtonSize.x; break;
374410
}
375-
return Rect(pos, ButtonSize);
411+
return Rect(pos, size);
376412
}

libs/s25main/ingameWindows/IngameWindow.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ enum CloseBehavior
2828
enum class IwButtonId : unsigned short
2929
{
3030
Close,
31-
Minimize
31+
Title, /// Pseudo-button to respond to double-clicks on the title bar
32+
PinOrMinimize
3233
};
3334
constexpr auto maxEnumValue(IwButtonId)
3435
{
35-
return IwButtonId::Minimize;
36+
return IwButtonId::PinOrMinimize;
3637
}
3738

3839
class IngameWindow : public Window
@@ -82,6 +83,9 @@ class IngameWindow : public Window
8283
/// ist das Fenster minimiert?
8384
bool IsMinimized() const { return isMinimized_; }
8485

86+
void SetPinned(bool pinned = true) { isPinned_ = pinned; }
87+
bool IsPinned() const { return isPinned_; }
88+
8589
CloseBehavior getCloseBehavior() const { return closeBehavior_; }
8690

8791
/// Modal windows cannot be minimized, are always active and stay on top of non-modal ones
@@ -125,6 +129,7 @@ class IngameWindow : public Window
125129

126130
bool isModal_;
127131
bool closeme;
132+
bool isPinned_;
128133
bool isMinimized_;
129134
bool isMoving;
130135
CloseBehavior closeBehavior_;

0 commit comments

Comments
 (0)