Files
test2/intern/ghost/intern/GHOST_EventPrinter.cc
Jacques Lucke afd760f2b7 UI: Ghost: support horizontal scrolling for 2D editors
Some mice have an additional horizontal scroll wheel. This patch adds support
for receiving such events. By default it is used to scroll 2D editors left and right.

I originally developed this because I was missing it in the spreadsheet, but it
seems to be useful in many other editors too.

It's supported on Linux (Wayland), Windows and macos.

Pull Request: https://projects.blender.org/blender/blender/pulls/138758
2025-05-14 13:33:10 +02:00

375 lines
12 KiB
C++

/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup GHOST
* Declaration of GHOST_EventPrinter class.
*/
#include "GHOST_EventPrinter.hh"
#include "GHOST_Debug.hh"
#include "GHOST_EventDragnDrop.hh"
#include "GHOST_EventKey.hh"
#include <iomanip>
#include <iostream>
/* For now only used with NDOF. */
#ifdef WITH_INPUT_NDOF
static const char *getButtonActionString(const GHOST_TButtonAction action)
{
switch (action) {
case GHOST_kPress:
return "Press";
case GHOST_kRelease:
return "Release";
}
return "Unknown";
}
#endif /* WITH_INPUT_NDOF */
bool GHOST_EventPrinter::processEvent(const GHOST_IEvent *event)
{
bool handled = false;
GHOST_ASSERT(event, "event==0");
if (event->getType() == GHOST_kEventWindowUpdate) {
return false;
}
GHOST_TEventDataPtr data = event->getData();
std::cout << "GHOST_EventPrinter::processEvent, time: " << int32_t(event->getTime())
<< ", type: ";
#define CASE_TYPE(ty) \
case ty: { \
std::cout << #ty; \
handled = true; \
break; \
} \
((void)0)
const GHOST_TEventType event_type = event->getType();
switch (event_type) {
case GHOST_kEventUnknown: {
std::cout << "GHOST_kEventUnknown";
handled = false;
break;
}
case GHOST_kEventCursorMove: {
const GHOST_TEventCursorData *cursorData = static_cast<const GHOST_TEventCursorData *>(data);
std::cout << "GHOST_kEventCursorMove, (x,y): (" << cursorData->x << "," << cursorData->y
<< ")";
handled = true;
break;
}
case GHOST_kEventButtonDown: {
const GHOST_TEventButtonData *buttonData = static_cast<const GHOST_TEventButtonData *>(data);
std::cout << "GHOST_kEventButtonDown, button: " << buttonData->button;
handled = true;
break;
}
case GHOST_kEventButtonUp: {
const GHOST_TEventButtonData *buttonData = static_cast<const GHOST_TEventButtonData *>(data);
std::cout << "GHOST_kEventCursorButtonUp, button: " << buttonData->button;
handled = true;
break;
}
case GHOST_kEventWheel: {
const GHOST_TEventWheelData *wheelData = static_cast<const GHOST_TEventWheelData *>(data);
std::cout << "GHOST_kEventWheel, axis: "
<< (wheelData->axis == GHOST_kEventWheelAxisVertical ? "vertical" : "horizontal")
<< ", value: " << wheelData->value;
handled = true;
break;
}
CASE_TYPE(GHOST_kEventTrackpad);
#ifdef WITH_INPUT_NDOF
case GHOST_kEventNDOFMotion: {
const GHOST_TEventNDOFMotionData *ndof_motion =
static_cast<const GHOST_TEventNDOFMotionData *>(data);
std::cout << "GHOST_kEventNDOFMotion: ";
std::cout << std::fixed << std::setprecision(2) <<
/* Translation. */
"tx=" << ndof_motion->tx << " ty=" << ndof_motion->tx << " tz=" << ndof_motion->tz <<
/* Rotation. */
"rx=" << ndof_motion->rx << " ry=" << ndof_motion->ry << " rz=" << ndof_motion->rz;
std::cout << std::fixed << std::setprecision(4) << " dt=" << ndof_motion->dt;
handled = true;
break;
}
case GHOST_kEventNDOFButton: {
const GHOST_TEventNDOFButtonData *ndof_button =
static_cast<const GHOST_TEventNDOFButtonData *>(data);
std::cout << "GHOST_kEventNDOFButton: " << getButtonActionString(ndof_button->action)
<< " button=" << ndof_button->button;
handled = true;
break;
}
#endif /* WITH_INPUT_NDOF */
case GHOST_kEventKeyDown: {
const GHOST_TEventKeyData *keyData = static_cast<const GHOST_TEventKeyData *>(data);
std::cout << "GHOST_kEventKeyDown, key: " << getKeyString(keyData->key);
handled = true;
break;
}
case GHOST_kEventKeyUp: {
const GHOST_TEventKeyData *keyData = static_cast<const GHOST_TEventKeyData *>(data);
std::cout << "GHOST_kEventKeyUp, key: " << getKeyString(keyData->key);
handled = true;
break;
}
CASE_TYPE(GHOST_kEventQuitRequest);
CASE_TYPE(GHOST_kEventWindowClose);
CASE_TYPE(GHOST_kEventWindowActivate);
CASE_TYPE(GHOST_kEventWindowDeactivate);
CASE_TYPE(GHOST_kEventWindowUpdate);
CASE_TYPE(GHOST_kEventWindowUpdateDecor);
CASE_TYPE(GHOST_kEventWindowSize);
CASE_TYPE(GHOST_kEventWindowMove);
CASE_TYPE(GHOST_kEventWindowDPIHintChanged);
case GHOST_kEventDraggingEntered: {
const GHOST_TEventDragnDropData *dragnDropData =
static_cast<const GHOST_TEventDragnDropData *>(data);
std::cout << "GHOST_kEventDraggingEntered, dragged object type : "
<< dragnDropData->dataType;
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
handled = true;
break;
}
case GHOST_kEventDraggingUpdated: {
const GHOST_TEventDragnDropData *dragnDropData =
static_cast<const GHOST_TEventDragnDropData *>(data);
std::cout << "GHOST_kEventDraggingUpdated, dragged object type : "
<< dragnDropData->dataType;
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
handled = true;
break;
}
case GHOST_kEventDraggingExited: {
const GHOST_TEventDragnDropData *dragnDropData =
static_cast<const GHOST_TEventDragnDropData *>(data);
std::cout << "GHOST_kEventDraggingExited, dragged object type : " << dragnDropData->dataType;
handled = true;
break;
}
case GHOST_kEventDraggingDropDone: {
const GHOST_TEventDragnDropData *dragnDropData =
static_cast<const GHOST_TEventDragnDropData *>(data);
std::cout << "GHOST_kEventDraggingDropDone,";
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
switch (dragnDropData->dataType) {
case GHOST_kDragnDropTypeString: {
std::cout << " type : GHOST_kDragnDropTypeString,";
std::cout << "\n String received = " << (char *)dragnDropData->data;
break;
}
case GHOST_kDragnDropTypeFilenames: {
GHOST_TStringArray *strArray = (GHOST_TStringArray *)dragnDropData->data;
int i;
std::cout << " type : GHOST_kDragnDropTypeFilenames,";
std::cout << "\n Received " << strArray->count << " filename"
<< (strArray->count > 1 ? "s:" : ":");
for (i = 0; i < strArray->count; i++) {
std::cout << "\n File[" << i << "] : " << strArray->strings[i];
}
break;
}
default: {
break;
}
}
handled = true;
break;
}
case GHOST_kEventOpenMainFile: {
if (data) {
std::cout << "GHOST_kEventOpenMainFile for path: " << static_cast<const char *>(data);
}
else {
std::cout << "GHOST_kEventOpenMainFile with no path specified!!";
}
handled = true;
break;
}
CASE_TYPE(GHOST_kEventNativeResolutionChange);
CASE_TYPE(GHOST_kEventImeCompositionStart);
CASE_TYPE(GHOST_kEventImeComposition);
CASE_TYPE(GHOST_kEventImeCompositionEnd);
}
#undef CASE_TYPE
if ((handled == false) && event_type != GHOST_kEventUnknown) {
std::cout << "not found";
}
std::cout << std::endl;
std::cout.flush();
return handled;
}
const char *GHOST_EventPrinter::getKeyString(const GHOST_TKey key) const
{
const char *tstr = nullptr;
#define CASE_KEY(k, v) \
case k: { \
tstr = v; \
break; \
}
switch (key) {
CASE_KEY(GHOST_kKeyBackSpace, "BackSpace");
CASE_KEY(GHOST_kKeyTab, "Tab");
CASE_KEY(GHOST_kKeyLinefeed, "Linefeed");
CASE_KEY(GHOST_kKeyClear, "Clear");
CASE_KEY(GHOST_kKeyEnter, "Enter");
CASE_KEY(GHOST_kKeyEsc, "Esc");
CASE_KEY(GHOST_kKeySpace, "Space");
CASE_KEY(GHOST_kKeyQuote, "Quote");
CASE_KEY(GHOST_kKeyBackslash, "\\");
CASE_KEY(GHOST_kKeyAccentGrave, "`");
CASE_KEY(GHOST_kKeyLeftShift, "LeftShift");
CASE_KEY(GHOST_kKeyRightShift, "RightShift");
CASE_KEY(GHOST_kKeyLeftControl, "LeftControl");
CASE_KEY(GHOST_kKeyRightControl, "RightControl");
CASE_KEY(GHOST_kKeyLeftAlt, "LeftAlt");
CASE_KEY(GHOST_kKeyRightAlt, "RightAlt");
CASE_KEY(GHOST_kKeyLeftOS, "LeftOS");
CASE_KEY(GHOST_kKeyRightOS, "RightOS");
CASE_KEY(GHOST_kKeyLeftHyper, "LeftHyper");
CASE_KEY(GHOST_kKeyRightHyper, "RightHyper");
CASE_KEY(GHOST_kKeyApp, "App");
CASE_KEY(GHOST_kKeyGrLess, "GrLess");
CASE_KEY(GHOST_kKeyCapsLock, "CapsLock");
CASE_KEY(GHOST_kKeyNumLock, "NumLock");
CASE_KEY(GHOST_kKeyScrollLock, "ScrollLock");
CASE_KEY(GHOST_kKeyLeftArrow, "LeftArrow");
CASE_KEY(GHOST_kKeyRightArrow, "RightArrow");
CASE_KEY(GHOST_kKeyUpArrow, "UpArrow");
CASE_KEY(GHOST_kKeyDownArrow, "DownArrow");
CASE_KEY(GHOST_kKeyPrintScreen, "PrintScreen");
CASE_KEY(GHOST_kKeyPause, "Pause");
CASE_KEY(GHOST_kKeyInsert, "Insert");
CASE_KEY(GHOST_kKeyDelete, "Delete");
CASE_KEY(GHOST_kKeyHome, "Home");
CASE_KEY(GHOST_kKeyEnd, "End");
CASE_KEY(GHOST_kKeyUpPage, "UpPage");
CASE_KEY(GHOST_kKeyDownPage, "DownPage");
CASE_KEY(GHOST_kKeyNumpadPeriod, "NumpadPeriod");
CASE_KEY(GHOST_kKeyNumpadEnter, "NumpadEnter");
CASE_KEY(GHOST_kKeyNumpadPlus, "NumpadPlus");
CASE_KEY(GHOST_kKeyNumpadMinus, "NumpadMinus");
CASE_KEY(GHOST_kKeyNumpadAsterisk, "NumpadAsterisk");
CASE_KEY(GHOST_kKeyNumpadSlash, "NumpadSlash");
CASE_KEY(GHOST_kKeyMediaPlay, "MediaPlayPause");
CASE_KEY(GHOST_kKeyMediaStop, "MediaStop");
CASE_KEY(GHOST_kKeyMediaFirst, "MediaFirst");
CASE_KEY(GHOST_kKeyMediaLast, "MediaLast");
CASE_KEY(GHOST_kKeyNumpad0, "Numpad 0");
CASE_KEY(GHOST_kKeyNumpad1, "Numpad 1");
CASE_KEY(GHOST_kKeyNumpad2, "Numpad 2");
CASE_KEY(GHOST_kKeyNumpad3, "Numpad 3");
CASE_KEY(GHOST_kKeyNumpad4, "Numpad 4");
CASE_KEY(GHOST_kKeyNumpad5, "Numpad 5");
CASE_KEY(GHOST_kKeyNumpad6, "Numpad 6");
CASE_KEY(GHOST_kKeyNumpad7, "Numpad 7");
CASE_KEY(GHOST_kKeyNumpad8, "Numpad 8");
CASE_KEY(GHOST_kKeyNumpad9, "Numpad 9");
CASE_KEY(GHOST_kKeyF1, "F1");
CASE_KEY(GHOST_kKeyF2, "F2");
CASE_KEY(GHOST_kKeyF3, "F3");
CASE_KEY(GHOST_kKeyF4, "F4");
CASE_KEY(GHOST_kKeyF5, "F5");
CASE_KEY(GHOST_kKeyF6, "F6");
CASE_KEY(GHOST_kKeyF7, "F7");
CASE_KEY(GHOST_kKeyF8, "F8");
CASE_KEY(GHOST_kKeyF9, "F9");
CASE_KEY(GHOST_kKeyF10, "F10");
CASE_KEY(GHOST_kKeyF11, "F11");
CASE_KEY(GHOST_kKeyF12, "F12");
CASE_KEY(GHOST_kKeyF13, "F13");
CASE_KEY(GHOST_kKeyF14, "F14");
CASE_KEY(GHOST_kKeyF15, "F15");
CASE_KEY(GHOST_kKeyF16, "F16");
CASE_KEY(GHOST_kKeyF17, "F17");
CASE_KEY(GHOST_kKeyF18, "F18");
CASE_KEY(GHOST_kKeyF19, "F19");
CASE_KEY(GHOST_kKeyF20, "F20");
CASE_KEY(GHOST_kKeyF21, "F21");
CASE_KEY(GHOST_kKeyF22, "F22");
CASE_KEY(GHOST_kKeyF23, "F23");
CASE_KEY(GHOST_kKeyF24, "F24");
CASE_KEY(GHOST_kKeyUnknown, "Unknown");
CASE_KEY(GHOST_kKeyComma, ",");
CASE_KEY(GHOST_kKeyMinus, "-");
CASE_KEY(GHOST_kKeyPlus, "=");
CASE_KEY(GHOST_kKeyPeriod, ".");
CASE_KEY(GHOST_kKeySlash, "/");
CASE_KEY(GHOST_kKey0, "0");
CASE_KEY(GHOST_kKey1, "1");
CASE_KEY(GHOST_kKey2, "2");
CASE_KEY(GHOST_kKey3, "3");
CASE_KEY(GHOST_kKey4, "4");
CASE_KEY(GHOST_kKey5, "5");
CASE_KEY(GHOST_kKey6, "6");
CASE_KEY(GHOST_kKey7, "7");
CASE_KEY(GHOST_kKey8, "8");
CASE_KEY(GHOST_kKey9, "9");
CASE_KEY(GHOST_kKeySemicolon, ";");
CASE_KEY(GHOST_kKeyEqual, "=");
CASE_KEY(GHOST_kKeyA, "A");
CASE_KEY(GHOST_kKeyB, "B");
CASE_KEY(GHOST_kKeyC, "C");
CASE_KEY(GHOST_kKeyD, "D");
CASE_KEY(GHOST_kKeyE, "E");
CASE_KEY(GHOST_kKeyF, "F");
CASE_KEY(GHOST_kKeyG, "G");
CASE_KEY(GHOST_kKeyH, "H");
CASE_KEY(GHOST_kKeyI, "I");
CASE_KEY(GHOST_kKeyJ, "J");
CASE_KEY(GHOST_kKeyK, "K");
CASE_KEY(GHOST_kKeyL, "L");
CASE_KEY(GHOST_kKeyM, "M");
CASE_KEY(GHOST_kKeyN, "N");
CASE_KEY(GHOST_kKeyO, "O");
CASE_KEY(GHOST_kKeyP, "P");
CASE_KEY(GHOST_kKeyQ, "Q");
CASE_KEY(GHOST_kKeyR, "R");
CASE_KEY(GHOST_kKeyS, "S");
CASE_KEY(GHOST_kKeyT, "T");
CASE_KEY(GHOST_kKeyU, "U");
CASE_KEY(GHOST_kKeyV, "V");
CASE_KEY(GHOST_kKeyW, "W");
CASE_KEY(GHOST_kKeyX, "X");
CASE_KEY(GHOST_kKeyY, "Y");
CASE_KEY(GHOST_kKeyZ, "Z");
CASE_KEY(GHOST_kKeyLeftBracket, "[");
CASE_KEY(GHOST_kKeyRightBracket, "]");
}
#undef CASE_KEY
/* Shouldn't happen (the value is not known to #GHOST_TKey). */
if (tstr == nullptr) {
tstr = "Invalid";
}
return tstr;
}