Browse Source

x11: Implement window state events

Cheng Zhao 10 years ago
parent
commit
b77e6c369a

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

@@ -112,6 +112,30 @@ void Window::OnWindowFocus() {
   Emit("focus");
 }
 
+void Window::OnWindowMaximize() {
+  Emit("maximize");
+}
+
+void Window::OnWindowUnmaximize() {
+  Emit("unmaximize");
+}
+
+void Window::OnWindowMinimize() {
+  Emit("minimize");
+}
+
+void Window::OnWindowRestore() {
+  Emit("restore");
+}
+
+void Window::OnWindowEnterFullScreen() {
+  Emit("enter-full-screen");
+}
+
+void Window::OnWindowLeaveFullScreen() {
+  Emit("leave-full-screen");
+}
+
 void Window::OnRendererUnresponsive() {
   Emit("unresponsive");
 }

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

@@ -43,7 +43,7 @@ class Window : public mate::EventEmitter,
   explicit Window(const mate::Dictionary& options);
   virtual ~Window();
 
-  // Implementations of NativeWindowObserver:
+  // NativeWindowObserver:
   void OnPageTitleUpdated(bool* prevent_default,
                           const std::string& title) override;
   void WillCreatePopupWindow(const base::string16& frame_name,
@@ -54,6 +54,12 @@ class Window : public mate::EventEmitter,
   void OnWindowClosed() override;
   void OnWindowBlur() override;
   void OnWindowFocus() override;
+  void OnWindowMaximize() override;
+  void OnWindowUnmaximize() override;
+  void OnWindowMinimize() override;
+  void OnWindowRestore() override;
+  void OnWindowEnterFullScreen() override;
+  void OnWindowLeaveFullScreen() override;
   void OnRendererUnresponsive() override;
   void OnRendererResponsive() override;
 

+ 26 - 0
atom/browser/native_window.cc

@@ -466,6 +466,32 @@ void NativeWindow::NotifyWindowFocus() {
   FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowFocus());
 }
 
