+ add: enable vertical scrolling by "Shift + Mouse-Wheel"

This commit is contained in:
Rainer Kottenhoff 2021-01-24 09:37:56 +01:00
parent ae9c01699d
commit 5113d0ba7f
3 changed files with 78 additions and 60 deletions

View File

@ -236,38 +236,38 @@ constexpr float componentMaximum = 255.0F;
class ColourDesired {
unsigned int co;
public:
explicit ColourDesired(unsigned int co_ = 0) noexcept : co(co_) {}
constexpr explicit ColourDesired(unsigned int co_ = 0) noexcept : co(co_) {}
ColourDesired(unsigned int red, unsigned int green, unsigned int blue) noexcept :
co(red | (green << 8) | (blue << 16)) {}
bool operator==(const ColourDesired &other) const noexcept {
constexpr bool operator==(const ColourDesired &other) const noexcept {
return co == other.co;
}
unsigned int AsInteger() const noexcept {
constexpr unsigned int AsInteger() const noexcept {
return co;
}
// Red, green and blue values as bytes 0..255
unsigned char GetRed() const noexcept {
constexpr unsigned char GetRed() const noexcept {
return co & 0xff;
}
unsigned char GetGreen() const noexcept {
constexpr unsigned char GetGreen() const noexcept {
return (co >> 8) & 0xff;
}
unsigned char GetBlue() const noexcept {
constexpr unsigned char GetBlue() const noexcept {
return (co >> 16) & 0xff;
}
// Red, green and blue values as float 0..1.0
float GetRedComponent() const noexcept {
constexpr float GetRedComponent() const noexcept {
return GetRed() / componentMaximum;
}
float GetGreenComponent() const noexcept {
constexpr float GetGreenComponent() const noexcept {
return GetGreen() / componentMaximum;
}
float GetBlueComponent() const noexcept {
constexpr float GetBlueComponent() const noexcept {
return GetBlue() / componentMaximum;
}
};
@ -277,7 +277,7 @@ public:
*/
class ColourAlpha : public ColourDesired {
public:
explicit ColourAlpha(unsigned int co_ = 0) noexcept : ColourDesired(co_) {}
constexpr explicit ColourAlpha(unsigned int co_ = 0) noexcept : ColourDesired(co_) {}
ColourAlpha(unsigned int red, unsigned int green, unsigned int blue) noexcept :
ColourDesired(red | (green << 8) | (blue << 16)) {}
@ -287,15 +287,15 @@ public:
ColourAlpha(ColourDesired cd, unsigned int alpha) noexcept :
ColourDesired(cd.AsInteger() | (alpha << 24)) {}
ColourDesired GetColour() const noexcept {
constexpr ColourDesired GetColour() const noexcept {
return ColourDesired(AsInteger() & 0xffffff);
}
unsigned char GetAlpha() const noexcept {
constexpr unsigned char GetAlpha() const noexcept {
return (AsInteger() >> 24) & 0xff;
}
float GetAlphaComponent() const noexcept {
constexpr float GetAlphaComponent() const noexcept {
return GetAlpha() / componentMaximum;
}

View File

@ -538,7 +538,7 @@ public:
};
using TextPositions = VarBuffer<XYPOSITION, stackBufferLength>;
class SurfaceGDI : public Surface {
class SurfaceGDI final : public Surface {
bool unicodeMode = false;
HDC hdc{};
bool hdcOwned = false;
@ -798,7 +798,7 @@ constexpr byte AlphaScaled(unsigned char component, unsigned int alpha) noexcept
return static_cast<byte>(component * alpha / 255);
}
const inline DWORD dwordMultiplied(ColourDesired colour, unsigned int alpha) noexcept {
constexpr DWORD dwordMultiplied(ColourDesired colour, unsigned int alpha) noexcept {
return dwordFromBGRA(
AlphaScaled(colour.GetBlue(), alpha),
AlphaScaled(colour.GetGreen(), alpha),
@ -1206,7 +1206,7 @@ constexpr D2D1_RECT_F RectangleFromPRectangle(PRectangle rc) noexcept {
class BlobInline;
class SurfaceD2D : public Surface {
class SurfaceD2D final : public Surface {
bool unicodeMode = false;
int x = 0;
int y = 0;
@ -1553,25 +1553,27 @@ void SurfaceD2D::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesir
void SurfaceD2D::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
ColourDesired outline, int alphaOutline, int /* flags*/) {
if (pRenderTarget) {
float const left = std::round(rc.left);
float const right = std::round(rc.right);
if (cornerSize == 0) {
// When corner size is zero, draw square rectangle to prevent blurry pixels at corners
const D2D1_RECT_F rectFill = D2D1::RectF(std::round(rc.left) + 1.0f, rc.top + 1.0f, std::round(rc.right) - 1.0f, rc.bottom - 1.0f);
const D2D1_RECT_F rectFill = D2D1::RectF(left + 1.0f, rc.top + 1.0f, right - 1.0f, rc.bottom - 1.0f);
D2DPenColour(fill, alphaFill);
pRenderTarget->FillRectangle(rectFill, pBrush);
const D2D1_RECT_F rectOutline = D2D1::RectF(std::round(rc.left) + 0.5f, rc.top + 0.5f, std::round(rc.right) - 0.5f, rc.bottom - 0.5f);
const D2D1_RECT_F rectOutline = D2D1::RectF(left + 0.5f, rc.top + 0.5f, right - 0.5f, rc.bottom - 0.5f);
D2DPenColour(outline, alphaOutline);
pRenderTarget->DrawRectangle(rectOutline, pBrush);
} else {
const float cornerSizeF = static_cast<float>(cornerSize);
D2D1_ROUNDED_RECT roundedRectFill = {
D2D1::RectF(std::round(rc.left) + 1.0f, rc.top + 1.0f, std::round(rc.right) - 1.0f, rc.bottom - 1.0f),
D2D1::RectF(left + 1.0f, rc.top + 1.0f, right - 1.0f, rc.bottom - 1.0f),
cornerSizeF - 1.0f, cornerSizeF - 1.0f };
D2DPenColour(fill, alphaFill);
pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
D2D1_ROUNDED_RECT roundedRect = {
D2D1::RectF(std::round(rc.left) + 0.5f, rc.top + 0.5f, std::round(rc.right) - 0.5f, rc.bottom - 0.5f),
D2D1::RectF(left + 0.5f, rc.top + 0.5f, right - 0.5f, rc.bottom - 0.5f),
cornerSizeF, cornerSizeF };
D2DPenColour(outline, alphaOutline);
pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush);
@ -1581,12 +1583,13 @@ void SurfaceD2D::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fil
namespace {
inline D2D_COLOR_F ColorFromColourAlpha(ColourAlpha colour) noexcept {
D2D_COLOR_F col;
col.r = colour.GetRedComponent();
col.g = colour.GetGreenComponent();
col.b = colour.GetBlueComponent();
col.a = colour.GetAlphaComponent();
constexpr D2D_COLOR_F ColorFromColourAlpha(ColourAlpha colour) noexcept {
D2D_COLOR_F col = {
colour.GetRedComponent(),
colour.GetGreenComponent(),
colour.GetBlueComponent(),
colour.GetAlphaComponent()
};
return col;
}
@ -1623,8 +1626,9 @@ void SurfaceD2D::GradientRectangle(PRectangle rc, const std::vector<ColourStop>
if (SUCCEEDED(hr) && pBrushLinear) {
const D2D1_RECT_F rectangle = D2D1::RectF(std::round(rc.left), rc.top, std::round(rc.right), rc.bottom);
pRenderTarget->FillRectangle(&rectangle, pBrushLinear);
ReleaseUnknown(pBrushLinear);
}
ReleaseUnknown(pBrushLinear);
ReleaseUnknown(pGradientStops);
}
}
@ -2570,7 +2574,7 @@ ListBox::ListBox() noexcept = default;
ListBox::~ListBox() = default;
class ListBoxX : public ListBox {
class ListBoxX final : public ListBox {
int lineHeight;
FontID fontCopy;
int technology;
@ -3462,13 +3466,7 @@ LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam
wheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
if (std::abs(wheelDelta) >= WHEEL_DELTA) {
const int nRows = GetVisibleRows();
int linesToScroll = 1;
if (nRows > 1) {
linesToScroll = nRows - 1;
}
if (linesToScroll > 3) {
linesToScroll = 3;
}
int linesToScroll = std::clamp(nRows - 1, 1, 3);
linesToScroll *= (wheelDelta / WHEEL_DELTA);
int top = ListBox_GetTopIndex(lb) + linesToScroll;
if (top < 0) {

View File

@ -231,7 +231,7 @@ class ScintillaWin; // Forward declaration for COM interface subobjects
/**
*/
class FormatEnumerator : public IEnumFORMATETC {
class FormatEnumerator final : public IEnumFORMATETC {
ULONG ref;
ULONG pos;
std::vector<CLIPFORMAT> formats;
@ -254,7 +254,7 @@ public:
/**
*/
class DropSource : public IDropSource {
class DropSource final : public IDropSource {
public:
ScintillaWin *sci = nullptr;
DropSource() noexcept = default;
@ -272,7 +272,7 @@ public:
/**
*/
class DataObject : public IDataObject {
class DataObject final : public IDataObject {
public:
ScintillaWin *sci = nullptr;
DataObject() noexcept = default;
@ -297,7 +297,7 @@ public:
/**
*/
class DropTarget : public IDropTarget {
class DropTarget final : public IDropTarget {
public:
ScintillaWin *sci = nullptr;
DropTarget() noexcept = default;
@ -434,7 +434,8 @@ class ScintillaWin final :
SetCoalescableTimerSig SetCoalescableTimerFn;
#endif
unsigned int linesPerScroll; ///< Intellimouse support
UINT linesPerScroll; ///< Intellimouse support
UINT charsPerScroll; ///< Intellimouse support
int wheelDelta; ///< Wheel delta from roll
DPI_T dpi = { USER_DEFAULT_SCREEN_DPI, USER_DEFAULT_SCREEN_DPI };
@ -676,6 +677,7 @@ ScintillaWin::ScintillaWin(HWND hwnd) {
#endif
linesPerScroll = 0;
charsPerScroll = 0;
wheelDelta = 0; // Wheel delta from roll
dpi = GetWindowDPI(hwnd);
@ -763,8 +765,8 @@ void ScintillaWin::Init() noexcept {
void ScintillaWin::Finalise() noexcept {
ScintillaBase::Finalise();
for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast<TickReason>(tr + 1)) {
FineTickerCancel(tr);
for (int tr = tickCaret; tr <= tickDwell; tr = tr + 1) {
FineTickerCancel(static_cast<TickReason>(tr));
}
SetIdle(false);
#if defined(USE_D2D)
@ -884,7 +886,7 @@ bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) noexcept {
const XYPOSITION xMove = std::trunc(std::abs(ptDifference.x));
const XYPOSITION yMove = std::trunc(std::abs(ptDifference.y));
return (xMove > SystemMetricsForDpi(SM_CXDRAG, dpi.x)) ||
(yMove > SystemMetricsForDpi(SM_CYDRAG, dpi.y));
(yMove > SystemMetricsForDpi(SM_CYDRAG, dpi.y));
}
void ScintillaWin::StartDrag() {
@ -1457,16 +1459,16 @@ unsigned int SciMessageFromEM(unsigned int iMessage) noexcept {
case EM_LINEINDEX: return SCI_POSITIONFROMLINE;
case EM_LINESCROLL: return SCI_LINESCROLL;
case EM_REDO: return SCI_REDO;
case EM_UNDO: return SCI_UNDO;
case EM_SCROLL: return WM_VSCROLL;
case EM_REPLACESEL: return SCI_REPLACESEL;
case EM_SCROLL: return WM_VSCROLL;
case EM_SCROLLCARET: return SCI_SCROLLCARET;
case EM_SETREADONLY: return SCI_SETREADONLY;
case EM_UNDO: return SCI_UNDO;
case WM_CLEAR: return SCI_CLEAR;
case WM_COPY: return SCI_COPY;
case WM_CUT: return SCI_CUT;
case WM_SETTEXT: return SCI_SETTEXT;
case WM_PASTE: return SCI_PASTE;
case WM_SETTEXT: return SCI_SETTEXT;
case WM_UNDO: return SCI_UNDO;
}
return iMessage;
@ -1709,21 +1711,40 @@ sptr_t ScintillaWin::MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t l
// (A good idea for datazoom would be to "fold" or "unfold" details.
// i.e. if datazoomed out only class structures are visible, when datazooming in the control
// structures appear, then eventually the individual statements...)
if (wParam & (MK_SHIFT | MK_RBUTTON)) {
// send to client
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
//@@@if (wParam & (MK_SHIFT | MK_RBUTTON)) {
if (wParam & MK_SHIFT) {
if (vs.wrapState != WrapMode::none || charsPerScroll == 0) {
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
}
}
// Either SCROLL or ZOOM. We handle the wheel steppings calculation
wheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
if (std::abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) {
if (std::abs(wheelDelta) < WHEEL_DELTA) {
return 0;
}
if (wParam & MK_SHIFT) {
int charsToScroll = charsPerScroll;
if (charsPerScroll == WHEEL_PAGESCROLL) {
const PRectangle rcText = GetTextRectangle();
const int pageWidth = static_cast<int>(rcText.Width() * 2 / 3);
charsToScroll = pageWidth;
} else {
charsToScroll = 1 + static_cast<int>(std::max(charsToScroll, 1) * vs.aveCharWidth);
}
charsToScroll *= (wheelDelta / WHEEL_DELTA);
if (wheelDelta >= 0) {
wheelDelta = wheelDelta % WHEEL_DELTA;
} else {
wheelDelta = -(-wheelDelta % WHEEL_DELTA);
}
HorizontalScrollTo(xOffset + charsToScroll);
} else if (linesPerScroll > 0) {
Sci::Line linesToScroll = linesPerScroll;
if (linesPerScroll == WHEEL_PAGESCROLL) {
linesToScroll = LinesOnScreen() - 1;
}
if (linesToScroll == 0) {
linesToScroll = 1;
}
linesToScroll = std::max<Sci::Line>(linesToScroll, 1);
linesToScroll *= (wheelDelta / WHEEL_DELTA);
if (wheelDelta >= 0) {
wheelDelta = wheelDelta % WHEEL_DELTA;
@ -1739,10 +1760,8 @@ sptr_t ScintillaWin::MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t l
} else {
KeyCommand(SCI_ZOOMOUT);
}
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
// send to main window too !
// send to main window too (trigger Zoom CallTip) !
::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
} else {
// Scroll
ScrollTo(topLine + linesToScroll);
@ -3251,6 +3270,7 @@ LRESULT ScintillaWin::ImeOnReconvert(LPARAM lParam) {
void ScintillaWin::GetIntelliMouseParameters() noexcept {
// This retrieves the number of lines per scroll as configured in the Mouse Properties sheet in Control Panel
::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &charsPerScroll, 0);
}
void ScintillaWin::CopyToGlobal(GlobalMemory &gmUnicode, const SelectionText &selectedText, CopyEncoding encoding) {
@ -3341,7 +3361,7 @@ void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
}
void ScintillaWin::ScrollMessage(WPARAM wParam) {
//DWORD dwStart = timeGetTime();
//DWORD dwStart = GetTickCount();
//Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam);
SCROLLINFO sci = {};
@ -3752,7 +3772,7 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, PO
NotifyURIDropped(putf.c_str());
} else {
FORMATETC fmtr = { cfColumnSelect, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
const bool isRectangular = (S_OK == pIDataSource->QueryGetData(&fmtr));
const bool isRectangular = S_OK == pIDataSource->QueryGetData(&fmtr);
POINT rpt = { pt.x, pt.y };
::ScreenToClient(MainHWND(), &rpt);
@ -3824,7 +3844,7 @@ bool ScintillaWin::Register(HINSTANCE hInstance_) noexcept {
wndclass.lpszClassName = L"Scintilla";
scintillaClassAtom = ::RegisterClassExW(&wndclass);
const bool result = (0 != scintillaClassAtom);
const bool result = 0 != scintillaClassAtom;
return result;
}
@ -4002,7 +4022,7 @@ namespace Scintilla {
}
#else
extern "C"
sptr_t __stdcall Scintilla_DirectFunction(
sptr_t SCI_METHOD Scintilla_DirectFunction(
ScintillaWin* sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
return sci->WndProc(iMessage, wParam, lParam);
}