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; 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_LEFT, nppGUI._dockingData._leftWidth);
_dockingManager.setDockedContSize(CONT_RIGHT, nppGUI._dockingData._rightWidth); _dockingManager.setDockedContSize(CONT_RIGHT, nppGUI._dockingData._rightWidth);
_dockingManager.setDockedContSize(CONT_TOP, nppGUI._dockingData._topHeight); _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) 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._leftWidth = _dockingManager.getDockedContSize(CONT_LEFT);
nppGUI._dockingData._rightWidth = _dockingManager.getDockedContSize(CONT_RIGHT); nppGUI._dockingData._rightWidth = _dockingManager.getDockedContSize(CONT_RIGHT);
nppGUI._dockingData._topHeight = _dockingManager.getDockedContSize(CONT_TOP); 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) // clear the container tab information (active tab)
nppGUI._dockingData._containerTabInfo.clear(); nppGUI._dockingData._containerTabInfo.clear();
@ -1091,7 +1097,7 @@ void Notepad_plus::saveDockingParams()
} }
nppGUI._dockingData._pluginDockInfo = vPluginDockInfo; nppGUI._dockingData._pluginDockInfo = vPluginDockInfo;
nppGUI._dockingData._flaotingWindowInfo = vFloatingWindowInfo; nppGUI._dockingData._floatingWindowInfo = vFloatingWindowInfo;
} }

View File

@ -24,6 +24,7 @@
#include "localizationString.h" #include "localizationString.h"
#include "UserDefineDialog.h" #include "UserDefineDialog.h"
#include "WindowsDlgRc.h" #include "WindowsDlgRc.h"
#include "Notepad_plus_Window.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4996) // for GetVersionEx() #pragma warning(disable : 4996) // for GetVersionEx()
@ -6715,18 +6716,110 @@ void NppParameters::feedDockingManager(TiXmlNode *node)
{ {
TiXmlElement *element = node->ToElement(); 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; int i;
if (element->Attribute(TEXT("leftWidth"), &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)) 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)) 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)) 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")); for (TiXmlNode *childNode = node->FirstChildElement(TEXT("FloatingWindow"));
childNode ; childNode ;
@ -6738,14 +6831,44 @@ void NppParameters::feedDockingManager(TiXmlNode *node)
{ {
int x = 0; int x = 0;
int y = 0; int y = 0;
int w = 100; int w = FWI_PANEL_WH_DEFAULT;
int h = 100; int h = FWI_PANEL_WH_DEFAULT;
floatElement->Attribute(TEXT("x"), &x); if (floatElement->Attribute(TEXT("x"), &x))
floatElement->Attribute(TEXT("y"), &y); {
floatElement->Attribute(TEXT("width"), &w); if ((x > (maxMonitorSize.cx - 1)) || (x < 0))
floatElement->Attribute(TEXT("height"), &h); x = 0; // invalid, reset
_nppGUI._dockingData._flaotingWindowInfo.push_back(FloatingWindowInfo(cont, x, y, w, h)); }
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("leftWidth"), _nppGUI._dockingData._leftWidth);
DMNode.SetAttribute(TEXT("rightWidth"), _nppGUI._dockingData._rightWidth); DMNode.SetAttribute(TEXT("rightWidth"), _nppGUI._dockingData._rightWidth);
DMNode.SetAttribute(TEXT("topHeight"), _nppGUI._dockingData._topHeight); 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")); TiXmlElement FWNode(TEXT("FloatingWindow"));
FWNode.SetAttribute(TEXT("cont"), fwi._cont); FWNode.SetAttribute(TEXT("cont"), fwi._cont);
FWNode.SetAttribute(TEXT("x"), fwi._pos.left); FWNode.SetAttribute(TEXT("x"), fwi._pos.left);

View File

@ -32,6 +32,7 @@
#include <map> #include <map>
#include "ILexer.h" #include "ILexer.h"
#include "Lexilla.h" #include "Lexilla.h"
#include "DockingCont.h"
#ifdef _WIN64 #ifdef _WIN64
@ -325,10 +326,11 @@ struct CmdLineParamsDTO
} }
}; };
#define FWI_PANEL_WH_DEFAULT 100
struct FloatingWindowInfo struct FloatingWindowInfo
{ {
int _cont = 0; 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) FloatingWindowInfo(int cont, int x, int y, int w, int h)
: _cont(cont) : _cont(cont)
@ -370,27 +372,32 @@ struct ContainerTabInfo final
}; };
#define DMD_PANEL_WH_DEFAULT 200
struct DockingManagerData final struct DockingManagerData final
{ {
int _leftWidth = 200; int _leftWidth = DMD_PANEL_WH_DEFAULT;
int _rightWidth = 200; int _rightWidth = DMD_PANEL_WH_DEFAULT;
int _topHeight = 200; int _topHeight = DMD_PANEL_WH_DEFAULT;
int _bottomHight = 200; 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<PluginDlgDockingInfo> _pluginDockInfo;
std::vector<ContainerTabInfo> _containerTabInfo; std::vector<ContainerTabInfo> _containerTabInfo;
bool getFloatingRCFrom(int floatCont, RECT& rc) const 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.left = _floatingWindowInfo[i]._pos.left;
rc.top = _flaotingWindowInfo[i]._pos.top; rc.top = _floatingWindowInfo[i]._pos.top;
rc.right = _flaotingWindowInfo[i]._pos.right; rc.right = _floatingWindowInfo[i]._pos.right;
rc.bottom = _flaotingWindowInfo[i]._pos.bottom; rc.bottom = _floatingWindowInfo[i]._pos.bottom;
return true; return true;
} }
} }

View File

@ -1153,6 +1153,18 @@ intptr_t CALLBACK DockingCont::run_dlgProc(UINT Message, WPARAM wParam, LPARAM l
onSize(); onSize();
break; 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: case WM_ERASEBKGND:
{ {
if (!NppDarkMode::isEnabled()) 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); int offset = static_cast<int32_t>(wParam);
NppGUI& nppGUI = (NppParameters::getInstance()).getNppGUI();
for (int iCont = 0; iCont < DOCKCONT_MAX; ++iCont) for (int iCont = 0; iCont < DOCKCONT_MAX; ++iCont)
{ {
if (_vSplitter[iCont]->getHSelf() == reinterpret_cast<HWND>(lParam)) 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) switch (iCont)
{ {
case CONT_TOP: case CONT_TOP:
_dockData.rcRegion[iCont].bottom -= offset; _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)) if ((_rcWork.bottom < (-SPLITTER_WIDTH)) && (offset < 0))
{ {
@ -319,9 +335,9 @@ LRESULT DockingManager::runProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
break; break;
case CONT_BOTTOM: case CONT_BOTTOM:
_dockData.rcRegion[iCont].bottom += offset; _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)) if ((_rcWork.bottom < (-SPLITTER_WIDTH)) && (offset > 0))
{ {
@ -330,9 +346,9 @@ LRESULT DockingManager::runProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
break; break;
case CONT_LEFT: case CONT_LEFT:
_dockData.rcRegion[iCont].right -= offset; _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)) if ((_rcWork.right < SPLITTER_WIDTH) && (offset < 0))
{ {
@ -341,9 +357,9 @@ LRESULT DockingManager::runProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM l
break; break;
case CONT_RIGHT: case CONT_RIGHT:
_dockData.rcRegion[iCont].right += offset; _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)) if ((_rcWork.right < SPLITTER_WIDTH) && (offset > 0))
{ {