diff --git a/pd/nw/index.js b/pd/nw/index.js
index 33ea2c1c053b6dc5a17db506ca2707b38c60bc73..d37a60aaa538c0d5547e35f8e19ec55c4a376c68 100644
--- a/pd/nw/index.js
+++ b/pd/nw/index.js
@@ -87,6 +87,16 @@ function nw_window_focus_callback() {
     }
 }
 
+// This should be merged with the same function name in pd_canvas.js,
+// except that we're not saving the Pd Window zoomlevel anywhere
+function nw_window_zoom(delta) {
+    var z = gui.Window.get().zoomLevel;
+    z += delta;
+    if (z < 8 && z > -8) {
+        gui.Window.get().zoomLevel = z;
+    }
+}
+
 function connect() {
     var gui_path, file_path;
     if (have_args() && gui.App.argv.length > 1) {
@@ -323,6 +333,16 @@ function add_events() {
     gui.Window.get().on("focus", function () {
         nw_window_focus_callback();
     });
+    // Pd Window zooming with mousewheel
+    document.addEventListener("wheel", function(evt) {
+        if (pdgui.cmd_or_ctrl_key(evt)) {
+            if (evt.deltaY < 0) {
+                nw_window_zoom(+1);
+            } else if (evt.deltaY > 0) {
+                nw_window_zoom(-1);
+            }
+        }
+    }, false);
     // Open dialog
     document.getElementById("fileDialog").setAttribute("nwworkingdir", pwd);
     document.getElementById("fileDialog").setAttribute("accept",
@@ -593,16 +613,12 @@ function nw_create_pd_window_menus(gui, w) {
     // View menu
     minit(m.view.zoomin, {
         click: function () {
-            var z = gui.Window.get().zoomLevel;
-            if (z < 8) { z++; }
-            gui.Window.get().zoomLevel = z;
+            nw_window_zoom(+1);
         }
     });
     minit(m.view.zoomout, {
         click: function () {
-            var z = gui.Window.get().zoomLevel;
-            if (z > -7) { z--; }
-            gui.Window.get().zoomLevel = z;
+            nw_window_zoom(-1);
         }
     });
     minit(m.view.zoomreset, {
diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js
index 106d56d5354de59bebe59475472e1e659b16cd02..399ea05f7f5dca3ea1cacf7546bb64ab0c355d9d 100644
--- a/pd/nw/pd_canvas.js
+++ b/pd/nw/pd_canvas.js
@@ -122,6 +122,16 @@ function nw_window_blur_callback(name) {
     }
 }
 
+function nw_window_zoom(name, delta) {
+    var z = gui.Window.get().zoomLevel;
+    z += delta;
+    if (z < 8 && z > -8) {
+        gui.Window.get().zoomLevel = z;
+        pdgui.pdsend(name, "zoom", z);
+        pdgui.gui_canvas_get_scroll(name);
+    }
+}
+
 // These three functions need to be inside canvas_events closure
 function canvas_find_whole_word(elem) {
     canvas_events.match_words(elem.checked);
@@ -580,6 +590,15 @@ var canvas_events = (function() {
         pdgui.pdsend(name, "paste");
     });
 
+    // MouseWheel event for zooming
+    document.addEventListener("wheel", function(evt) {
+        if (evt.deltaY < 0) {
+            nw_window_zoom(name, +1);
+        } else if (evt.deltaY > 0) {
+            nw_window_zoom(name, -1);
+        }
+    });
+
     // The following is commented out because we have to set the
     // event listener inside nw_create_pd_window_menus due to a
     // bug with nwworkingdir
@@ -1265,21 +1284,13 @@ function nw_create_patch_window_menus(gui, w, name) {
     minit(m.view.zoomin, {
         enabled: true,
         click: function () {
-            var z = gui.Window.get().zoomLevel;
-            if (z < 8) { z++; }
-            gui.Window.get().zoomLevel = z;
-            pdgui.pdsend(name, "zoom", z);
-            pdgui.gui_canvas_get_scroll(name);
+            nw_window_zoom(name, +1);
         }
     });
     minit(m.view.zoomout, {
         enabled: true,
         click: function () {
-            var z = gui.Window.get().zoomLevel;
-            if (z > -7) { z--; }
-            gui.Window.get().zoomLevel = z;
-            pdgui.pdsend(name, "zoom", z);
-            pdgui.gui_canvas_get_scroll(name);
+            nw_window_zoom(name, -1);
         }
     });
     minit(m.view.optimalzoom, {