diff --git a/example/linux/flutter_embedder_example.cc b/example/linux/flutter_embedder_example.cc
index 1a030828e..003ecd989 100644
--- a/example/linux/flutter_embedder_example.cc
+++ b/example/linux/flutter_embedder_example.cc
@@ -26,7 +26,7 @@
 #ifdef USE_FLATTENED_INCLUDES
 #include <flutter_desktop_embedding/embedder.h>
 #else
-#include <flutter_desktop_embedding/linux/embedder.h>
+#include <flutter_desktop_embedding/glfw/embedder.h>
 #endif
 
 namespace {
@@ -53,7 +53,7 @@ std::string GetExecutableDirectory() {
 }  // namespace
 
 int main(int argc, char **argv) {
-  if (!glfwInit()) {
+  if (!flutter_desktop_embedding::FlutterInit()) {
     std::cerr << "Couldn't init GLFW" << std::endl;
   }
 
@@ -78,7 +78,7 @@ int main(int argc, char **argv) {
   auto window = flutter_desktop_embedding::CreateFlutterWindowInSnapshotMode(
       640, 480, assets_path, icu_data_path, arguments);
   if (window == nullptr) {
-    glfwTerminate();
+    flutter_desktop_embedding::FlutterTerminate();
     return EXIT_FAILURE;
   }
 
diff --git a/example/windows/GLFW Example.vcxproj b/example/windows/GLFW Example.vcxproj
index e15a6eda7..c61b451f0 100644
--- a/example/windows/GLFW Example.vcxproj	
+++ b/example/windows/GLFW Example.vcxproj	
@@ -72,7 +72,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Dynamic Library|x64'">
     <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
     <IntDir>$(SolutionDir)bin\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
-    <IncludePath>$(ProjectDir)..\..\library\windows\dependencies\;$(ProjectDir)..\..\;$(IncludePath);$(ProjectDir)..\..\library\windows\</IncludePath>
+    <IncludePath>$(ProjectDir)..\..\library\windows\dependencies\;$(ProjectDir)..\..\;$(IncludePath);$(ProjectDir)..\..\library\windows\;$(ProjectDir)..\..\library\include\</IncludePath>
     <LibraryPath>$(ProjectDir)..\..\library\windows\dependencies\GLFW\;$(SolutionDir)bin\$(Platform)\$(Configuration)\GLFW Library\;$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static Library|x64'">
diff --git a/example/windows/flutter_embedder_example.cpp b/example/windows/flutter_embedder_example.cpp
index 165bbd55e..94d4a2d57 100644
--- a/example/windows/flutter_embedder_example.cpp
+++ b/example/windows/flutter_embedder_example.cpp
@@ -15,7 +15,7 @@
 #include <iostream>
 #include <vector>
 
-#include "embedder.h"
+#include "flutter_desktop_embedding/glfw/embedder.h"
 
 int main(int argc, char **argv) {
   if (!flutter_desktop_embedding::FlutterInit()) {
diff --git a/library/BUILD.gn b/library/BUILD.gn
index 6b31ae428..605deddc5 100644
--- a/library/BUILD.gn
+++ b/library/BUILD.gn
@@ -17,14 +17,22 @@ import("//build/packaging.gni")
 import("//library/engine.gni")
 
 published_shared_library("flutter_embedder") {
-  if (is_linux) {
-    sources = [
-      "linux/src/embedder.cc",
-    ]
+  # GLFW embedding implementation.
+  if (is_linux || is_win) {
     public = [
-      "include/flutter_desktop_embedding/linux/embedder.h",
+      "include/flutter_desktop_embedding/glfw/embedder.h",
+    ]
+    sources = [
+      "common/glfw/embedder.cc",
+      "common/glfw/key_event_handler.cc",
+      "common/glfw/key_event_handler.h",
+      "common/glfw/keyboard_hook_handler.h",
+      "common/glfw/text_input_plugin.cc",
+      "common/glfw/text_input_plugin.h",
     ]
   }
+
+  # Embedding-agnostic shared C++.
   if (is_linux || is_win) {
     sources += [
       "common/internal/engine_method_result.cc",
@@ -56,16 +64,6 @@ published_shared_library("flutter_embedder") {
       "include/flutter_desktop_embedding/plugin.h",
     ]
   }
-  # GLFW-specific code.
-  if (is_linux || is_win) {
-    sources += [
-      "common/glfw/key_event_handler.cc",
-      "common/glfw/key_event_handler.h",
-      "common/glfw/keyboard_hook_handler.h",
-      "common/glfw/text_input_plugin.cc",
-      "common/glfw/text_input_plugin.h",
-    ]
-  }
 
   deps = [
     ":fetch_flutter_engine",
diff --git a/library/README.md b/library/README.md
index e325a41d6..79329f705 100644
--- a/library/README.md
+++ b/library/README.md
@@ -49,7 +49,7 @@ $ sudo apt-get install libglfw3-dev libepoxy-dev libjsoncpp-dev libgtk-3-dev \
 #### Using the Library
 
 Run `make` under `linux/`, then link `libflutter_embedder.so` into your
-binary. See [embedder.h](linux/include/flutter_desktop_embedding/embedder.h)
+binary. See [embedder.h](include/flutter_desktop_embedding/glfw/embedder.h)
 for details on calling into the library.
 
 You will also need to link `libflutter_engine.so` into your binary.
diff --git a/library/linux/src/embedder.cc b/library/common/glfw/embedder.cc
similarity index 88%
rename from library/linux/src/embedder.cc
rename to library/common/glfw/embedder.cc
index b793464a2..c2a0b6460 100644
--- a/library/linux/src/embedder.cc
+++ b/library/common/glfw/embedder.cc
@@ -11,18 +11,14 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-#include <flutter_desktop_embedding/linux/embedder.h>
 
-#include <X11/Xlib.h>
-#include <assert.h>
-#include <gtk/gtk.h>
+#include "library/include/flutter_desktop_embedding/glfw/embedder.h"
 
+#include <assert.h>
 #include <algorithm>
 #include <chrono>
 #include <cstdlib>
 #include <iostream>
-#include <memory>
-#include <string>
 
 #include <flutter_embedder.h>
 
@@ -31,6 +27,12 @@
 #include "library/common/glfw/text_input_plugin.h"
 #include "library/common/internal/plugin_handler.h"
 
+#ifdef __linux__
+// For plugin-compatible event handling (e.g., modal windows).
+#include <X11/Xlib.h>
+#include <gtk/gtk.h>
+#endif
+
 // GLFW_TRUE & GLFW_FALSE are introduced since libglfw-3.3,
 // add definitions here to compile under the old versions.
 #ifndef GLFW_TRUE
@@ -51,67 +53,22 @@ struct FlutterEmbedderState {
   // deleted from the heap.
   std::vector<flutter_desktop_embedding::KeyboardHookHandler *>
       keyboard_hook_handlers;
+
   // Handles raw key interactions from GLFW.
-  // TODO: Move key_event_handler once
-  // https://github.com/google/flutter-desktop-embedding/issues/102 is resolved.
+  // TODO: Revisit ownership model once Issue #102 is resolved.
   std::unique_ptr<flutter_desktop_embedding::KeyEventHandler> key_event_handler;
 };
 
 static constexpr char kDefaultWindowTitle[] = "Flutter";
 
-// Callback forward declarations.
-static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode,
-                            int action, int mods);
-static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point);
-static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action,
-                                    int mods);
-
+// Retrieves state bag for the window in question from the GLFWWindow.
 static FlutterEmbedderState *GetSavedEmbedderState(GLFWwindow *window) {
   return reinterpret_cast<FlutterEmbedderState *>(
       glfwGetWindowUserPointer(window));
 }
 
-// Flushes event queue and then assigns default window callbacks.
-static void GLFWAssignEventCallbacks(GLFWwindow *window) {
-  glfwPollEvents();
-  glfwSetKeyCallback(window, GLFWKeyCallback);
-  glfwSetCharCallback(window, GLFWCharCallback);
-  glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback);
-}
-
-// Clears default window events.
-static void GLFWClearEventCallbacks(GLFWwindow *window) {
-  glfwSetKeyCallback(window, nullptr);
-  glfwSetCharCallback(window, nullptr);
-  glfwSetMouseButtonCallback(window, nullptr);
-}
-
-static void GLFWwindowSizeCallback(GLFWwindow *window, int width, int height) {
-  FlutterWindowMetricsEvent event = {};
-  event.struct_size = sizeof(event);
-  event.width = width;
-  event.height = height;
-  event.pixel_ratio = 1.0;
-  auto state = GetSavedEmbedderState(window);
-  FlutterEngineSendWindowMetricsEvent(state->engine, &event);
-}
-
-static void GLFWOnFlutterPlatformMessage(const FlutterPlatformMessage *message,
-                                         void *user_data) {
-  if (message->struct_size != sizeof(FlutterPlatformMessage)) {
-    std::cerr << "Invalid message size received. Expected: "
-              << sizeof(FlutterPlatformMessage) << " but received "
-              << message->struct_size << std::endl;
-    return;
-  }
-
-  GLFWwindow *window = reinterpret_cast<GLFWwindow *>(user_data);
-  auto state = GetSavedEmbedderState(window);
-  state->plugin_handler->HandleMethodCallMessage(
-      message, [window] { GLFWClearEventCallbacks(window); },
-      [window] { GLFWAssignEventCallbacks(window); });
-}
-
+// When GLFW calls back to the window with a cursor position move, forwards to
+// FlutterEngine as a pointer event with appropriate phase.
 static void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window,
                                               FlutterPointerPhase phase,
                                               double x, double y) {
@@ -124,14 +81,16 @@ static void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window,
       std::chrono::duration_cast<std::chrono::microseconds>(
           std::chrono::high_resolution_clock::now().time_since_epoch())
           .count();
-  auto state = GetSavedEmbedderState(window);
-  FlutterEngineSendPointerEvent(state->engine, &event, 1);
+  FlutterEngineSendPointerEvent(GetSavedEmbedderState(window)->engine, &event,
+                                1);
 }
 
+// Reports cursor move to the Flutter engine.
 static void GLFWcursorPositionCallback(GLFWwindow *window, double x, double y) {
   GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kMove, x, y);
 }
 
+// Reports mouse button press to the Flutter engine.
 static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action,
                                     int mods) {
   double x, y;
@@ -147,6 +106,7 @@ static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action,
   }
 }
 
+// Passes character input events to registered handlers.
 static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point) {
   for (flutter_desktop_embedding::KeyboardHookHandler *handler :
        GetSavedEmbedderState(window)->keyboard_hook_handlers) {
@@ -154,6 +114,7 @@ static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point) {
   }
 }
 
+// Passes raw key events to registered handlers.
 static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode,
                             int action, int mods) {
   for (flutter_desktop_embedding::KeyboardHookHandler *handler :
@@ -162,6 +123,51 @@ static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode,
   }
 }
 
