diff --git a/Notepad3.sln b/Notepad3.sln index 13ac42f23..1fd1fde39 100644 --- a/Notepad3.sln +++ b/Notepad3.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.4.33403.182 +# Visual Studio Version 18 +VisualStudioVersion = 18.6.11806.211 stable MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{D32CB10B-1891-471D-B780-5445BC67C1E2}" ProjectSection(SolutionItems) = preProject diff --git a/src/Notepad3.c b/src/Notepad3.c index 1e1441025..8e6a56ec0 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -777,6 +777,21 @@ static VOID CALLBACK TinyExprCopyTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEven // ---------------------------------------------------------------------------- +// Ends the temporary always-on-top window opened around a background URL launch +// (Ctrl+Shift+Click). Restores Notepad3's normal z-order from Settings.AlwaysOnTop. +static VOID CALLBACK _ForegroundLockReleaseTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + UNREFERENCED_PARAMETER(uMsg); + UNREFERENCED_PARAMETER(dwTime); + KillTimer(hwnd, idEvent); // one-shot + LockSetForegroundWindow(LSFW_UNLOCK); + SetWindowPos(hwnd, Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + SetForegroundWindow(hwnd); +} +// ---------------------------------------------------------------------------- + + //============================================================================= // // InvalidateStyleRedraw @@ -8899,7 +8914,18 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio Path_Release(hfile_pth); } else if (operation & OPEN_WITH_BROWSER) { // open in web browser or associated application - + + bool const bBackground = (operation & OPEN_BACKGROUND) != 0; + int const nShowFlag = bBackground ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL; + + if (bBackground) { + // Pin Notepad3 above the about-to-launch browser; SWP_NOACTIVATE keeps focus. + // The lock prevents the browser's async SetForegroundWindow from winning. + SetWindowPos(Globals.hwndMain, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + LockSetForegroundWindow(LSFW_LOCK); + } + HPATHL hDirectory = Path_Allocate(NULL); if (UrlIsFileUrl(szTextW)) { @@ -8929,7 +8955,7 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio sei.lpFile = StrgGet(Settings2.HyperlinkShellExURLWithApp); sei.lpParameters = StrgIsNotEmpty(hstr_params) ? StrgGet(hstr_params) : szUnEscW; sei.lpDirectory = Path_Get(hDirectory); - sei.nShow = SW_SHOWNORMAL; + sei.nShow = nShowFlag; bHandled = ShellExecuteExW(&sei); StrgDestroy(hstr_params); @@ -8945,10 +8971,16 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio sei.lpFile = szUnEscW; sei.lpParameters = NULL; sei.lpDirectory = Path_Get(hDirectory); - sei.nShow = SW_SHOWNORMAL; + sei.nShow = nShowFlag; bHandled = ShellExecuteExW(&sei); } + if (bBackground) { + // 600 ms covers the typical browser async-activation window with margin. + SetForegroundWindow(Globals.hwndMain); + SetTimer(Globals.hwndMain, ID_FGLOCKRELEASETIMER, 600, _ForegroundLockReleaseTimerProc); + } + Path_Release(hDirectory); } } @@ -9659,7 +9691,11 @@ static LRESULT _MsgNotifyFromEdit(HWND hwnd, const SCNotification* const scn) HandleHotSpotURLClicked(scn->position, OPEN_IN_NOTEPAD3); } } else if (_s_indic_click_modifiers & SCMOD_CTRL) { - HandleHotSpotURLClicked(scn->position, OPEN_WITH_BROWSER); // if applicable (file://) + // Ctrl+Shift+Click → open in background (browser behind, Notepad3 stays active) + HYPERLINK_OPS const op = (_s_indic_click_modifiers & SCMOD_SHIFT) + ? (HYPERLINK_OPS)(OPEN_WITH_BROWSER | OPEN_BACKGROUND) + : OPEN_WITH_BROWSER; + HandleHotSpotURLClicked(scn->position, op); // if applicable (file://) } } else if (SciCall_IndicatorValueAt(INDIC_NP3_COLOR_DEF, scn->position) > 0) { if (_s_indic_click_modifiers & SCMOD_CTRL) { diff --git a/src/Notepad3.h b/src/Notepad3.h index 0d04407eb..84453fe4e 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -72,6 +72,7 @@ np3params, *LPnp3params; #define ID_ATOMICSAVETIMER (0xA005) // Atomic Save Detection #define ID_DEFERMINIMIZETIMER (0xA006) // Deferred minimize on /B + /I startup #define ID_TINYEXPRCOPYTIMER (0xA007) // TinyExpr status-bar single-click copy debounce +#define ID_FGLOCKRELEASETIMER (0xA008) // Release LockSetForegroundWindow after background URL launch //==== Reuse Window Lock Timeout ============================================== diff --git a/src/TypeDefs.h b/src/TypeDefs.h index 08c3d8057..d3f9d44da 100644 --- a/src/TypeDefs.h +++ b/src/TypeDefs.h @@ -180,7 +180,7 @@ typedef COLORREF COLORALPHAREF; // ---------------------------------------------------------------------------- typedef enum COLOR_LAYER { BACKGROUND_LAYER = 0, FOREGROUND_LAYER = 1 } COLOR_LAYER; // Style_GetColor() -typedef enum HYPERLINK_OPS { OPEN_WITH_BROWSER = 1, OPEN_IN_NOTEPAD3 = (1<<1), OPEN_NEW_NOTEPAD3 = (1<<2), COPY_HYPERLINK = (1<<3), SELECT_HYPERLINK = (1<<4) } HYPERLINK_OPS; // Hyperlink Operations +typedef enum HYPERLINK_OPS { OPEN_WITH_BROWSER = 1, OPEN_IN_NOTEPAD3 = (1<<1), OPEN_NEW_NOTEPAD3 = (1<<2), COPY_HYPERLINK = (1<<3), SELECT_HYPERLINK = (1<<4), OPEN_BACKGROUND = (1<<5) } HYPERLINK_OPS; // Hyperlink Operations typedef enum FILE_WATCHING_MODE { FWM_NO_INIT = -1, FWM_DONT_CARE = 0, FWM_INDICATORSILENT = 1, FWM_MSGBOX = 2, FWM_AUTORELOAD = 3, FWM_EXCLUSIVELOCK = 4 } FILE_WATCHING_MODE; typedef enum FILE_WATCHING_METHOD { FWMTH_BOTH = 0, FWMTH_POLL = 1, FWMTH_PUSH = 2 } FILE_WATCHING_METHOD; typedef enum FOCUSVIEW_MARKER_MODE { FVMM_MARGIN = 1, FVMM_LN_BACKGR = 2, FVMM_FOLD = 4 } FOCUSVIEW_MARKER_MODE;