+void NativeWindow::NotifyWindowMaximize() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowMaximize());
+}
+
+void NativeWindow::NotifyWindowUnmaximize() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowUnmaximize());
+}
+
+void NativeWindow::NotifyWindowMinimize() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowMinimize());
+}
+
+void NativeWindow::NotifyWindowRestore() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowRestore());
+}
+
+void NativeWindow::NotifyWindowEnterFullScreen() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
+                    OnWindowEnterFullScreen());
+}
+
+void NativeWindow::NotifyWindowLeaveFullScreen() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
+                    OnWindowLeaveFullScreen());
+}
+
 bool NativeWindow::ShouldCreateWebContents(
     content::WebContents* web_contents,
     int route_id,

+ 6 - 0
atom/browser/native_window.h

@@ -192,6 +192,12 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
   void NotifyWindowClosed();
   void NotifyWindowBlur();
   void NotifyWindowFocus();
+  void NotifyWindowMaximize();
+  void NotifyWindowUnmaximize();
+  void NotifyWindowMinimize();
+  void NotifyWindowRestore();
+  void NotifyWindowEnterFullScreen();
+  void NotifyWindowLeaveFullScreen();
 
   void AddObserver(NativeWindowObserver* obs) {
     observers_.AddObserver(obs);

+ 8 - 0
atom/browser/native_window_observer.h

@@ -39,6 +39,14 @@ class NativeWindowObserver {
   // Called when window gains focus.
   virtual void OnWindowFocus() {}
 
+  // Called when window state changed.
+  virtual void OnWindowMaximize() {}
+  virtual void OnWindowUnmaximize() {}
+  virtual void OnWindowMinimize() {}
+  virtual void OnWindowRestore() {}
+  virtual void OnWindowEnterFullScreen() {}
+  virtual void OnWindowLeaveFullScreen() {}
+
   // Called when renderer is hung.
   virtual void OnRendererUnresponsive() {}
 

+ 60 - 2
atom/browser/ui/views/window_state_watcher.cc

@@ -4,13 +4,31 @@
 
 #include "atom/browser/ui/views/window_state_watcher.h"
 
+#if defined(USE_X11)
+#include <X11/Xlib.h>
+#endif
+
 #include "ui/events/platform/platform_event_source.h"
 
 namespace atom {
 
+namespace {
+
+const char* kAtomsToCache[] = {
+  "_NET_WM_STATE",
+  NULL,
+};
+
+}  // namespace
+
 WindowStateWatcher::WindowStateWatcher(NativeWindowViews* window)
     : window_(window),
-      widget_(window->GetAcceleratedWidget()) {
+      widget_(window->GetAcceleratedWidget()),
+#if defined(USE_X11)
+      atom_cache_(gfx::GetXDisplay(), kAtomsToCache),
+#endif
+      was_minimized_(false),
+      was_maximized_(false) {
   ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
 }
 
@@ -19,10 +37,50 @@ WindowStateWatcher::~WindowStateWatcher() {
 }
 
 void WindowStateWatcher::WillProcessEvent(const ui::PlatformEvent& event) {
-  LOG(ERROR) << "WillProcessEvent";
+  if (IsWindowStateEvent(event)) {
+    was_minimized_ = window_->IsMinimized();
+    was_maximized_ = window_->IsMaximized();
+  }
 }
 
 void WindowStateWatcher::DidProcessEvent(const ui::PlatformEvent& event) {
+  if (IsWindowStateEvent(event)) {
+    bool is_minimized = window_->IsMinimized();
+    bool is_maximized = window_->IsMaximized();
+    bool is_fullscreen = window_->IsFullscreen();
+    if (is_minimized != was_minimized_) {
+      if (is_minimized)
+        window_->NotifyWindowMinimize();
+      else
+        window_->NotifyWindowRestore();
+    } else if (is_maximized != was_maximized_) {
+      if (is_maximized)
+        window_->NotifyWindowMaximize();
+      else
+        window_->NotifyWindowUnmaximize();
+    } else {
+      // If this is neither a "maximize" or "minimize" event, then we think it
+      // is a "fullscreen" event.
+      // The "IsFullscreen()" becomes true immediately before "WillProcessEvent"
+      // is called, so we can not handle this like "maximize" and "minimize" by
+      // watching whether they have changed.
+      if (is_fullscreen)
+        window_->NotifyWindowEnterFullScreen();
+      else
+        window_->NotifyWindowLeaveFullScreen();
+    }
+  }
+}
+
+bool WindowStateWatcher::IsWindowStateEvent(const ui::PlatformEvent& event) {
+#if defined(USE_X11)
+  ::Atom changed_atom = event->xproperty.atom;
+  return (changed_atom == atom_cache_.GetAtom("_NET_WM_STATE") &&
+          event->type == PropertyNotify &&
+          event->xproperty.window == widget_);
+#else
+  return false;
+#endif
 }
 
 }  // namespace atom

+ 13 - 0
atom/browser/ui/views/window_state_watcher.h

@@ -6,6 +6,10 @@
 
 #include "atom/browser/native_window_views.h"
 
+#if defined(USE_X11)
+#include "ui/gfx/x/x11_atom_cache.h"
+#endif
+
 namespace atom {
 
 class WindowStateWatcher : public ui::PlatformEventObserver {
@@ -19,9 +23,18 @@ class WindowStateWatcher : public ui::PlatformEventObserver {
   void DidProcessEvent(const ui::PlatformEvent& event) override;
 
  private:
+  bool IsWindowStateEvent(const ui::PlatformEvent& event);
+
   NativeWindowViews* window_;
   gfx::AcceleratedWidget widget_;
 
+#if defined(USE_X11)
+  ui::X11AtomCache atom_cache_;
+#endif
+
+  bool was_minimized_;
+  bool was_maximized_;
+
   DISALLOW_COPY_AND_ASSIGN(WindowStateWatcher);
 };