/
window_state_watcher.cc
82 lines (71 loc) · 3.01 KB
/
window_state_watcher.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/ui/x/window_state_watcher.h"
#include <vector>
#include "ui/base/x/x11_util.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/xproto_util.h"
namespace electron {
WindowStateWatcher::WindowStateWatcher(NativeWindowViews* window)
: window_(window),
widget_(window->GetAcceleratedWidget()),
net_wm_state_atom_(x11::GetAtom("_NET_WM_STATE")),
net_wm_state_hidden_atom_(x11::GetAtom("_NET_WM_STATE_HIDDEN")),
net_wm_state_maximized_vert_atom_(
x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")),
net_wm_state_maximized_horz_atom_(
x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")),
net_wm_state_fullscreen_atom_(x11::GetAtom("_NET_WM_STATE_FULLSCREEN")),
was_minimized_(window_->IsMinimized()),
was_maximized_(window_->IsMaximized()) {
ui::X11EventSource::GetInstance()->connection()->AddEventObserver(this);
}
WindowStateWatcher::~WindowStateWatcher() {
ui::X11EventSource::GetInstance()->connection()->RemoveEventObserver(this);
}
void WindowStateWatcher::OnEvent(const x11::Event& x11_event) {
if (IsWindowStateEvent(x11_event)) {
std::vector<x11::Atom> wm_states;
if (GetArrayProperty(
static_cast<x11::Window>(window_->GetAcceleratedWidget()),
net_wm_state_atom_, &wm_states)) {
const auto props =
base::flat_set<x11::Atom>(std::begin(wm_states), std::end(wm_states));
const bool is_minimized = props.contains(net_wm_state_hidden_atom_);
const bool is_maximized =
props.contains(net_wm_state_maximized_vert_atom_) &&
props.contains(net_wm_state_maximized_horz_atom_);
const bool is_fullscreen = props.contains(net_wm_state_fullscreen_atom_);
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 "OnEvent"
// 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();
}
was_minimized_ = is_minimized;
was_maximized_ = is_maximized;
}
}
}
bool WindowStateWatcher::IsWindowStateEvent(const x11::Event& x11_event) const {
auto* property = x11_event.As<x11::PropertyNotifyEvent>();
return (property && property->atom == net_wm_state_atom_ &&
static_cast<uint32_t>(property->window) == widget_);
}
} // namespace electron