aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn1
-rw-r--r--DEPS3
-rw-r--r--third_party/imgui/BUILD.gn19
-rw-r--r--tools/viewer/Viewer.cpp212
-rw-r--r--tools/viewer/Viewer.h7
-rw-r--r--tools/viewer/sk_app/CommandSet.cpp13
-rw-r--r--tools/viewer/sk_app/CommandSet.h8
-rw-r--r--tools/viewer/sk_app/Window.cpp9
-rw-r--r--tools/viewer/sk_app/Window.h25
-rw-r--r--tools/viewer/sk_app/mac/Window_mac.cpp52
-rw-r--r--tools/viewer/sk_app/mac/main_mac.cpp2
-rw-r--r--tools/viewer/sk_app/unix/Window_unix.cpp64
-rw-r--r--tools/viewer/sk_app/win/Window_win.cpp55
13 files changed, 400 insertions, 70 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 1f95d60182..ffc5713bc3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1429,6 +1429,7 @@ if (skia_enable_tools) {
":skia",
":tool_utils",
":views",
+ "//third_party/imgui",
"//third_party/jsoncpp",
]
if (is_android) {
diff --git a/DEPS b/DEPS
index 61e441dfca..2ed02355b7 100644
--- a/DEPS
+++ b/DEPS
@@ -41,6 +41,9 @@ deps = {
# microhttpd for skiaserve
"third_party/externals/microhttpd" : "https://android.googlesource.com/platform/external/libmicrohttpd@748945ec6f1c67b7efc934ab0808e1d32f2fb98d",
+
+ # imgui for Viewer/SampleApp widgets
+ "third_party/externals/imgui" : "https://github.com/ocornut/imgui.git@6384eee34f08cb7eab8d835043e1738e4adcdf75",
}
recursedeps = [ "common" ]
diff --git a/third_party/imgui/BUILD.gn b/third_party/imgui/BUILD.gn
new file mode 100644
index 0000000000..5e3769ccbd
--- /dev/null
+++ b/third_party/imgui/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2016 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+}
+
+import("../third_party.gni")
+
+third_party("imgui") {
+ public_include_dirs = [ "../externals/imgui" ]
+
+ sources = [
+ "../externals/imgui/imgui.cpp",
+ "../externals/imgui/imgui_demo.cpp",
+ "../externals/imgui/imgui_draw.cpp",
+ ]
+}
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 384e9c6a5b..85b6e7da9c 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -25,8 +25,11 @@
#include "SkRandom.h"
#include "SkStream.h"
#include "SkSurface.h"
+#include "SkSwizzle.h"
#include "SkTime.h"
+#include "imgui.h"
+
using namespace sk_app;
Application* Application::Create(int argc, char** argv, void* platformData) {
@@ -52,6 +55,51 @@ static void on_ui_state_changed_handler(const SkString& stateName, const SkStrin
return viewer->onUIStateChanged(stateName, stateValue);
}
+static bool on_mouse_handler(int x, int y, Window::InputState state, uint32_t modifiers,
+ void* userData) {
+ ImGuiIO& io = ImGui::GetIO();
+ io.MousePos.x = static_cast<float>(x);
+ io.MousePos.y = static_cast<float>(y);
+ if (Window::kDown_InputState == state) {
+ io.MouseDown[0] = true;
+ } else if (Window::kUp_InputState == state) {
+ io.MouseDown[0] = false;
+ }
+ return true;
+}
+
+static bool on_mouse_wheel_handler(float delta, uint32_t modifiers, void* userData) {
+ ImGuiIO& io = ImGui::GetIO();
+ io.MouseWheel += delta;
+ return true;
+}
+
+static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers,
+ void* userData) {
+ ImGuiIO& io = ImGui::GetIO();
+ io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state);
+
+ if (io.WantCaptureKeyboard) {
+ return true;
+ } else {
+ Viewer* viewer = reinterpret_cast<Viewer*>(userData);
+ return viewer->onKey(key, state, modifiers);
+ }
+}
+
+static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) {
+ ImGuiIO& io = ImGui::GetIO();
+ if (io.WantTextInput) {
+ if (c > 0 && c < 0x10000) {
+ io.AddInputCharacter(c);
+ }
+ return true;
+ } else {
+ Viewer* viewer = reinterpret_cast<Viewer*>(userData);
+ return viewer->onChar(c, modifiers);
+ }
+}
+
static DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
static DEFINE_string2(match, m, nullptr,
@@ -122,6 +170,8 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
: fCurrentMeasurement(0)
, fDisplayStats(false)
, fRefresh(false)
+ , fShowImGuiDebugWindow(false)
+ , fShowImGuiTestWindow(false)
, fBackendType(sk_app::Window::kNativeGL_BackendType)
, fColorType(kN32_SkColorType)
, fColorSpace(nullptr)
@@ -159,8 +209,20 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fWindow->registerPaintFunc(on_paint_handler, this);
fWindow->registerTouchFunc(on_touch_handler, this);
fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
+ fWindow->registerMouseFunc(on_mouse_handler, this);
+ fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
+ fWindow->registerKeyFunc(on_key_handler, this);
+ fWindow->registerCharFunc(on_char_handler, this);
// add key-bindings
+ fCommands.addCommand(' ', "GUI", "Toggle Debug GUI", [this]() {
+ this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow;
+ fWindow->inval();
+ });
+ fCommands.addCommand('g', "GUI", "Toggle GUI Demo", [this]() {
+ this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
+ fWindow->inval();
+ });
fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() {
this->fDisplayStats = !this->fDisplayStats;
fWindow->inval();
@@ -234,6 +296,10 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fWindow->registerPaintFunc(on_paint_handler, this);
fWindow->registerTouchFunc(on_touch_handler, this);
fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
+ fWindow->registerMouseFunc(on_mouse_handler, this);
+ fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
+ fWindow->registerKeyFunc(on_key_handler, this);
+ fWindow->registerCharFunc(on_char_handler, this);
}
#endif
fWindow->attach(fBackendType, DisplayParams());
@@ -252,6 +318,39 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
fCurrentSlide = 0;
setupCurrentSlide(-1);
+ // ImGui initialization:
+ ImGuiIO& io = ImGui::GetIO();
+ io.DisplaySize.x = static_cast<float>(fWindow->width());
+ io.DisplaySize.y = static_cast<float>(fWindow->height());
+
+ // Keymap...
+ io.KeyMap[ImGuiKey_Tab] = (int)Window::Key::kTab;
+ io.KeyMap[ImGuiKey_LeftArrow] = (int)Window::Key::kLeft;
+ io.KeyMap[ImGuiKey_RightArrow] = (int)Window::Key::kRight;
+ io.KeyMap[ImGuiKey_UpArrow] = (int)Window::Key::kUp;
+ io.KeyMap[ImGuiKey_DownArrow] = (int)Window::Key::kDown;
+ io.KeyMap[ImGuiKey_PageUp] = (int)Window::Key::kPageUp;
+ io.KeyMap[ImGuiKey_PageDown] = (int)Window::Key::kPageDown;
+ io.KeyMap[ImGuiKey_Home] = (int)Window::Key::kHome;
+ io.KeyMap[ImGuiKey_End] = (int)Window::Key::kEnd;
+ io.KeyMap[ImGuiKey_Delete] = (int)Window::Key::kDelete;
+ io.KeyMap[ImGuiKey_Backspace] = (int)Window::Key::kBack;
+ io.KeyMap[ImGuiKey_Enter] = (int)Window::Key::kOK;
+ io.KeyMap[ImGuiKey_Escape] = (int)Window::Key::kEscape;
+ io.KeyMap[ImGuiKey_A] = (int)Window::Key::kA;
+ io.KeyMap[ImGuiKey_C] = (int)Window::Key::kC;
+ io.KeyMap[ImGuiKey_V] = (int)Window::Key::kV;
+ io.KeyMap[ImGuiKey_X] = (int)Window::Key::kX;
+ io.KeyMap[ImGuiKey_Y] = (int)Window::Key::kY;
+ io.KeyMap[ImGuiKey_Z] = (int)Window::Key::kZ;
+
+ int w, h;
+ unsigned char* pixels;
+ io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
+ SkImageInfo info = SkImageInfo::MakeA8(w, h);
+ SkPixmap pmap(info, pixels, info.minRowBytes());
+ fImGuiFontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
+
fWindow->show();
}
@@ -498,6 +597,18 @@ void Viewer::drawSlide(SkCanvas* canvas) {
}
void Viewer::onPaint(SkCanvas* canvas) {
+ // Update ImGui input
+ ImGuiIO& io = ImGui::GetIO();
+ io.DeltaTime = 1.0f / 60.0f;
+ io.DisplaySize.x = static_cast<float>(fWindow->width());
+ io.DisplaySize.y = static_cast<float>(fWindow->height());
+
+ io.KeyAlt = io.KeysDown[static_cast<int>(Window::Key::kOption)];
+ io.KeyCtrl = io.KeysDown[static_cast<int>(Window::Key::kCtrl)];
+ io.KeyShift = io.KeysDown[static_cast<int>(Window::Key::kShift)];
+
+ ImGui::NewFrame();
+
drawSlide(canvas);
// Advance our timing bookkeeping
@@ -510,6 +621,8 @@ void Viewer::onPaint(SkCanvas* canvas) {
}
fCommands.drawHelp(canvas);
+ drawImGui(canvas);
+
// Update the FPS
updateUIState();
}
@@ -598,13 +711,102 @@ void Viewer::drawStats(SkCanvas* canvas) {
canvas->restore();
}
+void Viewer::drawImGui(SkCanvas* canvas) {
+ // Support drawing the ImGui demo window. Superfluous, but gives a good idea of what's possible
+ if (fShowImGuiTestWindow) {
+ ImGui::ShowTestWindow(&fShowImGuiTestWindow);
+ }
+
+ if (fShowImGuiDebugWindow) {
+ if (ImGui::Begin("Debug", &fShowImGuiDebugWindow)) {
+ if (ImGui::CollapsingHeader("Slide")) {
+ static ImGuiTextFilter filter;
+ filter.Draw();
+ int previousSlide = fCurrentSlide;
+ fCurrentSlide = 0;
+ for (auto slide : fSlides) {
+ if (filter.PassFilter(slide->getName().c_str())) {
+ ImGui::BulletText("%s", slide->getName().c_str());
+ if (ImGui::IsItemClicked()) {
+ setupCurrentSlide(previousSlide);
+ break;
+ }
+ }
+ ++fCurrentSlide;
+ }
+ if (fCurrentSlide >= fSlides.count()) {
+ fCurrentSlide = previousSlide;
+ }
+ }
+ }
+
+ ImGui::End();
+ }
+
+ // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
+ // (widgets, etc...) that have been issued
+ ImGui::Render();
+
+ // Then we fetch the most recent data, and convert it so we can render with Skia
+ const ImDrawData* drawData = ImGui::GetDrawData();
+ SkTDArray<SkPoint> pos;
+ SkTDArray<SkPoint> uv;
+ SkTDArray<SkColor> color;
+ SkPaint imguiPaint;
+ imguiPaint.setColor(SK_ColorWHITE);
+ SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / fImGuiFontImage->width(),
+ 1.0f / fImGuiFontImage->height());
+ imguiPaint.setShader(fImGuiFontImage->makeShader(SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode,
+ &localMatrix));
+ imguiPaint.setFilterQuality(kLow_SkFilterQuality);
+
+ for (int i = 0; i < drawData->CmdListsCount; ++i) {
+ const ImDrawList* drawList = drawData->CmdLists[i];
+
+ // De-interleave all vertex data (sigh), convert to Skia types
+ pos.rewind(); uv.rewind(); color.rewind();
+ for (int i = 0; i < drawList->VtxBuffer.size(); ++i) {
+ const ImDrawVert& vert = drawList->VtxBuffer[i];
+ pos.push(SkPoint::Make(vert.pos.x, vert.pos.y));
+ uv.push(SkPoint::Make(vert.uv.x, vert.uv.y));
+ color.push(vert.col);
+ }
+ // ImGui colors are RGBA
+ SkSwapRB(color.begin(), color.begin(), color.count());
+
+ int indexOffset = 0;
+
+ // Draw everything with canvas.drawVertices...
+ for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
+ const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];
+
+ // TODO: Find min/max index for each draw, so we know how many vertices (sigh)
+ if (drawCmd->UserCallback) {
+ drawCmd->UserCallback(drawList, drawCmd);
+ } else {
+ canvas->save();
+ canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
+ drawCmd->ClipRect.z, drawCmd->ClipRect.w));
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, drawList->VtxBuffer.size(),
+ pos.begin(), uv.begin(), color.begin(),
+ drawList->IdxBuffer.begin() + indexOffset, drawCmd->ElemCount,
+ imguiPaint);
+ indexOffset += drawCmd->ElemCount;
+ canvas->restore();
+ }
+ }
+ }
+}
+
void Viewer::onIdle() {
double startTime = SkTime::GetMSecs();
fAnimTimer.updateTime();
bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer);
fAnimateTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
- if (animateWantsInval || fDisplayStats || fRefresh) {
+ ImGuiIO& io = ImGui::GetIO();
+ if (animateWantsInval || fDisplayStats || fRefresh || io.MetricsActiveWindows) {
fWindow->inval();
}
}
@@ -706,3 +908,11 @@ void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateVa
SkDebugf("Unknown stateName: %s", stateName.c_str());
}
}
+
+bool Viewer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
+ return fCommands.onKey(key, state, modifiers);
+}
+
+bool Viewer::onChar(SkUnichar c, uint32_t modifiers) {
+ return fCommands.onChar(c, modifiers);
+}
diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h
index 7b08df5437..9499c6c979 100644
--- a/tools/viewer/Viewer.h
+++ b/tools/viewer/Viewer.h
@@ -27,6 +27,8 @@ public:
void onIdle() override;
bool onTouch(intptr_t owner, sk_app::Window::InputState state, float x, float y);
void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
+ bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers);
+ bool onChar(SkUnichar c, uint32_t modifiers);
private:
void initSlides();
@@ -38,6 +40,7 @@ private:
void drawSlide(SkCanvas* canvs);
void drawStats(SkCanvas* canvas);
+ void drawImGui(SkCanvas* canvas);
void changeZoomLevel(float delta);
SkMatrix computeMatrix();
@@ -57,6 +60,10 @@ private:
bool fDisplayStats;
bool fRefresh; // whether to continuously refresh for measuring render time
+ sk_sp<SkImage> fImGuiFontImage;
+ bool fShowImGuiDebugWindow;
+ bool fShowImGuiTestWindow;
+
sk_app::Window::BackendType fBackendType;
// Color properties for slide rendering
diff --git a/tools/viewer/sk_app/CommandSet.cpp b/tools/viewer/sk_app/CommandSet.cpp
index 4805e6aafe..f6568ec342 100644
--- a/tools/viewer/sk_app/CommandSet.cpp
+++ b/tools/viewer/sk_app/CommandSet.cpp
@@ -12,17 +12,6 @@
namespace sk_app {
-static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers,
- void* userData) {
- CommandSet* cs = reinterpret_cast<CommandSet*>(userData);
- return cs->onKey(key, state, modifiers);
-}
-
-static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) {
- CommandSet* cs = reinterpret_cast<CommandSet*>(userData);
- return cs->onChar(c, modifiers);
-}
-
CommandSet::CommandSet()
: fHelpMode(kNone_HelpMode) {
this->addCommand('h', "Overlays", "Show help screen", [this]() {
@@ -43,8 +32,6 @@ CommandSet::CommandSet()
void CommandSet::attach(Window* window) {
fWindow = window;
- window->registerKeyFunc(on_key_handler, this);
- window->registerCharFunc(on_char_handler, this);
}
bool CommandSet::onKey(Window::Key key, Window::InputState state, uint32_t modifiers) {
diff --git a/tools/viewer/sk_app/CommandSet.h b/tools/viewer/sk_app/CommandSet.h
index 4cbb367e01..0784a3875e 100644
--- a/tools/viewer/sk_app/CommandSet.h
+++ b/tools/viewer/sk_app/CommandSet.h
@@ -22,13 +22,15 @@ namespace sk_app {
* Helper class used by applications that want to hook keypresses to trigger events.
*
* An app can simply store an instance of CommandSet and then use it as follows:
- * 1) Attach to the Window at initialization time. This registers key handlers on the window.
+ * 1) Attach to the Window at initialization time.
* 2) Register commands to be executed for characters or keys. Each command needs a Group and a
* description (both just strings). Commands attached to Keys (rather than characters) also need
* a displayable name for the Key. Finally, a function to execute when the key or character is
* pressed must be supplied. The easiest option to is pass in a lambda that captures [this]
* (your application object), and performs whatever action is desired.
- * 3) At the end of your onPaint, call drawHelp, and pass in the application's canvas.
+ * 3) Register key and char handlers with the Window, and - depending on your state - forward those
+ * events to the CommandSet's onKey, onChar, and onSoftKey.
+ * 4) At the end of your onPaint, call drawHelp, and pass in the application's canvas.
* The CommandSet always binds 'h' to cycle through two different help screens. The first shows
* all commands, organized by Group (with headings for each Group). The second shows all commands
@@ -63,7 +65,7 @@ private:
std::function<void(void)> function)
: fType(kChar_CommandType)
, fChar(c)
- , fKeyName(SkStringPrintf("%c", c))
+ , fKeyName(' ' == c ? SkString("Space") : SkStringPrintf("%c", c))
, fGroup(group)
, fDescription(description)
, fFunction(function) {}
diff --git a/tools/viewer/sk_app/Window.cpp b/tools/viewer/sk_app/Window.cpp
index dec15840a1..9d14a174ff 100644
--- a/tools/viewer/sk_app/Window.cpp
+++ b/tools/viewer/sk_app/Window.cpp
@@ -27,6 +27,10 @@ static bool default_mouse_func(int x, int y, Window::InputState state, uint32_t
return false;
}
+static bool default_mouse_wheel_func(float delta, uint32_t modifiers, void* userData) {
+ return false;
+}
+
static bool default_touch_func(intptr_t owner, Window::InputState state, float x, float y,
void* userData) {
return false;
@@ -40,6 +44,7 @@ static void default_paint_func(SkCanvas*, void* userData) {}
Window::Window() : fCharFunc(default_char_func)
, fKeyFunc(default_key_func)
, fMouseFunc(default_mouse_func)
+ , fMouseWheelFunc(default_mouse_wheel_func)
, fTouchFunc(default_touch_func)
, fUIStateChangedFunc(default_ui_state_changed_func)
, fPaintFunc(default_paint_func) {
@@ -62,6 +67,10 @@ bool Window::onMouse(int x, int y, InputState state, uint32_t modifiers) {
return fMouseFunc(x, y, state, modifiers, fMouseUserData);
}
+bool Window::onMouseWheel(float delta, uint32_t modifiers) {
+ return fMouseWheelFunc(delta, modifiers, fMouseWheelUserData);
+}
+
bool Window::onTouch(intptr_t owner, InputState state, float x, float y) {
return fTouchFunc(owner, state, x, y, fTouchUserData);
}
diff --git a/tools/viewer/sk_app/Window.h b/tools/viewer/sk_app/Window.h
index ea6f6c14ea..b20eec8860 100644
--- a/tools/viewer/sk_app/Window.h
+++ b/tools/viewer/sk_app/Window.h
@@ -86,6 +86,22 @@ public:
kLeft,
kRight,
+ // Keys needed by ImGui
+ kTab,
+ kPageUp,
+ kPageDown,
+ kDelete,
+ kEscape,
+ kShift,
+ kCtrl,
+ kOption, // AKA Alt
+ kA,
+ kC,
+ kV,
+ kX,
+ kY,
+ kZ,
+
kOK, //!< the center key
kVolUp, //!< volume up - match android
@@ -115,6 +131,7 @@ public:
typedef bool(*OnCharFunc)(SkUnichar c, uint32_t modifiers, void* userData);
typedef bool(*OnKeyFunc)(Key key, InputState state, uint32_t modifiers, void* userData);
typedef bool(*OnMouseFunc)(int x, int y, InputState state, uint32_t modifiers, void* userData);
+ typedef bool(*OnMouseWheelFunc)(float delta, uint32_t modifiers, void* userData);
typedef bool(*OnTouchFunc)(intptr_t owner, InputState state, float x, float y, void* userData);
typedef void(*OnUIStateChangedFunc)(
const SkString& stateName, const SkString& stateValue, void* userData);
@@ -135,6 +152,11 @@ public:
fMouseUserData = userData;
}
+ void registerMouseWheelFunc(OnMouseWheelFunc func, void* userData) {
+ fMouseWheelFunc = func;
+ fMouseWheelUserData = userData;
+ }
+
void registerPaintFunc(OnPaintFunc func, void* userData) {
fPaintFunc = func;
fPaintUserData = userData;
@@ -153,6 +175,7 @@ public:
bool onChar(SkUnichar c, uint32_t modifiers);
bool onKey(Key key, InputState state, uint32_t modifiers);
bool onMouse(int x, int y, InputState state, uint32_t modifiers);
+ bool onMouseWheel(float delta, uint32_t modifiers);
bool onTouch(intptr_t owner, InputState state, float x, float y); // multi-owner = multi-touch
void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
void onPaint();
@@ -176,6 +199,8 @@ protected:
void* fKeyUserData;
OnMouseFunc fMouseFunc;
void* fMouseUserData;
+ OnMouseWheelFunc fMouseWheelFunc;
+ void* fMouseWheelUserData;
OnTouchFunc fTouchFunc;
void* fTouchUserData;
OnUIStateChangedFunc
diff --git a/tools/viewer/sk_app/mac/Window_mac.cpp b/tools/viewer/sk_app/mac/Window_mac.cpp
index 8e707a49c3..a23316dc80 100644
--- a/tools/viewer/sk_app/mac/Window_mac.cpp
+++ b/tools/viewer/sk_app/mac/Window_mac.cpp
@@ -92,7 +92,26 @@ static Window::Key get_key(const SDL_Keysym& keysym) {
{ SDLK_UP, Window::Key::kUp },
{ SDLK_DOWN, Window::Key::kDown },
{ SDLK_LEFT, Window::Key::kLeft },
- { SDLK_RIGHT, Window::Key::kRight }
+ { SDLK_RIGHT, Window::Key::kRight },
+ { SDLK_TAB, Window::Key::kTab },
+ { SDLK_PAGEUP, Window::Key::kPageUp },
+ { SDLK_PAGEDOWN, Window::Key::kPageDown },
+ { SDLK_HOME, Window::Key::kHome },
+ { SDLK_END, Window::Key::kEnd },
+ { SDLK_DELETE, Window::Key::kDelete },
+ { SDLK_ESCAPE, Window::Key::kEscape },
+ { SDLK_LSHIFT, Window::Key::kShift },
+ { SDLK_RSHIFT, Window::Key::kShift },
+ { SDLK_LCTRL, Window::Key::kCtrl },
+ { SDLK_RCTRL, Window::Key::kCtrl },
+ { SDLK_LALT, Window::Key::kOption },
+ { SDLK_LALT, Window::Key::kOption },
+ { 'A', Window::Key::kA },
+ { 'C', Window::Key::kC },
+ { 'V', Window::Key::kV },
+ { 'X', Window::Key::kX },
+ { 'Y', Window::Key::kY },
+ { 'Z', Window::Key::kZ },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
if (gPair[i].fSDLK == keysym.sym) {
@@ -176,24 +195,22 @@ bool Window_mac::handleEvent(const SDL_Event& event) {
break;
case SDL_MOUSEMOTION:
- // only track if left button is down
- if (event.motion.state & SDL_BUTTON_LMASK) {
- this->onMouse(event.motion.x, event.motion.y,
- Window::kMove_InputState, get_modifiers(event));
- }
+ this->onMouse(event.motion.x, event.motion.y,
+ Window::kMove_InputState, get_modifiers(event));
+ break;
+
+ case SDL_MOUSEWHEEL:
+ this->onMouseWheel(event.wheel.y, get_modifiers(event));
break;
case SDL_KEYDOWN: {
- if (event.key.keysym.sym == SDLK_ESCAPE) {
- return true;
- }
Window::Key key = get_key(event.key.keysym);
if (key != Window::Key::kNONE) {
- (void) this->onKey(key, Window::kDown_InputState,
- get_modifiers(event));
- } else {
- (void) this->onChar((SkUnichar) event.key.keysym.sym,
- get_modifiers(event));
+ if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) {
+ if (event.key.keysym.sym == SDLK_ESCAPE) {
+ return true;
+ }
+ }
}
} break;
@@ -205,6 +222,13 @@ bool Window_mac::handleEvent(const SDL_Event& event) {
}
} break;
+ case SDL_TEXTINPUT: {
+ const char* textIter = &event.text.text[0];
+ while (SkUnichar c = SkUTF8_NextUnichar(&textIter)) {
+ (void) this->onChar(c, get_modifiers(event));
+ }
+ } break;
+
default:
break;
}
diff --git a/tools/viewer/sk_app/mac/main_mac.cpp b/tools/viewer/sk_app/mac/main_mac.cpp
index c7040b5adb..b30a7ea781 100644
--- a/tools/viewer/sk_app/mac/main_mac.cpp
+++ b/tools/viewer/sk_app/mac/main_mac.cpp
@@ -32,8 +32,10 @@ int main(int argc, char* argv[]) {
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
+ case SDL_MOUSEWHEEL:
case SDL_KEYDOWN:
case SDL_KEYUP:
+ case SDL_TEXTINPUT:
done = sk_app::Window_mac::HandleWindowEvent(event);
break;
diff --git a/tools/viewer/sk_app/unix/Window_unix.cpp b/tools/viewer/sk_app/unix/Window_unix.cpp
index d22502bc91..2481bdbca6 100644
--- a/tools/viewer/sk_app/unix/Window_unix.cpp
+++ b/tools/viewer/sk_app/unix/Window_unix.cpp
@@ -155,7 +155,26 @@ static Window::Key get_key(KeySym keysym) {
{ XK_Up, Window::Key::kUp },
{ XK_Down, Window::Key::kDown },
{ XK_Left, Window::Key::kLeft },
- { XK_Right, Window::Key::kRight }
+ { XK_Right, Window::Key::kRight },
+ { XK_Tab, Window::Key::kTab },
+ { XK_Page_Up, Window::Key::kPageUp },
+ { XK_Page_Down, Window::Key::kPageDown },
+ { XK_Home, Window::Key::kHome },
+ { XK_End, Window::Key::kEnd },
+ { XK_Delete, Window::Key::kDelete },
+ { XK_Escape, Window::Key::kEscape },
+ { XK_Shift_L, Window::Key::kShift },
+ { XK_Shift_R, Window::Key::kShift },
+ { XK_Control_L, Window::Key::kCtrl },
+ { XK_Control_R, Window::Key::kCtrl },
+ { XK_Alt_L, Window::Key::kOption },
+ { XK_Alt_R, Window::Key::kOption },
+ { 'A', Window::Key::kA },
+ { 'C', Window::Key::kC },
+ { 'V', Window::Key::kV },
+ { 'X', Window::Key::kX },
+ { 'Y', Window::Key::kY },
+ { 'Z', Window::Key::kZ },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
if (gPair[i].fXK == keysym) {
@@ -200,9 +219,17 @@ bool Window_unix::handleEvent(const XEvent& event) {
break;
case ButtonPress:
- if (event.xbutton.button == Button1) {
- this->onMouse(event.xbutton.x, event.xbutton.y,
- Window::kDown_InputState, get_modifiers(event));
+ switch (event.xbutton.button) {
+ case Button1:
+ this->onMouse(event.xbutton.x, event.xbutton.y,
+ Window::kDown_InputState, get_modifiers(event));
+ break;
+ case Button4:
+ this->onMouseWheel(1.0f, get_modifiers(event));
+ break;
+ case Button5:
+ this->onMouseWheel(-1.0f, get_modifiers(event));
+ break;
}
break;
@@ -214,31 +241,26 @@ bool Window_unix::handleEvent(const XEvent& event) {
break;
case MotionNotify:
- // only track if left button is down
- if (event.xmotion.state & Button1Mask) {
- this->onMouse(event.xmotion.x, event.xmotion.y,
- Window::kMove_InputState, get_modifiers(event));
- }
+ this->onMouse(event.xmotion.x, event.xmotion.y,
+ Window::kMove_InputState, get_modifiers(event));
break;
case KeyPress: {
int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0;
- KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode,
- 0, shiftLevel);
- if (keysym == XK_Escape) {
- return true;
- }
+ KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, 0, shiftLevel);
Window::Key key = get_key(keysym);
if (key != Window::Key::kNONE) {
- (void) this->onKey(key, Window::kDown_InputState,
- get_modifiers(event));
- } else {
- long uni = keysym2ucs(keysym);
- if (uni != -1) {
- (void) this->onChar((SkUnichar) uni,
- get_modifiers(event));
+ if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) {
+ if (keysym == XK_Escape) {
+ return true;
+ }
}
}
+
+ long uni = keysym2ucs(keysym);
+ if (uni != -1) {
+ (void) this->onChar((SkUnichar) uni, get_modifiers(event));
+ }
} break;
case KeyRelease: {
diff --git a/tools/viewer/sk_app/win/Window_win.cpp b/tools/viewer/sk_app/win/Window_win.cpp
index f7cb547f2a..6f6e72d590 100644
--- a/tools/viewer/sk_app/win/Window_win.cpp
+++ b/tools/viewer/sk_app/win/Window_win.cpp
@@ -107,7 +107,23 @@ static Window::Key get_key(WPARAM vk) {
{ VK_UP, Window::Key::kUp },
{ VK_DOWN, Window::Key::kDown },
{ VK_LEFT, Window::Key::kLeft },
- { VK_RIGHT, Window::Key::kRight }
+ { VK_RIGHT, Window::Key::kRight },
+ { VK_TAB, Window::Key::kTab },
+ { VK_PRIOR, Window::Key::kPageUp },
+ { VK_NEXT, Window::Key::kPageDown },
+ { VK_HOME, Window::Key::kHome },
+ { VK_END, Window::Key::kEnd },
+ { VK_DELETE, Window::Key::kDelete },
+ { VK_ESCAPE, Window::Key::kEscape },
+ { VK_SHIFT, Window::Key::kShift },
+ { VK_CONTROL, Window::Key::kCtrl },
+ { VK_MENU, Window::Key::kOption },
+ { 'A', Window::Key::kA },
+ { 'C', Window::Key::kC },
+ { 'V', Window::Key::kV },
+ { 'X', Window::Key::kX },
+ { 'Y', Window::Key::kY },
+ { 'Z', Window::Key::kZ },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
if (gPair[i].fVK == vk) {
@@ -151,6 +167,7 @@ static uint32_t get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
+ case WM_MOUSEWHEEL:
if (wParam & MK_CONTROL) {
modifiers |= Window::kControl_ModifierKey;
}
@@ -236,23 +253,25 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
get_modifiers(message, wParam, lParam));
} break;
- case WM_MOUSEMOVE:
- // only track if left button is down
- if ((wParam & MK_LBUTTON) != 0) {
- int xPos = GET_X_LPARAM(lParam);
- int yPos = GET_Y_LPARAM(lParam);
-
- //if (!gIsFullscreen)
- //{
- // RECT rc = { 0, 0, 640, 480 };
- // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
- // xPos -= rc.left;
- // yPos -= rc.top;
- //}
-
- eventHandled = window->onMouse(xPos, yPos, Window::kMove_InputState,
- get_modifiers(message, wParam, lParam));
- }
+ case WM_MOUSEMOVE: {
+ int xPos = GET_X_LPARAM(lParam);
+ int yPos = GET_Y_LPARAM(lParam);
+
+ //if (!gIsFullscreen)
+ //{
+ // RECT rc = { 0, 0, 640, 480 };
+ // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
+ // xPos -= rc.left;
+ // yPos -= rc.top;
+ //}
+
+ eventHandled = window->onMouse(xPos, yPos, Window::kMove_InputState,
+ get_modifiers(message, wParam, lParam));
+ } break;
+
+ case WM_MOUSEWHEEL:
+ eventHandled = window->onMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f,
+ get_modifiers(message, wParam, lParam));
break;
default: