GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windowmanager.cpp Lines: 81 170 47.6 %
Date: 2021-03-17 Branches: 73 202 36.1 %

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
205
void WindowManager::init()
115
{
116
    // Initialize frame limiting
117
205
    fpsManager.framecount = 0;
118
205
    fpsManager.rateticks = 0;
119
205
    fpsManager.lastticks = 0;
120
205
    fpsManager.rate = 0;
121
205
}
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
205
void WindowManager::deleteWindows()
182
{
183
#ifndef DYECMD
184
205
    delete2(textBoxPopup)
185
205
    delete2(beingPopup)
186
205
    delete2(itemPopup)
187
205
    delete2(spellPopup)
188
205
    delete2(skillPopup)
189
410
    delete2(popupMenu)
190
205
    delete2(didYouKnowWindow)
191
410
    delete2(helpWindow)
192
205
    delete2(setupWindow)
193
205
    delete2(userPalette)
194
205
    delete2(spellManager)
195
205
    delete2(spellShortcut)
196
197
205
    delete2(debugChatTab)
198
205
    delete2(chatWindow)
199
205
    delete2(debugWindow)
200
#endif  // DYECMD
201
202
205
    delete2(textPopup)
203
205
}
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
204
void WindowManager::deleteIcon()
496
{
497
204
    MSDL_FreeSurface(mIcon);
498
204
    mIcon = nullptr;
499
204
}