Browse Source

Add window opacity support

Ted Kim 7 years ago
parent
commit
7f2c4a9e06

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

@@ -631,6 +631,10 @@ bool Window::HasShadow() {
   return window_->HasShadow();
 }
 
+void Window::SetOpacity(const double opacity) {
+  window_->SetOpacity(opacity);
+}
+
 void Window::FocusOnWebView() {
   window_->FocusOnWebView();
 }
@@ -1056,6 +1060,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("setBackgroundColor", &Window::SetBackgroundColor)
       .SetMethod("setHasShadow", &Window::SetHasShadow)
       .SetMethod("hasShadow", &Window::HasShadow)
+      .SetMethod("setOpacity", &Window::SetOpacity)
       .SetMethod("setRepresentedFilename", &Window::SetRepresentedFilename)
       .SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
       .SetMethod("setDocumentEdited", &Window::SetDocumentEdited)

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

@@ -161,6 +161,7 @@ class Window : public mate::TrackableObject<Window>,
   void SetBackgroundColor(const std::string& color_name);
   void SetHasShadow(bool has_shadow);
   bool HasShadow();
+  void SetOpacity(const double opacity);
   void FocusOnWebView();
   void BlurWebView();
   bool IsWebViewFocused();

+ 4 - 0
atom/browser/native_window.cc

@@ -159,6 +159,10 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
   if (options.Get(options::kHasShadow, &has_shadow)) {
     SetHasShadow(has_shadow);
   }
+  double opacity;
+  if (options.Get(options::kOpacity, &opacity)) {
+    SetOpacity(opacity);
+  }
   bool top;
   if (options.Get(options::kAlwaysOnTop, &top) && top) {
     SetAlwaysOnTop(true);

+ 1 - 0
atom/browser/native_window.h

@@ -141,6 +141,7 @@ class NativeWindow : public base::SupportsUserData,
   virtual void SetBackgroundColor(const std::string& color_name) = 0;
   virtual void SetHasShadow(bool has_shadow) = 0;
   virtual bool HasShadow() = 0;
+  virtual void SetOpacity(const double opacity) = 0;
   virtual void SetRepresentedFilename(const std::string& filename);
   virtual std::string GetRepresentedFilename();
   virtual void SetDocumentEdited(bool edited);

+ 1 - 0
atom/browser/native_window_mac.h

@@ -83,6 +83,7 @@ class NativeWindowMac : public NativeWindow,
   void SetBackgroundColor(const std::string& color_name) override;
   void SetHasShadow(bool has_shadow) override;
   bool HasShadow() override;
+  void SetOpacity(const double opacity) override;
   void SetRepresentedFilename(const std::string& filename) override;
   std::string GetRepresentedFilename() override;
   void SetDocumentEdited(bool edited) override;

+ 4 - 0
atom/browser/native_window_mac.mm

@@ -1503,6 +1503,10 @@ bool NativeWindowMac::HasShadow() {
   return [window_ hasShadow];
 }
 
+void NativeWindowMac::SetOpacity(const double opacity) {
+  [window_ setAlphaValue:opacity];
+}
+
 void NativeWindowMac::SetRepresentedFilename(const std::string& filename) {
   [window_ setRepresentedFilename:base::SysUTF8ToNSString(filename)];
 }

+ 15 - 0
atom/browser/native_window_views.cc

@@ -814,6 +814,19 @@ bool NativeWindowViews::HasShadow() {
       != wm::ShadowElevation::NONE;
 }
 
+void NativeWindowViews::SetOpacity(const double opacity) {
+#if defined(OS_WIN)
+  if (!layered_) {
+    LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
+    ex_style |= WS_EX_LAYERED;
+    ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
+    layered_ = true;
+  }
+
+  ::SetLayeredWindowAttributes(GetAcceleratedWidget(), 0, opacity * 255, LWA_ALPHA);
+#endif
+}
+
 void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
 #if defined(OS_WIN)
   LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
@@ -821,6 +834,8 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
     ex_style |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
   else
     ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
+  if (layered_)
+    ex_style |= WS_EX_LAYERED;
   ::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
 
   // Forwarding is always disabled when not ignoring mouse messages.

+ 2 - 0
atom/browser/native_window_views.h

@@ -104,6 +104,7 @@ class NativeWindowViews : public NativeWindow,
   void SetBackgroundColor(const std::string& color_name) override;
   void SetHasShadow(bool has_shadow) override;
   bool HasShadow() override;
+  void SetOpacity(const double opacity) override;
   void SetIgnoreMouseEvents(bool ignore, bool forward) override;
   void SetContentProtection(bool enable) override;
   void SetFocusable(bool focusable) override;
@@ -274,6 +275,7 @@ class NativeWindowViews : public NativeWindow,
   static HHOOK mouse_hook_;
   bool forwarding_mouse_messages_ = false;
   HWND legacy_window_ = NULL;
+  bool layered_ = false;
 #endif
 
   // Handles unhandled keyboard messages coming back from the renderer process.

+ 3 - 0
atom/common/options_switches.cc

@@ -86,6 +86,9 @@ const char kBackgroundColor[] = "backgroundColor";
 // Whether the window should have a shadow.
 const char kHasShadow[] = "hasShadow";
 
+// Browser window opacity
+const char kOpacity[] = "opacity";
+
 // Whether the window can be activated.
 const char kFocusable[] = "focusable";
 

+ 1 - 0
atom/common/options_switches.h

@@ -48,6 +48,7 @@ extern const char kDisableAutoHideCursor[];
 extern const char kStandardWindow[];
 extern const char kBackgroundColor[];
 extern const char kHasShadow[];
+extern const char kOpacity[];
 extern const char kFocusable[];
 extern const char kWebPreferences[];
 extern const char kVibrancyType[];

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

@@ -795,6 +795,26 @@ describe('BrowserWindow module', function () {
     })
   })
 
+  describe('BrowserWindow.setOpacity(opacity)', function () {
+    it('make window with initial opacity', function () {
+      w.destroy()
+      w = new BrowserWindow({
+        show: false,
+        width: 400,
+        height: 400,
+        opacity: 0.5
+      })
+    })
+
+    it('allows setting the opacity', function () {
+      assert.doesNotThrow(function () {
+        w.setOpacity(0.0)
+        w.setOpacity(0.5)
+        w.setOpacity(1.0)
+      })
+    })
+  })
+
   describe('"useContentSize" option', function () {
     it('make window created with content size when used', function () {
       w.destroy()