Fixed the "lost" panels issue

Implement some size limits for the Notepad++ docked and floating panels, as the users often "lost" its panels (e.g. when they minimized them to zero width or height).

This also fixes the config.xml possible previous "out-of-the-allowed-range" data.

Fix #13084, close #15236
pull/15261/head
xomx 2024-06-03 20:12:25 +02:00 committed by Don Ho
parent e7e88a380a
commit 8beda66cb8
5 changed files with 204 additions and 40 deletions

View File

@ -811,10 +811,16 @@ LRESULT Notepad_plus::init(HWND hwnd)
DockingManagerData& dmd = nppGUI._dockingData;
// preset minimal panel dimensions according to the current DPI
dmd._minDockedPanelVisibility = DPIManagerV2::scale(nppGUI._dockingData._minDockedPanelVisibility, dpi);
dmd._minFloatingPanelSize.cy = nppGUI._dockingData._minDockedPanelVisibility;
dmd._minFloatingPanelSize.cx = std::max(static_cast<int>(nppGUI._dockingData._minFloatingPanelSize.cy * 6),
DPIManagerV2::getSystemMetricsForDpi(SM_CXMINTRACK, dpi));
_dockingManager.setDockedContSize(CONT_LEFT, nppGUI._dockingData._leftWidth);
_dockingManager.setDockedContSize(CONT_RIGHT, nppGUI._dockingData._rightWidth);
_dockingManager.setDockedContSize(CONT_TOP, nppGUI._dockingData._topHeight);
_dockingManager.setDockedContSize(CONT_BOTTOM, nppGUI._dockingData._bottomHight);
_dockingManager.setDockedContSize(CONT_BOTTOM, nppGUI._dockingData._bottomHeight);
{
for (size_t i = 0, len = dmd._pluginDockInfo.size(); i < len; ++i)
@ -996,7 +1002,7 @@ void Notepad_plus::saveDockingParams()
nppGUI._dockingData._leftWidth = _dockingManager.getDockedContSize(CONT_LEFT);
nppGUI._dockingData._rightWidth = _dockingManager.getDockedContSize(CONT_RIGHT);
nppGUI._dockingData._topHeight = _dockingManager.getDockedContSize(CONT_TOP);
nppGUI._dockingData._bottomHight = _dockingManager.getDockedContSize(CONT_BOTTOM);
nppGUI._dockingData._bottomHeight = _dockingManager.getDockedContSize(CONT_BOTTOM);
// clear the container tab information (active tab)
nppGUI._dockingData._containerTabInfo.clear();
@ -1091,7 +1097,7 @@ void Notepad_plus::saveDockingParams()
}
nppGUI._dockingData._pluginDockInfo = vPluginDockInfo;
nppGUI._dockingData._flaotingWindowInfo = vFloatingWindowInfo;
nppGUI._dockingData._floatingWindowInfo = vFloatingWindowInfo;
}

View File

