Fix flickering issue if Doc is deleted from outside

Improve behavior when notifying the user about a buffer change (opened file changed or deleted)
- Restore the Notepad++ window and switch to the document in question *before* showing the dialog (this was only done afterwards before)
- Fix flickering issue described in #1018 and #2010 which was exposed by f2cd779066

Closes #2956
This commit is contained in:
Eduard Braun 2017-02-24 23:47:19 +01:00 committed by Don HO
parent 61bc5e27bb
commit ffe2ddace3
2 changed files with 28 additions and 43 deletions

View File

@ -4963,6 +4963,27 @@ void Notepad_plus::drawTabbarColoursFromStylerArray()
TabBarPlus::setColour(stInact->_bgColor, TabBarPlus::inactiveBg); TabBarPlus::setColour(stInact->_bgColor, TabBarPlus::inactiveBg);
} }
void Notepad_plus::prepareBufferChangedDialog(Buffer * buffer)
{
// immediately show window if it was minimized before
if (::IsIconic(_pPublicInterface->getHSelf()))
::ShowWindow(_pPublicInterface->getHSelf(), SW_RESTORE);
// switch to the file that changed
int index = _pDocTab->getIndexByBuffer(buffer->getID());
int iView = currentView();
if (index == -1)
iView = otherView();
activateBuffer(buffer->getID(), iView); //activate the buffer in the first view possible
// prevent flickering issue by "manually" clicking and activating the _pEditView
// (mouse events seem to get lost / improperly handled when showing the dialog)
auto curPos = _pEditView->execute(SCI_GETCURRENTPOS);
::PostMessage(_pEditView->getHSelf(), WM_LBUTTONDOWN, 0, 0);
::PostMessage(_pEditView->getHSelf(), WM_LBUTTONUP, 0, 0);
::PostMessage(_pEditView->getHSelf(), SCI_SETSEL, curPos, curPos);
}
void Notepad_plus::notifyBufferChanged(Buffer * buffer, int mask) void Notepad_plus::notifyBufferChanged(Buffer * buffer, int mask)
{ {
// To avoid to crash while MS-DOS style is set as default language, // To avoid to crash while MS-DOS style is set as default language,
@ -4983,8 +5004,6 @@ void Notepad_plus::notifyBufferChanged(Buffer * buffer, int mask)
//Only event that applies to non-active Buffers //Only event that applies to non-active Buffers
if (mask & BufferChangeStatus) if (mask & BufferChangeStatus)
{ //reload etc { //reload etc
bool didDialog = false;
bool doCloseDoc = false;
switch(buffer->getStatus()) switch(buffer->getStatus())
{ {
case DOC_UNNAMED: //nothing todo case DOC_UNNAMED: //nothing todo
@ -4997,28 +5016,9 @@ void Notepad_plus::notifyBufferChanged(Buffer * buffer, int mask)
bool autoUpdate = (nppGUI._fileAutoDetection == cdAutoUpdate) || (nppGUI._fileAutoDetection == cdAutoUpdateGo2end); bool autoUpdate = (nppGUI._fileAutoDetection == cdAutoUpdate) || (nppGUI._fileAutoDetection == cdAutoUpdateGo2end);
if (!autoUpdate || buffer->isDirty()) if (!autoUpdate || buffer->isDirty())
{ {
// if file updating is not silently, we switch to the file to update. prepareBufferChangedDialog(buffer);
int index = _pDocTab->getIndexByBuffer(buffer->getID());
int iView = currentView();
if (index == -1)
iView = otherView();
activateBuffer(buffer->getID(), iView); //activate the buffer in the first view possible
// Then we ask user to update
didDialog = true;
// This section deal with the flicking issue which was caused by f2cd779 (discussed in detail @ #1018)
// Idea is :
// 1. First get the current caret position.
// 2. Send WM_LBUTTONDOWN and WM_LBUTTONUP message (which acts as double click at 0,0)
// 3. Now set caret back to original position.
//
auto curPos = _pEditView->execute(SCI_GETCURRENTPOS);
::PostMessage(_pEditView->getHSelf(), WM_LBUTTONDOWN, 0, 0);
::PostMessage(_pEditView->getHSelf(), WM_LBUTTONUP, 0, 0);
::PostMessage(_pEditView->getHSelf(), SCI_SETSEL, curPos, curPos);
// Now the flickering issue is not seen.
// Then we ask user to update
if (doReloadOrNot(buffer->getFullPathName(), buffer->isDirty()) != IDYES) if (doReloadOrNot(buffer->getFullPathName(), buffer->isDirty()) != IDYES)
break; //abort break; //abort
} }
@ -5050,42 +5050,26 @@ void Notepad_plus::notifyBufferChanged(Buffer * buffer, int mask)
} }
case DOC_DELETED: //ask for keep case DOC_DELETED: //ask for keep
{ {
prepareBufferChangedDialog(buffer);
SCNotification scnN; SCNotification scnN;
scnN.nmhdr.code = NPPN_FILEDELETED; scnN.nmhdr.code = NPPN_FILEDELETED;
scnN.nmhdr.hwndFrom = _pPublicInterface->getHSelf(); scnN.nmhdr.hwndFrom = _pPublicInterface->getHSelf();
scnN.nmhdr.idFrom = (uptr_t)buffer->getID(); scnN.nmhdr.idFrom = (uptr_t)buffer->getID();
_pluginsManager.notify(&scnN); _pluginsManager.notify(&scnN);
int index = _pDocTab->getIndexByBuffer(buffer->getID()); int doCloseDoc = doCloseOrNot(buffer->getFullPathName()) == IDNO;
int iView = currentView();
if (index == -1)
iView = otherView();
activateBuffer(buffer->getID(), iView); //activate the buffer in the first view possible
didDialog = true;
doCloseDoc = doCloseOrNot(buffer->getFullPathName()) == IDNO;
if (doCloseDoc) if (doCloseDoc)
{ {
//close in both views, doing current view last since that has to remain opened //close in both views, doing current view last since that has to remain opened
bool isSnapshotMode = nppGUI.isSnapshotMode(); bool isSnapshotMode = nppGUI.isSnapshotMode();
doClose(buffer->getID(), otherView(), isSnapshotMode); doClose(buffer->getID(), otherView(), isSnapshotMode);
doClose(buffer->getID(), currentView(), isSnapshotMode); doClose(buffer->getID(), currentView(), isSnapshotMode);
return;
} }
break; break;
} }
} }
if (didDialog)
{
auto curPos = _pEditView->execute(SCI_GETCURRENTPOS);
::PostMessage(_pEditView->getHSelf(), WM_LBUTTONUP, 0, 0);
::PostMessage(_pEditView->getHSelf(), SCI_SETSEL, curPos, curPos);
if (::IsIconic(_pPublicInterface->getHSelf()))
::ShowWindow(_pPublicInterface->getHSelf(), SW_RESTORE);
if (doCloseDoc) // buffer has been deleted, cannot (and no need to) go on
return;
}
} }
if (mask & (BufferChangeReadonly)) if (mask & (BufferChangeReadonly))

View File

@ -207,6 +207,7 @@ public:
void loadLastSession(); void loadLastSession();
bool loadSession(Session & session, bool isSnapshotMode = false); bool loadSession(Session & session, bool isSnapshotMode = false);
void prepareBufferChangedDialog(Buffer * buffer);
void notifyBufferChanged(Buffer * buffer, int mask); void notifyBufferChanged(Buffer * buffer, int mask);
bool findInFinderFiles(FindersInfo *findInFolderInfo); bool findInFinderFiles(FindersInfo *findInFolderInfo);
bool findInFiles(); bool findInFiles();