GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windowmanager.cpp Lines: 81 174 46.6 %
Date: 2021-03-17 Branches: 73 210 34.8 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2019  The ManaPlus Developers
6
 *  Copyright (C) 2019-2021  Andrei Karas
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "gui/windowmanager.h"
25
26
#include "client.h"
27
#include "configuration.h"
28
#include "game.h"
29
#include "main.h"
30
#include "settings.h"
31
#include "spellmanager.h"
32
33
#include "fs/virtfs/tools.h"
34
35
#include "gui/gui.h"
36
#include "gui/userpalette.h"
37
38
#include "gui/shortcut/spellshortcut.h"
39
40
#include "gui/popups/textpopup.h"
41
42
#ifdef DYECMD
43
#include "render/graphics.h"
44
#else  // DYECMD
45
#include "gui/popups/beingpopup.h"
46
#include "gui/popups/itempopup.h"
47
#include "gui/popups/popupmenu.h"
48
#include "gui/popups/skillpopup.h"
49
#include "gui/popups/spellpopup.h"
50
#include "gui/popups/textboxpopup.h"
51
52
#include "gui/windows/chatwindow.h"
53
#include "gui/windows/debugwindow.h"
54
#include "gui/windows/didyouknowwindow.h"
55
#include "gui/windows/equipmentwindow.h"
56
#include "gui/windows/helpwindow.h"
57
#include "gui/windows/setupwindow.h"
58
#include "gui/windows/skilldialog.h"
59
#include "gui/windows/questswindow.h"
60
61
#include "gui/widgets/tabs/chat/chattab.h"
62
63
#include "utils/gettext.h"
64
#endif  // DYECMD
65
66
#include "gui/widgets/createwidget.h"
67
#include "gui/widgets/desktop.h"
68
69
#include "input/touch/touchmanager.h"
70
71
#include "utils/delete2.h"
72
#include "utils/sdlcheckutils.h"
73
#include "utils/sdlhelper.h"
74
#ifdef __native_client__
75
#include "utils/naclmessages.h"
76
#endif  // __native_client__
77
78
PRAGMA48(GCC diagnostic push)
79
PRAGMA48(GCC diagnostic ignored "-Wshadow")
80
#ifdef ANDROID
81
#ifndef USE_SDL2
82
#include <SDL_screenkeyboard.h>
83
#endif  // USE_SDL2
84
#endif  // ANDROID
85
86
#ifdef USE_SDL2
87
#include <SDL2_framerate.h>
88
#else  // USE_SDL2
89
#include <SDL_framerate.h>
90
#endif  // USE_SDL2
91
92
#include <SDL_image.h>
93
94
#ifdef WIN32
95
#include <SDL_syswm.h>
96
#endif  // WIN32
97
PRAGMA48(GCC diagnostic pop)
98
99
#include "debug.h"
100
101
FPSmanager fpsManager;
102
103
namespace
104
{
105
    SDL_Surface *mIcon(nullptr);
106
#ifndef USE_SDL2
107
    int mKeyboardHeight(0);
108
#endif  // USE_SDL2
109
110
    bool mIsMinimized(false);
111
    bool mNewMessageFlag(false);
112
}  // namespace
113
114
216
void WindowManager::init()
115
{
116
    // Initialize frame limiting
117
216
    fpsManager.framecount = 0;
118
216
    fpsManager.rateticks = 0;
119
216
    fpsManager.lastticks = 0;
120
216
    fpsManager.rate = 0;
121
216
}
122
123
1
void WindowManager::createWindows()
124
{
125
✓✗
1
    userPalette = new UserPalette;
126
#ifndef DYECMD
127
✓✗
1
    CREATEWIDGETV0(setupWindow, SetupWindow);
128
✓✗
1
    CREATEWIDGETV0(helpWindow, HelpWindow);
129
✓✗
1
    CREATEWIDGETV0(didYouKnowWindow, DidYouKnowWindow);
130
✓✗
1
    CREATEWIDGETV0(popupMenu, PopupMenu);
131
✓✗
1
    CREATEWIDGETV0(beingPopup, BeingPopup);
132
✓✗
1
    CREATEWIDGETV0(textBoxPopup, TextBoxPopup);
133
✓✗
1
    CREATEWIDGETV0(itemPopup, ItemPopup);
134
✓✗
1
    CREATEWIDGETV0(spellPopup, SpellPopup);
135
✓✗
1
    CREATEWIDGETV0(skillPopup, SkillPopup);
136
✗✓
1
    delete2(debugChatTab)
137
✗✓
1
    if (chatWindow != nullptr)
138
    {
139
        chatWindow->scheduleDelete();
140
        chatWindow = nullptr;
141
    }
142
✓✗✓✗
4
    CREATEWIDGETV(chatWindow, ChatWindow,
143
1
        "DebugChat");
144
    // TRANSLATORS: chat tab header
145
2
    debugChatTab = new ChatTab(chatWindow, _("Debug"), "",
146
✓✗✓✗
✓✗✓✗
10
        "#Debug", ChatTabType::DEBUG);
147
2
    debugChatTab->setAllowHighlight(false);
148
1
    chatWindow->setVisible(Visible_false);
149
✗✓
1
    if (debugWindow != nullptr)
150
    {
151
        debugWindow->scheduleDelete();
152
        debugWindow = nullptr;
153
    }
154
✓✗✓✗
4
    CREATEWIDGETV(debugWindow, DebugWindow,
155
1
        "DebugDebug");
156
#endif  // DYECMD
157
158
✓✗
1
    CREATEWIDGETV0(textPopup, TextPopup);
159
1
}
160
161
void WindowManager::createValidateWindows()
162
{
163
#ifndef DYECMD
164
    CREATEWIDGETV0(skillDialog, SkillDialog);
165
    skillDialog->loadSkills();
166
    CREATEWIDGETV(beingEquipmentWindow, EquipmentWindow,
167
        nullptr, nullptr, true);
168
    CREATEWIDGETV0(questsWindow, QuestsWindow);
169
#endif  // DYECMD
170
}
171
172
void WindowManager::deleteValidateWindows()
173
{
174
#ifndef DYECMD
175
    delete2(skillDialog)
176
    delete2(beingEquipmentWindow)
177
    delete2(questsWindow)
178
#endif  // DYECMD
179
}
180
181
216
void WindowManager::deleteWindows()
182
{
183
#ifndef DYECMD
184
✓✓
216
    delete2(textBoxPopup)
185
✓✓
216
    delete2(beingPopup)
186
✓✓
216
    delete2(itemPopup)
187
✓✓
216
    delete2(spellPopup)
188
✓✓
216
    delete2(skillPopup)
189
✓✓
432
    delete2(popupMenu)
190
✓✓
216
    delete2(didYouKnowWindow)
191
✓✓
432
    delete2(helpWindow)
192
✓✓
216
    delete2(setupWindow)
193
✓✓
216
    delete2(userPalette)
194
✗✓
216
    delete2(spellManager)
195
✗✓
216
    delete2(spellShortcut)
196
197
✓✓
216
    delete2(debugChatTab)
198
✓✓
216
    delete2(chatWindow)
199
✓✓
216
    delete2(debugWindow)
200
#endif  // DYECMD
201
202
✓✓
216
    delete2(textPopup)
203
216
}
204
205
1
void WindowManager::initTitle()
206
{
207
✓✗
1
    if (settings.options.test.empty())
208
    {
209
✓✗
2
        settings.windowCaption = strprintf("%s %s",
210
✓✗
4
            branding.getStringValue("appName").c_str(),
211
1
            SMALL_VERSION);
212
    }
213
    else
214
    {
215
        settings.windowCaption = strprintf(
216
            "Please wait - VIDEO MODE TEST - %s %s - Please wait",
217
            branding.getStringValue("appName").c_str(),
218
            SMALL_VERSION);
219
    }
220
221
1
    SDL::SetWindowTitle(mainGraphics->getWindow(),
222
1
        settings.windowCaption.c_str());
223
1
}
224
225
3
void WindowManager::updateTitle()
226
{
227
6
    std::string str;
228
✓✓
3
    if (settings.login.empty())
229
        str = settings.serverName;
230
    else
231
✓✗
1
        str.append(settings.login).append(" ").append(settings.serverName);
232
✓✓
3
    if (str.empty())
233
    {
234
✓✗
2
        settings.windowCaption = strprintf("%s %s",
235
✓✗✓✗
4
            branding.getStringValue("appName").c_str(),
236
1
            SMALL_VERSION);
237
    }
238
    else
239
    {
240
✓✗
6
        settings.windowCaption = strprintf("%s %s - %s",
241
✓✗✓✗
8
            branding.getStringValue("appName").c_str(),
242
            SMALL_VERSION,
243
2
            str.c_str());
244
    }
245
3
    SDL::SetWindowTitle(mainGraphics->getWindow(),
246
✓✗
3
        settings.windowCaption.c_str());
247
3
}
248
249
6
void WindowManager::setFramerate(const unsigned int fpsLimit)
250
{
251
✓✓
6
    if (fpsLimit == 0U)
252
        return;
253
254
✓✓
4
    if (!settings.limitFps)
255
        return;
256
257
2
    SDL_setFramerate(&fpsManager, fpsLimit);
258
}
259
260
6
int WindowManager::getFramerate()
261
{
262
✓✓
6
    if (!settings.limitFps)
263
        return 0;
264
265
3
    return SDL_getFramerate(&fpsManager);
266
}
267
268
void WindowManager::doResizeVideo(const int actualWidth,
269
                                  const int actualHeight,
270
                                  const bool always)
