blob: 2f318a25093d22ff288418d628234d39fdc92062 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gfx/x/property_cache.h"
#include <limits>
#include "base/check_op.h"
#include "ui/gfx/x/event.h"
#include "ui/gfx/x/xproto.h"
namespace x11 {
PropertyCache::PropertyCache(Connection* connection,
Window window,
const std::vector<Atom>& properties)
: connection_(connection),
window_(window),
event_selector_(window_, EventMask::PropertyChange) {
connection_->AddEventObserver(this);
std::vector<std::pair<Atom, PropertyValue>> mem(properties.size());
for (size_t i = 0; i < properties.size(); i++) {
mem[i].first = properties[i];
FetchProperty(properties[i], &mem[i].second);
}
properties_ = base::flat_map<Atom, PropertyValue>(std::move(mem));
}
PropertyCache::~PropertyCache() {
connection_->RemoveEventObserver(this);
}
const GetPropertyResponse& PropertyCache::Get(Atom atom) {
auto it = properties_.find(atom);
DCHECK(it != properties_.end());
if (!it->second.response.has_value())
it->second.future.Wait();
DCHECK(it->second.response.has_value());
return it->second.response.value();
}
void PropertyCache::OnEvent(const Event& xev) {
auto* prop = xev.As<PropertyNotifyEvent>();
if (!prop)
return;
if (prop->window != window_)
return;
auto it = properties_.find(prop->atom);
if (it == properties_.end())
return;
if (prop->state == Property::NewValue) {
FetchProperty(it->first, &it->second);
} else {
DCHECK_EQ(prop->state, Property::Delete);
// When the property is deleted, a GetPropertyRequest will result in a
// zeroed GetPropertyReply, so set the reply state now to avoid making an
// unnecessary request.
it->second.response =
GetPropertyResponse{std::make_unique<GetPropertyReply>(), nullptr};
}
}
void PropertyCache::FetchProperty(Atom property, PropertyValue* value) {
value->future = connection_->GetProperty({
.window = window_,
.property = property,
.long_length = std::numeric_limits<uint32_t>::max(),
});
value->future.OnResponse(base::BindOnce(&PropertyCache::OnGetPropertyResponse,
weak_factory_.GetWeakPtr(), value));
}
void PropertyCache::OnGetPropertyResponse(PropertyValue* value,
GetPropertyResponse response) {
value->response = std::move(response);
}
PropertyCache::PropertyValue::PropertyValue() = default;
PropertyCache::PropertyValue::PropertyValue(PropertyValue&&) = default;
PropertyCache::PropertyValue& PropertyCache::PropertyValue::operator=(
PropertyValue&&) = default;
PropertyCache::PropertyValue::~PropertyValue() = default;
} // namespace x11