+// Reports window size changes to the Flutter engine.
+static void GLFWwindowSizeCallback(GLFWwindow *window, int width, int height) {
+  FlutterWindowMetricsEvent event = {};
+  event.struct_size = sizeof(event);
+  event.width = width;
+  event.height = height;
+  // TODO: Handle pixel ratio for different DPI monitors.
+  event.pixel_ratio = 1.0;
+  FlutterEngineSendWindowMetricsEvent(GetSavedEmbedderState(window)->engine,
+                                      &event);
+}
+
+// Flushes event queue and then assigns default window callbacks.
+static void GLFWAssignEventCallbacks(GLFWwindow *window) {
+  glfwPollEvents();
+  glfwSetKeyCallback(window, GLFWKeyCallback);
+  glfwSetCharCallback(window, GLFWCharCallback);
+  glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback);
+}
+
+// Clears default window events.
+static void GLFWClearEventCallbacks(GLFWwindow *window) {
+  glfwSetKeyCallback(window, nullptr);
+  glfwSetCharCallback(window, nullptr);
+  glfwSetMouseButtonCallback(window, nullptr);
+}
+
+// The Flutter Engine calls out to this function when new platform messages are
+// available
+static void GLFWOnFlutterPlatformMessage(const FlutterPlatformMessage *message,
+                                         void *user_data) {
+  if (message->struct_size != sizeof(FlutterPlatformMessage)) {
+    std::cerr << "Invalid message size received. Expected: "
+              << sizeof(FlutterPlatformMessage) << " but received "
+              << message->struct_size << std::endl;
+    return;
+  }
+
+  GLFWwindow *window = reinterpret_cast<GLFWwindow *>(user_data);
+  auto state = GetSavedEmbedderState(window);
+  state->plugin_handler->HandleMethodCallMessage(
+      message, [window] { GLFWClearEventCallbacks(window); },
+      [window] { GLFWAssignEventCallbacks(window); });
+}
+
 static bool GLFWMakeContextCurrent(void *user_data) {
   GLFWwindow *window = reinterpret_cast<GLFWwindow *>(user_data);
   glfwMakeContextCurrent(window);
@@ -192,7 +198,7 @@ static uint32_t GLFWGetActiveFbo(void *user_data) { return 0; }
 static void GLFWClearCanvas(GLFWwindow *window) {
   glfwMakeContextCurrent(window);
   // This color is Material Blue Grey.
-  glClearColor(0.92549, 0.93725, 0.9451, 0);
+  glClearColor(236.0 / 255.0, 239.0 / 255.0, 241.0 / 255.0, 0);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glFlush();
   glfwSwapBuffers(window);
@@ -242,6 +248,13 @@ static FlutterEngine RunFlutterEngine(
 
 namespace flutter_desktop_embedding {
 
+// Initialize glfw
+bool FlutterInit() { return glfwInit(); }
+
+// Tear down glfw
+void FlutterTerminate() { glfwTerminate(); }
+
+// set up embedder state and add the plugin to the plugin_handler
 bool AddPlugin(GLFWwindow *flutter_window, std::unique_ptr<Plugin> plugin) {
   auto state = GetSavedEmbedderState(flutter_window);
   return state->plugin_handler->AddPlugin(std::move(plugin));
@@ -261,7 +274,9 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
                                 const std::string &packages_path,
                                 const std::string &icu_data_path,
                                 const std::vector<std::string> &arguments) {
+#ifdef __linux__
   gtk_init(0, nullptr);
+#endif
   auto window = glfwCreateWindow(initial_width, initial_height,
                                  kDefaultWindowTitle, NULL, NULL);
   if (window == nullptr) {
@@ -274,6 +289,7 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
     glfwDestroyWindow(window);
     return nullptr;
   }
+
   FlutterEmbedderState *state = new FlutterEmbedderState();
   state->plugin_handler = std::make_unique<PluginHandler>(engine);
   state->engine = engine;
@@ -297,13 +313,19 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
 }
 
 void FlutterWindowLoop(GLFWwindow *flutter_window) {
+#ifdef __linux__
   // Necessary for GTK thread safety.
   XInitThreads();
+#endif
   while (!glfwWindowShouldClose(flutter_window)) {
+#ifdef __linux__
     glfwPollEvents();
     if (gtk_events_pending()) {
       gtk_main_iteration();
     }
+#else
+    glfwWaitEvents();
+#endif
     // TODO(awdavies): This will be deprecated soon.
     __FlutterEngineFlushPendingTasksNow();
   }
diff --git a/library/windows/embedder.h b/library/include/flutter_desktop_embedding/glfw/embedder.h
similarity index 88%
rename from library/windows/embedder.h
rename to library/include/flutter_desktop_embedding/glfw/embedder.h
index 028d418fb..669ea9d50 100644
--- a/library/windows/embedder.h
+++ b/library/include/flutter_desktop_embedding/glfw/embedder.h
@@ -12,15 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef WINDOWS_LIBRARY_EMBEDDER_H_
-#define WINDOWS_LIBRARY_EMBEDDER_H_
+#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_
+#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
+#ifdef __linux__
+// Epoxy must be included before any graphics-related code.
+#include <epoxy/gl.h>
+#endif
+
 #include <GLFW/glfw3.h>
 
-#include "library/include/flutter_desktop_embedding/plugin.h"
+#ifdef USE_FLATTENED_INCLUDES
+#include "plugin.h"
+#else
+#include "../plugin.h"
+#endif
 
 namespace flutter_desktop_embedding {
 
@@ -86,4 +96,4 @@ void FlutterWindowLoop(GLFWwindow *flutter_window);
 
 }  // namespace flutter_desktop_embedding
 
-#endif  // WINDOWS_LIBRARY_EMBEDDER_H_
+#endif  // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_
diff --git a/library/include/flutter_desktop_embedding/linux/embedder.h b/library/include/flutter_desktop_embedding/linux/embedder.h
deleted file mode 100644
index 3fc973595..000000000
--- a/library/include/flutter_desktop_embedding/linux/embedder.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_LINUX_EMBEDDER_H_
-#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_LINUX_EMBEDDER_H_
-
-// Epoxy must be included before any graphics-related code.
-#include <epoxy/gl.h>
-
-#include <GLFW/glfw3.h>
-
-#include <memory>
-#include <string>
-
-#ifdef USE_FLATTENED_INCLUDES
-#include "plugin.h"
-#else
-#include "../plugin.h"
-#endif
-
-namespace flutter_desktop_embedding {
-
-// Creates a GLFW Window running a Flutter Application.
-//
-// glfwInit() must be called prior to this function.
-//
-// The arguments are to configure the paths when launching the engine. See:
-// https://github.com/flutter/engine/wiki/Custom-Flutter-Engine-Embedders for
-// more details on Flutter Engine embedding.
-//
-// Returns a null pointer in the event of an error. The caller owns the pointer
-// when it is non-null.
-GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
-                                const std::string &main_path,
-                                const std::string &assets_path,
-                                const std::string &packages_path,
-                                const std::string &icu_data_path,
-                                const std::vector<std::string> &arguments);
-
-// Creates a GLFW Window running a Flutter Application in snapshot mode.
-//
-// glfwInit() must be called prior to this function.
-//
-// In snapshot mode the assets directory snapshot is used to run the application
-// instead of the sources.
-//
-// The arguments are to configure the paths when launching the engine. See:
-// https://github.com/flutter/engine/wiki/Custom-Flutter-Engine-Embedders for
-// more details on Flutter Engine embedding.
-//
-// Returns a null pointer in the event of an error. The caller owns the pointer
-// when it is non-null.
-GLFWwindow *CreateFlutterWindowInSnapshotMode(
-    size_t initial_width, size_t initial_height, const std::string &assets_path,
-    const std::string &icu_data_path,
-    const std::vector<std::string> &arguments);
-
-// Adds a plugin to the flutter_window.
-//
-// If a plugin already exists for this plugin's channel, returns false.
-// Otherwise returns true.
-bool AddPlugin(GLFWwindow *flutter_window, std::unique_ptr<Plugin> plugin);
-
-// Loops on flutter window events until termination.
-//
-// Must be used instead of glfwWindowShouldClose as it cleans up engine state
-// after termination.
-//
-// After this function the user must eventually call glfwTerminate() if doing
-// cleanup.
-void FlutterWindowLoop(GLFWwindow *flutter_window);
-
-}  // namespace flutter_desktop_embedding
-
-#endif  // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_LINUX_EMBEDDER_H_
diff --git a/library/linux/Makefile b/library/linux/Makefile
index 7c7f4db47..6a5810892 100644
--- a/library/linux/Makefile
+++ b/library/linux/Makefile
@@ -36,7 +36,7 @@ LDFLAGS= -L$(CURDIR) \
 LIBRARIES=$(FLUTTER_ENGINE_LIB_FILE)
 HEADERS=$(shell find $(PROJECT_ROOT)/library/include/ -type f -name '*.h') \
 	$(FLUTTER_ENGINE_HEADER_DIR)/$(FLUTTER_ENGINE_HEADER)
-SOURCES=$(shell find src/ $(PROJECT_ROOT)/library/common/ -type f -name '*.cc')
+SOURCES=$(shell find $(PROJECT_ROOT)/library/common/ -type f -name '*.cc')
 
 .PHONY: all
 all: $(LIBRARY_OUT)
diff --git a/library/windows/GLFW Library.vcxproj b/library/windows/GLFW Library.vcxproj
index 8ea8c4899..f1628bc2d 100644
--- a/library/windows/GLFW Library.vcxproj	
+++ b/library/windows/GLFW Library.vcxproj	
@@ -263,6 +263,7 @@
     </PreLinkEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="..\common\glfw\embedder.cc" />
     <ClCompile Include="..\common\glfw\key_event_handler.cc" />
     <ClCompile Include="..\common\glfw\text_input_plugin.cc" />
     <ClCompile Include="..\common\internal\engine_method_result.cc" />
@@ -277,7 +278,6 @@
     <ClCompile Include="..\common\method_codec.cc" />
     <ClCompile Include="..\common\method_result.cc" />
     <ClCompile Include="..\common\plugin.cc" />
-    <ClCompile Include="embedder.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="embedder.h" />
@@ -288,4 +288,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/library/windows/GLFW Library.vcxproj.filters b/library/windows/GLFW Library.vcxproj.filters
index bf7b4fad3..03dd85a33 100644
--- a/library/windows/GLFW Library.vcxproj.filters	
+++ b/library/windows/GLFW Library.vcxproj.filters	
@@ -15,7 +15,7 @@
     </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="embedder.cpp">
+    <ClCompile Include="..\common\glfw\embedder.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\common\internal\plugin_handler.cc">
@@ -71,4 +71,4 @@
       <Filter>Source Files</Filter>
     </None>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/library/windows/embedder.cpp b/library/windows/embedder.cpp
deleted file mode 100644
index f6522ca3f..000000000
--- a/library/windows/embedder.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "embedder.h"
-
-#include <assert.h>
-#include <algorithm>
-#include <chrono>
-#include <iostream>
-
-#include <flutter_embedder.h>
-
-#include "library/common/glfw/key_event_handler.h"
-#include "library/common/glfw/keyboard_hook_handler.h"
-#include "library/common/glfw/text_input_plugin.h"
-#include "library/common/internal/plugin_handler.h"
-
-static_assert(FLUTTER_ENGINE_VERSION == 1, "");
-
-// Struct for storing state within an instance of the GLFW Window.
-struct FlutterEmbedderState {
-  FlutterEngine engine;
-  std::unique_ptr<flutter_desktop_embedding::PluginHandler> plugin_handler;
-
-  // plugin_handler owns these pointers. Destruction happens when this struct is
-  // deleted from the heap.
-  std::vector<flutter_desktop_embedding::KeyboardHookHandler *>
-      keyboard_hook_handlers;
-
-  // Handles raw key interactions from GLFW.
-  // TODO: Revisit ownership model once Issue #102 is resolved.
-  std::unique_ptr<flutter_desktop_embedding::KeyEventHandler> key_event_handler;
-};
-
-static constexpr char kDefaultWindowTitle[] = "Flutter";
-
-// Retreaves state bag for the window in question from the GLFWWindow
-static FlutterEmbedderState *GetSavedEmbedderState(GLFWwindow *window) {
-  return reinterpret_cast<FlutterEmbedderState *>(
-      glfwGetWindowUserPointer(window));
-}
-
-// When GLFW calls back to the window with a cursor position move, forward to
-// FlutterEngine as a pointer event with appropriate phase
-static void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window,
-                                              FlutterPointerPhase phase,
-                                              double x, double y) {
-  FlutterPointerEvent event = {};
-  event.struct_size = sizeof(event);
-  event.phase = phase;
-  event.x = x;
-  event.y = y;
-  event.timestamp =
-      std::chrono::duration_cast<std::chrono::microseconds>(
-          std::chrono::high_resolution_clock::now().time_since_epoch())
-          .count();
-  FlutterEngineSendPointerEvent(GetSavedEmbedderState(window)->engine, &event,
-                                1);
-}
-
-// Report cursor move to engine
-static void GLFWcursorPositionCallback(GLFWwindow *window, double x, double y) {
-  GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kMove, x, y);
-}
-
-static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action,
-                                    int mods) {
-  double x, y;
-  if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) {
-    glfwGetCursorPos(window, &x, &y);
-    GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kDown, x, y);
-    glfwSetCursorPosCallback(window, GLFWcursorPositionCallback);
-  }
-  if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_RELEASE) {
-    glfwGetCursorPos(window, &x, &y);
-    GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kUp, x, y);
-    glfwSetCursorPosCallback(window, nullptr);
-  }
-}
-
-static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point) {
-  for (flutter_desktop_embedding::KeyboardHookHandler *handler :
-       GetSavedEmbedderState(window)->keyboard_hook_handlers) {
-    handler->CharHook(window, code_point);
-  }
-}
-
-static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode,
-                            int action, int mods) {
-  for (flutter_desktop_embedding::KeyboardHookHandler *handler :
-       GetSavedEmbedderState(window)->keyboard_hook_handlers) {
-    handler->KeyboardHook(window, key, scancode, action, mods);
-  }
-  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
-    glfwSetWindowShouldClose(window, GLFW_TRUE);
-  }
-}
-
-static void GLFWwindowSizeCallback(GLFWwindow *window, int width, int height) {
-  FlutterWindowMetricsEvent event = {};
-  event.struct_size = sizeof(event);
-  event.width = width;
-  event.height = height;
-  // TODO: Handle pixel ratio for different DPI monitors.
-  event.pixel_ratio = 1.0;
-  FlutterEngineSendWindowMetricsEvent(GetSavedEmbedderState(window)->engine,
-                                      &event);
-}
-
-// Flushes event queue and then assigns default window callbacks.
-static void GLFWAssignEventCallbacks(GLFWwindow *window) {
-  glfwPollEvents();
-  glfwSetKeyCallback(window, GLFWKeyCallback);
-  glfwSetCharCallback(window, GLFWCharCallback);
-  glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback);
-}
-
-// Clears default window events.
-static void GLFWClearEventCallbacks(GLFWwindow *window) {
-  glfwSetKeyCallback(window, nullptr);
-  glfwSetCharCallback(window, nullptr);
-  glfwSetMouseButtonCallback(window, nullptr);
-}
-
-// The Flutter Engine calls out to this function when new platform messages are
-// available
-static void GLFWOnFlutterPlatformMessage(const FlutterPlatformMessage *message,
-                                         void *user_data) {
-  if (message->struct_size != sizeof(FlutterPlatformMessage)) {
-    std::cerr << "Invalid message size received. Expected: "
-              << sizeof(FlutterPlatformMessage) << " but received "
-              << message->struct_size << std::endl;
-    return;
-  }
-
-  GLFWwindow *window = reinterpret_cast<GLFWwindow *>(user_data);
-  auto state = GetSavedEmbedderState(window);
-  state->plugin_handler->HandleMethodCallMessage(
-      message, [window] { GLFWClearEventCallbacks(window); },
-      [window] { GLFWAssignEventCallbacks(window); });
-}
-
-static bool GLFWMakeContextCurrent(void *user_data) {
-  GLFWwindow *window = reinterpret_cast<GLFWwindow *>(user_data);
-  glfwMakeContextCurrent(window);
-  return true;
-}
-
-static bool GLFWClearContext(void *user_data) {
-  glfwMakeContextCurrent(nullptr);
-  return true;
-}
-
-static bool GLFWPresent(void *user_data) {
-  GLFWwindow *window = reinterpret_cast<GLFWwindow *>(user_data);
-  glfwSwapBuffers(window);
-  return true;
-}
-
-static uint32_t GLFWGetActiveFbo(void *user_data) { return 0; }
-
-// Clears the GLFW window to Material Blue-Grey.
-//
-// This function is primarily to fix an issue when the Flutter Engine is
-// spinning up, wherein artifacts of existing windows are rendered onto the
-// canvas for a few moments.
-//
-// This function isn't necessary, but makes starting the window much easier on
-// the eyes.
-static void GLFWClearCanvas(GLFWwindow *window) {
-  glfwMakeContextCurrent(window);
-  // This color is Material Blue Grey.
-  glClearColor(236, 239, 241, 0);
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  glFlush();
-  glfwSwapBuffers(window);
-  glfwMakeContextCurrent(nullptr);
-}
-
-// Spins up an instance of the Flutter Engine.
-//
-// This function launches the Flutter Engine in a background thread, supplying
-// the necessary callbacks for rendering within a GLFWwindow.
-//
-// Returns a caller-owned pointer to the engine.
-static FlutterEngine RunFlutterEngine(
-    GLFWwindow *window, const std::string &main_path,
-    const std::string &assets_path, const std::string &packages_path,
-    const std::string &icu_data_path,
-    const std::vector<std::string> &arguments) {
-  std::vector<const char *> argv;
-  std::transform(
-      arguments.begin(), arguments.end(), std::back_inserter(argv),
-      [](const std::string &arg) -> const char * { return arg.c_str(); });
-
-  FlutterRendererConfig config = {};
-  config.type = kOpenGL;
-  config.open_gl.struct_size = sizeof(config.open_gl);
-  config.open_gl.make_current = GLFWMakeContextCurrent;
-  config.open_gl.clear_current = GLFWClearContext;
-  config.open_gl.present = GLFWPresent;
-  config.open_gl.fbo_callback = GLFWGetActiveFbo;
-  FlutterProjectArgs args = {};
-  args.struct_size = sizeof(FlutterProjectArgs);
-  args.assets_path = assets_path.c_str();
-  args.main_path = main_path.c_str();
-  args.packages_path = packages_path.c_str();
-  args.icu_data_path = icu_data_path.c_str();
-  args.command_line_argc = argv.size();
-  args.command_line_argv = &argv[0];
-  args.platform_message_callback = GLFWOnFlutterPlatformMessage;
-  FlutterEngine engine = nullptr;
-  auto result =
-      FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args, window, &engine);
-  if (result != kSuccess || engine == nullptr) {
-    return nullptr;
-  }
-  return engine;
-}
-
-namespace flutter_desktop_embedding {
-
-// Initialize glfw
-bool FlutterInit() { return glfwInit(); }
-
-// Tear down glfw
-void FlutterTerminate() { glfwTerminate(); }
-
-// set up embedder state and add the plugin to the plugin_handler
-bool AddPlugin(GLFWwindow *flutter_window, std::unique_ptr<Plugin> plugin) {
-  auto state = GetSavedEmbedderState(flutter_window);
-  return state->plugin_handler->AddPlugin(std::move(plugin));
-}
-
-GLFWwindow *CreateFlutterWindowInSnapshotMode(
-    size_t initial_width, size_t initial_height, const std::string &assets_path,
-    const std::string &icu_data_path,
-    const std::vector<std::string> &arguments) {
-  return CreateFlutterWindow(initial_width, initial_height, "", assets_path, "",
-                             icu_data_path, arguments);
-}
-
-GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
-                                const std::string &main_path,
-                                const std::string &assets_path,
-                                const std::string &packages_path,
-                                const std::string &icu_data_path,
-                                const std::vector<std::string> &arguments) {
-  auto window = glfwCreateWindow(initial_width, initial_height,
-                                 kDefaultWindowTitle, NULL, NULL);
-  if (window == nullptr) {
-    return nullptr;
-  }
-  GLFWClearCanvas(window);
-  auto engine = RunFlutterEngine(window, main_path, assets_path, packages_path,
-                                 icu_data_path, arguments);
-  if (engine == nullptr) {
-    glfwDestroyWindow(window);
-    return nullptr;
-  }
-
-  FlutterEmbedderState *state = new FlutterEmbedderState();
-  state->plugin_handler = std::make_unique<PluginHandler>(engine);
-  state->engine = engine;
-
-  state->key_event_handler =
-      std::make_unique<KeyEventHandler>(state->plugin_handler.get());
-  state->keyboard_hook_handlers.push_back(state->key_event_handler.get());
-  auto input_plugin = std::make_unique<TextInputPlugin>();
-  state->keyboard_hook_handlers.push_back(input_plugin.get());
-
-  glfwSetWindowUserPointer(window, state);
-
-  AddPlugin(window, std::move(input_plugin));
-
-  int width, height;
-  glfwGetWindowSize(window, &width, &height);
-  GLFWwindowSizeCallback(window, width, height);
-  glfwSetKeyCallback(window, GLFWKeyCallback);
-  glfwSetWindowSizeCallback(window, GLFWwindowSizeCallback);
-  glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback);
-  GLFWAssignEventCallbacks(window);
-  return window;
-}
-
-void FlutterWindowLoop(GLFWwindow *flutter_window) {
-  while (!glfwWindowShouldClose(flutter_window)) {
-    glfwWaitEvents();
-    // TODO(awdavies): This will be deprecated soon.
-    __FlutterEngineFlushPendingTasksNow();
-  }
-  auto state = GetSavedEmbedderState(flutter_window);
-  FlutterEngineShutdown(state->engine);
-  delete state;
-  glfwDestroyWindow(flutter_window);
-}
-
-}  // namespace flutter_desktop_embedding