271
{
272
    if (!always
273
        && mainGraphics->mActualWidth == actualWidth
274
        && mainGraphics->mActualHeight == actualHeight)
275
    {
276
        return;
277
    }
278
279
#ifdef __native_client__
280
    naclPostMessage("resize-window",
281
        strprintf("%d,%d", actualWidth, actualHeight));
282
#else  // __native_client__
283
284
    resizeVideo(actualWidth, actualHeight, always);
285
#endif  // __native_client__
286
}
287
288
void WindowManager::resizeVideo(int actualWidth,
289
                                int actualHeight,
290
                                const bool always)
291
{
292
    // Keep a minimum size. This isn't adhered to by the actual window, but
293
    // it keeps some window positions from getting messed up.
294
    actualWidth = std::max(470, actualWidth);
295
    actualHeight = std::max(320, actualHeight);
296
297
    if (mainGraphics == nullptr)
298
        return;
299
    if (!always
300
        && mainGraphics->mActualWidth == actualWidth
301
        && mainGraphics->mActualHeight == actualHeight)
302
    {
303
        return;
304
    }
305
306
    if (mainGraphics->resizeScreen(actualWidth, actualHeight))
307
    {
308
        const int width = mainGraphics->mWidth;
309
        const int height = mainGraphics->mHeight;
310
        touchManager.resize(width, height);
311
312
        if (gui != nullptr)
313
            gui->videoResized();
314
315
        if (desktop != nullptr)
316
            desktop->setSize(width, height);
317
318
        client->moveButtons(width);
319
320
#ifndef DYECMD
321
        Game *const game = Game::instance();
322
        if (game != nullptr)
323
            Game::videoResized(width, height);
324
#endif  // DYECMD
325
326
        if (gui != nullptr)
327
            gui->draw();
328
329
        config.setValue("screenwidth", actualWidth);
330
        config.setValue("screenheight", actualHeight);
331
    }
332
}
333
334
bool WindowManager::setFullScreen(const bool fs)
335
{
336
#ifdef __native_client__
337
    naclPostMessage("set-fullscreen",
338
        fs ? "on" : "off");
339
    return true;
340
#else  // __native_client__
341
342
    if (mainGraphics == nullptr)
343
        return false;
344
    return mainGraphics->setFullscreen(fs);
345
#endif  // __native_client__
346
}
347
348
void WindowManager::applyGrabMode()
349
{
350
    SDL::grabInput(mainGraphics->getWindow(),
351
        config.getBoolValue("grabinput"));
352
}
353
354
void WindowManager::applyGamma()
355
{
356
    if (config.getBoolValue("enableGamma"))
357
    {
358
        SDL::setGamma(mainGraphics->getWindow(),
359
            config.getFloatValue("gamma"));
360
    }
361
}
362
363
void WindowManager::applyVSync()
364
{
365
    const int val = config.getIntValue("vsync");
366
    if (val > 0 && val < 2)
367
        SDL::setVsync(val);
368
}
369
370
void WindowManager::applyKeyRepeat()
371
{
372
#ifndef USE_SDL2
373
    SDL_EnableKeyRepeat(config.getIntValue("repeateDelay"),
374
        config.getIntValue("repeateInterval"));
375
#endif  // USE_SDL2
376
}
377
378
void WindowManager::applyScale()
379
{
380
    const int scale = config.getIntValue("scale");
381
    if (mainGraphics->getScale() == scale)
382
        return;
383
    mainGraphics->setScale(scale);
384
    doResizeVideo(mainGraphics->mActualWidth,
385
        mainGraphics->mActualHeight,
386
        true);
387
}
388
389
void WindowManager::setIsMinimized(const bool n)
390
{
391
    mIsMinimized = n;
392
    if (!n && mNewMessageFlag)
393
    {
394
        mNewMessageFlag = false;
395
        SDL::SetWindowTitle(mainGraphics->getWindow(),
396
            settings.windowCaption.c_str());
397
    }
398
}
399
400
void WindowManager::newChatMessage()
401
{
402
    if (!mNewMessageFlag && mIsMinimized)
403
    {
404
        // show * on window caption
405
        SDL::SetWindowTitle(mainGraphics->getWindow(),
406
            ("*" + settings.windowCaption).c_str());
407
        mNewMessageFlag = true;
408
    }
409
}
410
411
void WindowManager::setIcon()
412
{
413
#if !defined(ANDROID) && !defined(__SWITCH__)
414
    std::string iconFile = branding.getValue("appIcon", "icons/manaplus");
415
#ifdef WIN32
416
    iconFile.append(".ico");
417
#else  // WIN32
418
419
    iconFile.append(".png");
420
#endif  // WIN32
421
422
    iconFile = VirtFs::getPath(iconFile);
423
    logger->log("Loading icon from file: %s", iconFile.c_str());
424
425
#ifdef WIN32
426
    static SDL_SysWMinfo pInfo;
427
    if (mainGraphics)
428
        SDL::getWindowWMInfo(mainGraphics->getWindow(), &pInfo);
429
    else
430
        SDL::getWindowWMInfo(nullptr, &pInfo);
431
    // Attempt to load icon from .ico file
432
    HICON icon = static_cast<HICON>(LoadImage(nullptr,
433
        iconFile.c_str(),
434
        IMAGE_ICON,
435
        64, 64,
436
        LR_LOADFROMFILE));
437
    // If it's failing, we load the default resource file.
438
    if (!icon)
439
    {
440
        logger->log("icon load error");
441
        icon = LoadIcon(GetModuleHandle(nullptr), "A");
442
    }
443
    if (icon)
444
    {
445
#ifdef WIN64
446
        SetClassLongPtr(pInfo.window,
447
            GCLP_HICON,
448
            reinterpret_cast<LONG_PTR>(icon));
449
#else  // WIN64
450
        SetClassLong(pInfo.window,
451
            GCL_HICON,
452
            reinterpret_cast<LONG>(icon));
453
#endif  // WIN64
454
    }
455
#else  // WIN32
456
457
    mIcon = MIMG_Load(iconFile.c_str());
458
    if (mIcon != nullptr)
459
    {
460
#ifdef USE_SDL2
461
        SDL_SetSurfaceAlphaMod(mIcon, SDL_ALPHA_OPAQUE);
462
#else  // USE_SDL2
463
464
        SDL_SetAlpha(mIcon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
465
#endif  // USE_SDL2
466
467
        SDL::SetWindowIcon(mainGraphics->getWindow(), mIcon);
468
    }
469
#endif  // WIN32
470
#endif  // ANDROID
471
}
472
473
bool WindowManager::isKeyboardVisible()
474
{
475
#ifdef USE_SDL2
476
    return SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE;
477
#else  // USE_SDL2
478
479
    return mKeyboardHeight > 1;
480
#endif  // USE_SDL2
481
}
482
483
bool WindowManager::getIsMinimized()
484
{
485
    return mIsMinimized;
486
}
487
488
#ifndef USE_SDL2
489
void WindowManager::updateScreenKeyboard(const int height)
490
{
491
    mKeyboardHeight = height;
492
}
493
#endif  // USE_SDL2
494
495
215
void WindowManager::deleteIcon()
496
{
497
215
    MSDL_FreeSurface(mIcon);
498
215
    mIcon = nullptr;
499
215
}