@ -24,6 +24,7 @@
#include "localizationString.h"
#include "UserDefineDialog.h"
#include "WindowsDlgRc.h"
#include "Notepad_plus_Window.h"
#ifdef _MSC_VER
#pragma warning(disable : 4996) // for GetVersionEx()
@ -6715,18 +6716,110 @@ void NppParameters::feedDockingManager(TiXmlNode *node)
{
TiXmlElement *element = node->ToElement();
SIZE maxMonitorSize{ ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) }; // use primary monitor as the default
SIZE nppSize = maxMonitorSize;
HWND hwndNpp = ::FindWindow(Notepad_plus_Window::getClassName(), NULL);
if (hwndNpp)
{
// TODO:
// the problem here is that this code-branch cannot be currently reached
// (as it is called at the Notepad++ startup in the wWinMain nppParameters.load())
HMONITOR hCurMon = ::MonitorFromWindow(hwndNpp, MONITOR_DEFAULTTONEAREST);
if (hCurMon)
{
MONITORINFO mi{};
mi.cbSize = sizeof(MONITORINFO);
if (::GetMonitorInfo(hCurMon, &mi))
{
maxMonitorSize.cx = mi.rcMonitor.right - mi.rcMonitor.left;
maxMonitorSize.cy = mi.rcMonitor.bottom - mi.rcMonitor.top;
nppSize = maxMonitorSize;
}
}
RECT rcNpp{};
if (::GetClientRect(hwndNpp, &rcNpp))
{
nppSize.cx = rcNpp.right;
nppSize.cy = rcNpp.bottom;
}
}
else
{
// no real Notepad++ wnd available, so try to use the previously saved config.xml data instead
if (!_nppGUI._isMaximized)
{
if (((_nppGUI._appPos.right > DMD_PANEL_WH_DEFAULT) && (_nppGUI._appPos.right < maxMonitorSize.cx))
&& ((_nppGUI._appPos.bottom > DMD_PANEL_WH_DEFAULT) && (_nppGUI._appPos.bottom < maxMonitorSize.cy)))
{
nppSize.cx = _nppGUI._appPos.right;
nppSize.cy = _nppGUI._appPos.bottom;
}
}
}
int i;
if (element->Attribute(TEXT("leftWidth"), &i))
_nppGUI._dockingData._leftWidth = i;
{
if (i > _nppGUI._dockingData._minDockedPanelVisibility)
{
if (i < (nppSize.cx - _nppGUI._dockingData._minDockedPanelVisibility))
_nppGUI._dockingData._leftWidth = i;
else
_nppGUI._dockingData._leftWidth = nppSize.cx - _nppGUI._dockingData._minDockedPanelVisibility; // invalid, reset
}
else
{
// invalid, reset
_nppGUI._dockingData._leftWidth = _nppGUI._dockingData._minDockedPanelVisibility;
}
}
if (element->Attribute(TEXT("rightWidth"), &i))
_nppGUI._dockingData._rightWidth = i;
{
if (i > _nppGUI._dockingData._minDockedPanelVisibility)
{
if (i < (nppSize.cx - _nppGUI._dockingData._minDockedPanelVisibility))
_nppGUI._dockingData._rightWidth = i;
else
_nppGUI._dockingData._rightWidth = nppSize.cx - _nppGUI._dockingData._minDockedPanelVisibility; // invalid, reset
}
else
{
// invalid, reset
_nppGUI._dockingData._rightWidth = _nppGUI._dockingData._minDockedPanelVisibility;
}
}
if (element->Attribute(TEXT("topHeight"), &i))
_nppGUI._dockingData._topHeight = i;
{
if (i > _nppGUI._dockingData._minDockedPanelVisibility)
{
if (i < (nppSize.cy - _nppGUI._dockingData._minDockedPanelVisibility))
_nppGUI._dockingData._topHeight = i;
else
_nppGUI._dockingData._topHeight = nppSize.cy - _nppGUI._dockingData._minDockedPanelVisibility; // invalid, reset
}
else
{
// invalid, reset
_nppGUI._dockingData._topHeight = _nppGUI._dockingData._minDockedPanelVisibility;
}
}
if (element->Attribute(TEXT("bottomHeight"), &i))
_nppGUI._dockingData._bottomHight = i;
{
if (i > _nppGUI._dockingData._minDockedPanelVisibility)
{
if (i < (nppSize.cy - _nppGUI._dockingData._minDockedPanelVisibility))
_nppGUI._dockingData._bottomHeight = i;
else
_nppGUI._dockingData._bottomHeight = nppSize.cy - _nppGUI._dockingData._minDockedPanelVisibility; // invalid, reset
}
else
{
// invalid, reset
_nppGUI._dockingData._bottomHeight = _nppGUI._dockingData._minDockedPanelVisibility;
}
}
for (TiXmlNode *childNode = node->FirstChildElement(TEXT("FloatingWindow"));
childNode ;
@ -6738,14 +6831,44 @@ void NppParameters::feedDockingManager(TiXmlNode *node)
{
int x = 0;
int y = 0;
int w = 100;
int h = 100;
int w = FWI_PANEL_WH_DEFAULT;
int h = FWI_PANEL_WH_DEFAULT;
floatElement->Attribute(TEXT("x"), &x);
floatElement->Attribute(TEXT("y"), &y);
floatElement->Attribute(TEXT("width"), &w);
floatElement->Attribute(TEXT("height"), &h);
_nppGUI._dockingData._flaotingWindowInfo.push_back(FloatingWindowInfo(cont, x, y, w, h));
if (floatElement->Attribute(TEXT("x"), &x))
{
if ((x > (maxMonitorSize.cx - 1)) || (x < 0))
x = 0; // invalid, reset
}
if (floatElement->Attribute(TEXT("y"), &y))
{
if ((y > (maxMonitorSize.cy - 1)) || (y < 0))
y = 0; // invalid, reset
}
if (floatElement->Attribute(TEXT("width"), &w))
{
if (w > maxMonitorSize.cx)
{
w = maxMonitorSize.cx; // invalid, reset
}
else
{
if (w < _nppGUI._dockingData._minFloatingPanelSize.cx)
w = _nppGUI._dockingData._minFloatingPanelSize.cx; // invalid, reset
}
}
if (floatElement->Attribute(TEXT("height"), &h))
{
if (h > maxMonitorSize.cy)
{
h = maxMonitorSize.cy; // invalid, reset
}
else
{
if (h < _nppGUI._dockingData._minFloatingPanelSize.cy)
h = _nppGUI._dockingData._minFloatingPanelSize.cy; // invalid, reset
}
}
_nppGUI._dockingData._floatingWindowInfo.push_back(FloatingWindowInfo(cont, x, y, w, h));
}
}
@ -7715,11 +7838,11 @@ void NppParameters::insertDockingParamNode(TiXmlNode *GUIRoot)
DMNode.SetAttribute(TEXT("leftWidth"), _nppGUI._dockingData._leftWidth);
DMNode.SetAttribute(TEXT("rightWidth"), _nppGUI._dockingData._rightWidth);
DMNode.SetAttribute(TEXT("topHeight"), _nppGUI._dockingData._topHeight);
DMNode.SetAttribute(TEXT("bottomHeight"), _nppGUI._dockingData._bottomHight);
DMNode.SetAttribute(TEXT("bottomHeight"), _nppGUI._dockingData._bottomHeight);
for (size_t i = 0, len = _nppGUI._dockingData._flaotingWindowInfo.size(); i < len ; ++i)
for (size_t i = 0, len = _nppGUI._dockingData._floatingWindowInfo.size(); i < len ; ++i)
{
FloatingWindowInfo & fwi = _nppGUI._dockingData._flaotingWindowInfo[i];
FloatingWindowInfo & fwi = _nppGUI._dockingData._floatingWindowInfo[i];
TiXmlElement FWNode(TEXT("FloatingWindow"));
FWNode.SetAttribute(TEXT("cont"), fwi._cont);
FWNode.SetAttribute(TEXT("x"), fwi._pos.left);

View File

@ -32,6 +32,7 @@
#include <map>
#include "ILexer.h"
#include "Lexilla.h"
#include "DockingCont.h"
#ifdef _WIN64
@ -325,10 +326,11 @@ struct CmdLineParamsDTO
}
};
#define FWI_PANEL_WH_DEFAULT 100
struct FloatingWindowInfo
{
int _cont = 0;
RECT _pos = {};
RECT _pos = { 0, 0, FWI_PANEL_WH_DEFAULT, FWI_PANEL_WH_DEFAULT };
FloatingWindowInfo(int cont, int x, int y, int w, int h)
: _cont(cont)
@ -370,27 +372,32 @@ struct ContainerTabInfo final
};
#define DMD_PANEL_WH_DEFAULT 200
struct DockingManagerData final
{
int _leftWidth = 200;
int _rightWidth = 200;
int _topHeight = 200;
int _bottomHight = 200;
int _leftWidth = DMD_PANEL_WH_DEFAULT;
int _rightWidth = DMD_PANEL_WH_DEFAULT;
int _topHeight = DMD_PANEL_WH_DEFAULT;
int _bottomHeight = DMD_PANEL_WH_DEFAULT;
std::vector<FloatingWindowInfo> _flaotingWindowInfo;
// will be updated at runtime (Notepad_plus::init & DockingManager::runProc DMM_MOVE_SPLITTER)
LONG _minDockedPanelVisibility = HIGH_CAPTION;
SIZE _minFloatingPanelSize = { (HIGH_CAPTION) * 6, HIGH_CAPTION };
std::vector<FloatingWindowInfo> _floatingWindowInfo;
std::vector<PluginDlgDockingInfo> _pluginDockInfo;
std::vector<ContainerTabInfo> _containerTabInfo;
bool getFloatingRCFrom(int floatCont, RECT& rc) const
{
for (size_t i = 0, fwiLen = _flaotingWindowInfo.size(); i < fwiLen; ++i)
for (size_t i = 0, fwiLen = _floatingWindowInfo.size(); i < fwiLen; ++i)
{
if (_flaotingWindowInfo[i]._cont == floatCont)
if (_floatingWindowInfo[i]._cont == floatCont)
{
rc.left = _flaotingWindowInfo[i]._pos.left;
rc.top = _flaotingWindowInfo[i]._pos.top;
rc.right = _flaotingWindowInfo[i]._pos.right;
rc.bottom = _flaotingWindowInfo[i]._pos.bottom;
rc.left = _floatingWindowInfo[i]._pos.left;
rc.top = _floatingWindowInfo[i]._pos.top;
rc.right = _floatingWindowInfo[i]._pos.right;
rc.bottom = _floatingWindowInfo[i]._pos.bottom;
return true;
}
}

View File

@ -1153,6 +1153,18 @@ intptr_t CALLBACK DockingCont::run_dlgProc(UINT Message, WPARAM wParam, LPARAM l
onSize();
break;
}
case WM_GETMINMAXINFO:
{
if (_isFloating)
{
// ensure a reasonable minimal size of the floating panels
LPMINMAXINFO pMinMax = reinterpret_cast<LPMINMAXINFO>(lParam);
pMinMax->ptMinTrackSize.x = NppParameters::getInstance().getNppGUI()._dockingData._minFloatingPanelSize.cx;
pMinMax->ptMinTrackSize.y = NppParameters::getInstance().getNppGUI()._dockingData._minFloatingPanelSize.cy;
return 0;
}
break;
}
case WM_ERASEBKGND:
{
if (!NppDarkMode::isEnabled())

View File

@ -300,17 +300,33 @@ LRESULT DockingManager::runProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
{
int offset = static_cast<int32_t>(wParam);
NppGUI& nppGUI = (NppParameters::getInstance()).getNppGUI();
for (int iCont = 0; iCont < DOCKCONT_MAX; ++iCont)
{
if (_vSplitter[iCont]->getHSelf() == reinterpret_cast<HWND>(lParam))
{
RECT rcPanelCaption{};
if (::GetWindowRect(_vContainer[iCont]->getCaptionWnd(), &rcPanelCaption))
{
LONG currentPanelHeight = rcPanelCaption.bottom - rcPanelCaption.top;
if (currentPanelHeight != nppGUI._dockingData._minDockedPanelVisibility)
{
// update with current value (important for multi-monitors setups or a runtime change of display DPI)
nppGUI._dockingData._minDockedPanelVisibility = currentPanelHeight;
nppGUI._dockingData._minFloatingPanelSize.cy = currentPanelHeight;
nppGUI._dockingData._minFloatingPanelSize.cx = std::max(static_cast<int>(nppGUI._dockingData._minFloatingPanelSize.cy * 6),
::GetSystemMetrics(SM_CXMINTRACK));
}
}
switch (iCont)
{
case CONT_TOP:
_dockData.rcRegion[iCont].bottom -= offset;
if (_dockData.rcRegion[iCont].bottom < 0)
if (_dockData.rcRegion[iCont].bottom < nppGUI._dockingData._minDockedPanelVisibility)
{
_dockData.rcRegion[iCont].bottom = 0;
_dockData.rcRegion[iCont].bottom = nppGUI._dockingData._minDockedPanelVisibility;
}
if ((_rcWork.bottom < (-SPLITTER_WIDTH)) && (offset < 0))
{
@ -319,9 +335,9 @@ LRESULT DockingManager::runProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
break;
case CONT_BOTTOM:
_dockData.rcRegion[iCont].bottom += offset;
if (_dockData.rcRegion[iCont].bottom < 0)
if (_dockData.rcRegion[iCont].bottom < nppGUI._dockingData._minDockedPanelVisibility)
{
_dockData.rcRegion[iCont].bottom = 0;
_dockData.rcRegion[iCont].bottom = nppGUI._dockingData._minDockedPanelVisibility;
}
if ((_rcWork.bottom < (-SPLITTER_WIDTH)) && (offset > 0))
{
@ -330,9 +346,9 @@ LRESULT DockingManager::runProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
break;
case CONT_LEFT:
_dockData.rcRegion[iCont].right -= offset;
if (_dockData.rcRegion[iCont].right < 0)
if (_dockData.rcRegion[iCont].right < nppGUI._dockingData._minDockedPanelVisibility)
{
_dockData.rcRegion[iCont].right = 0;
_dockData.rcRegion[iCont].right = nppGUI._dockingData._minDockedPanelVisibility;
}
if ((_rcWork.right < SPLITTER_WIDTH) && (offset < 0))
{
@ -341,9 +357,9 @@ LRESULT DockingManager::runProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
break;
case CONT_RIGHT:
_dockData.rcRegion[iCont].right += offset;
if (_dockData.rcRegion[iCont].right < 0)
if (_dockData.rcRegion[iCont].right < nppGUI._dockingData._minDockedPanelVisibility)
{
_dockData.rcRegion[iCont].right = 0;
_dockData.rcRegion[iCont].right = nppGUI._dockingData._minDockedPanelVisibility;
}
if ((_rcWork.right < SPLITTER_WIDTH) && (offset > 0))
{