Horizontal mouse wheel support

This patch adds support for the horizontal mouse wheel in ImGui. It
affects windows that can be scrolled, as long as the Ctrl key is not
being pressed.

The scrolling speed has been set empirically so that it matches the
scrolling speed on the Firefox browser when the horizontal wheel is
used.

Internally, it adds a MouseHorizWheel to ImGuiIO, which is then used in
NewFrame to scroll the current window.

The SDL/GL2, SDL/GL3, GLFW/GL2 and GLFW/GL3 examples has been modified
to use it.
diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp
index 364d928..8aa6395 100644
--- a/examples/opengl2_example/imgui_impl_glfw.cpp
+++ b/examples/opengl2_example/imgui_impl_glfw.cpp
@@ -31,6 +31,7 @@
 static GLFWwindow*  g_Window = NULL;
 static double       g_Time = 0.0f;
 static bool         g_MouseJustPressed[3] = { false, false, false };
+static float        g_MouseHorizWheel = 0.0f;
 static float        g_MouseWheel = 0.0f;
 static GLuint       g_FontTexture = 0;
 
@@ -136,9 +137,10 @@
         g_MouseJustPressed[button] = true;
 }
 
-void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset)
+void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
 {
-    g_MouseWheel += (float)yoffset; // Use fractional mouse wheel.
+    g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel.
+    g_MouseWheel += (float)yoffset;
 }
 
 void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
@@ -296,8 +298,9 @@
         g_MouseJustPressed[i] = false;
     }
 
+    io.MouseHorizWheel = g_MouseHorizWheel;
     io.MouseWheel = g_MouseWheel;
-    g_MouseWheel = 0.0f;
+    g_MouseHorizWheel = g_MouseWheel = 0.0f;
 
     // Hide OS mouse cursor if ImGui is drawing it
     glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp
index 7d924fc..01accf0 100644
--- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp
+++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp
@@ -25,6 +25,7 @@
 static GLFWwindow*  g_Window = NULL;
 static double       g_Time = 0.0f;
 static bool         g_MouseJustPressed[3] = { false, false, false };
+static float        g_MouseHorizWheel = 0.0f;
 static float        g_MouseWheel = 0.0f;
 static GLuint       g_FontTexture = 0;
 static int          g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
@@ -155,9 +156,10 @@
         g_MouseJustPressed[button] = true;
 }
 
-void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset)
+void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double xoffset, double yoffset)
 {
-    g_MouseWheel += (float)yoffset; // Use fractional mouse wheel.
+    g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel.
+    g_MouseWheel += (float)yoffset;
 }
 
 void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods)
@@ -408,8 +410,9 @@
         g_MouseJustPressed[i] = false;
     }
 
+    io.MouseHorizWheel = g_MouseHorizWheel;
     io.MouseWheel = g_MouseWheel;
-    g_MouseWheel = 0.0f;
+    g_MouseHorizWheel = g_MouseWheel = 0.0f;
 
     // Hide OS mouse cursor if ImGui is drawing it
     glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp
index 66f3ed5..b0a2553 100644
--- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp
+++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp
@@ -24,6 +24,7 @@
 // Data
 static double       g_Time = 0.0f;
 static bool         g_MousePressed[3] = { false, false, false };
+static float        g_MouseHorizWheel = 0.0f;
 static float        g_MouseWheel = 0.0f;
 static GLuint       g_FontTexture = 0;
 
@@ -134,6 +135,10 @@
     {
     case SDL_MOUSEWHEEL:
         {
+            if (event->wheel.x > 0)
+                g_MouseHorizWheel = 1;
+            if (event->wheel.x < 0)
+                g_MouseHorizWheel = -1;
             if (event->wheel.y > 0)
                 g_MouseWheel = 1;
             if (event->wheel.y < 0)
@@ -285,8 +290,9 @@
     io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
     g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
 
+    io.MouseHorizWheel = g_MouseHorizWheel;
     io.MouseWheel = g_MouseWheel;
-    g_MouseWheel = 0.0f;
+    g_MouseWheel = g_MouseHorizWheel = 0.0f;
 
     // Hide OS mouse cursor if ImGui is drawing it
     SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1);
diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp
index 68e27a6..933669c 100644
--- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp
+++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp
@@ -19,6 +19,7 @@
 // Data
 static double       g_Time = 0.0f;
 static bool         g_MousePressed[3] = { false, false, false };
+static float        g_MouseHorizWheel = 0.0f;
 static float        g_MouseWheel = 0.0f;
 static GLuint       g_FontTexture = 0;
 static int          g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
@@ -154,6 +155,10 @@
     {
     case SDL_MOUSEWHEEL:
         {
+            if (event->wheel.x > 0)
+                g_MouseHorizWheel = 1;
+            if (event->wheel.x < 0)
+                g_MouseHorizWheel = -1;
             if (event->wheel.y > 0)
                 g_MouseWheel = 1;
             if (event->wheel.y < 0)
@@ -396,8 +401,9 @@
     io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
     g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
 
+    io.MouseHorizWheel = g_MouseHorizWheel;
     io.MouseWheel = g_MouseWheel;
-    g_MouseWheel = 0.0f;
+    g_MouseHorizWheel = g_MouseWheel = 0.0f;
 
     // Hide OS mouse cursor if ImGui is drawing it
     SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1);
diff --git a/imgui.cpp b/imgui.cpp
index 211bd29..f13cfb4 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -628,6 +628,7 @@
 static ImFont*          GetDefaultFont();
 static void             SetCurrentFont(ImFont* font);
 static void             SetCurrentWindow(ImGuiWindow* window);
+static void             SetWindowScrollX(ImGuiWindow* window, float new_scroll_x);
 static void             SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
 static void             SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);
 static void             SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);
@@ -2430,6 +2431,16 @@
         }
     }
 
+    // Horizontal wheel scrolling; for consistency, only allowed if Ctrl is not pressed.
+    if (g.HoveredWindow && g.IO.MouseHorizWheel != 0.0f && !g.HoveredWindow->Collapsed)
+    {
+        ImGuiWindow* window = g.HoveredWindow;
+        if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse))
+        {
+            SetWindowScrollX(window, window->Scroll.x - g.IO.MouseHorizWheel * 10.f);
+        }
+    }
+
     // Pressing TAB activate widget focus
     if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false))
         g.NavWindow->FocusIdxTabRequestNext = 0;
@@ -5244,6 +5255,13 @@
     return window->Pos;
 }
 
+static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
+{
+    window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
+    window->Scroll.x = new_scroll_x;
+    window->DC.CursorMaxPos.x -= window->Scroll.x;
+}
+
 static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
 {
     window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
diff --git a/imgui.h b/imgui.h
index 4599d70..d45b5e8 100644
--- a/imgui.h
+++ b/imgui.h
@@ -856,6 +856,7 @@
     ImVec2      MousePos;                   // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.)
     bool        MouseDown[5];               // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
     float       MouseWheel;                 // Mouse wheel: 1 unit scrolls about 5 lines text.
+    float       MouseHorizWheel;            // Horizontal mouse wheel
     bool        MouseDrawCursor;            // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor).
     bool        KeyCtrl;                    // Keyboard modifier pressed: Control
     bool        KeyShift;                   // Keyboard modifier pressed: Shift