Browse Source

feat: allow setting window shape (backport: 3-0-x) (#14445)

* feat: allow setting window shape

This binds Widget::SetShape, an API that already exists in Chromium (for
Windows and Linux). It's a more reliable method of having some parts of
your window be "click-through" than the current `setIgnoreMouseEvents`
API, which messes around with the `WS_EX_LAYERED` window style on
Windows, causing strange bugs and incompatibility with hardware
acceleration.

* update docs
trop[bot] 6 years ago
parent
commit
ce592a5705

+ 5 - 0
atom/browser/api/atom_api_top_level_window.cc

@@ -571,6 +571,10 @@ double TopLevelWindow::GetOpacity() {
   return window_->GetOpacity();
 }
 
+void TopLevelWindow::SetShape(const std::vector<gfx::Rect>& rects) {
+  window_->widget()->SetShape(std::make_unique<std::vector<gfx::Rect>>(rects));
+}
+
 void TopLevelWindow::SetRepresentedFilename(const std::string& filename) {
   window_->SetRepresentedFilename(filename);
 }
@@ -993,6 +997,7 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("hasShadow", &TopLevelWindow::HasShadow)
       .SetMethod("setOpacity", &TopLevelWindow::SetOpacity)
       .SetMethod("getOpacity", &TopLevelWindow::GetOpacity)
+      .SetMethod("setShape", &TopLevelWindow::SetShape)
       .SetMethod("setRepresentedFilename",
                  &TopLevelWindow::SetRepresentedFilename)
       .SetMethod("getRepresentedFilename",

+ 1 - 0
atom/browser/api/atom_api_top_level_window.h

@@ -146,6 +146,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
   bool HasShadow();
   void SetOpacity(const double opacity);
   double GetOpacity();
+  void SetShape(const std::vector<gfx::Rect>& rects);
   void SetRepresentedFilename(const std::string& filename);
   std::string GetRepresentedFilename();
   void SetDocumentEdited(bool edited);

+ 11 - 0
docs/api/browser-window.md

@@ -1264,6 +1264,17 @@ Sets the opacity of the window. On Linux does nothing.
 
 Returns `Number` - between 0.0 (fully transparent) and 1.0 (fully opaque)
 
+#### `win.setShape(rects)` _Windows_ _Linux_ _Experimental_
+
+* `rects` [Rectangle[]](structures/rectangle.md) - Sets a shape on the window.
+  Passing an empty list reverts the window to being rectangular.
+
+Setting a window shape determines the area within the window where the system
+permits drawing and user interaction. Outside of the given region, no pixels
+will be drawn and no mouse events will be registered. Mouse events outside of
+the region will not be received by that window, but will fall through to
+whatever is behind the window.
+
 #### `win.setThumbarButtons(buttons)` _Windows_
 
 * `buttons` [ThumbarButton[]](structures/thumbar-button.md)

+ 11 - 0
spec/api-browser-window-spec.js

@@ -893,6 +893,17 @@ describe('BrowserWindow module', () => {
     })
   })
 
+  describe('BrowserWindow.setShape(rects)', () => {
+    it('allows setting shape', () => {
+      assert.doesNotThrow(() => {
+        w.setShape([])
+        w.setShape([{x: 0, y: 0, width: 100, height: 100}])
+        w.setShape([{x: 0, y: 0, width: 100, height: 100}, {x: 0, y: 200, width: 1000, height: 100}])
+        w.setShape([])
+      })
+    })
+  })
+
   describe('"useContentSize" option', () => {
     it('make window created with content size when used', () => {
       w.destroy()