| // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef __PLATFORM_WINDOW_MANAGER_UTIL_H__ |
| #define __PLATFORM_WINDOW_MANAGER_UTIL_H__ |
| |
| #include <ctime> |
| #include <list> |
| #include <map> |
| #include <sys/time.h> |
| |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| #include "base/string_util.h" |
| |
| typedef unsigned int uint; |
| |
| namespace chromeos { |
| |
| // Stacker maintains an ordering of objects (e.g. windows) in which changes |
| // can be made in faster-than-linear time. |
| template<class T> |
| class Stacker { |
| public: |
| Stacker() {} |
| |
| // Get the (top-to-bottom) ordered list of items. |
| const std::list<T>& items() const { return items_; } |
| |
| // Has a particular item been registered? |
| bool Contains(T item) const { |
| return (index_.find(item) != index_.end()); |
| } |
| |
| // Get an item's 0-based position in the stack, or -1 if it isn't |
| // present. Slow but useful for testing. |
| int GetIndex(T item) const { |
| int i = 0; |
| for (typename std::list<T>::const_iterator it = items_.begin(); |
| it != items_.end(); ++it, ++i) { |
| if (*it == item) |
| return i; |
| } |
| return -1; |
| } |
| |
| // Get the item under 'item' on the stack, or NULL if 'item' is on the |
| // bottom of the stack. |
| const T* GetUnder(T item) const { |
| typename IteratorMap::const_iterator map_it = index_.find(item); |
| if (map_it == index_.end()) { |
| LOG(WARNING) << "Got request for item under not-present item " << item; |
| return NULL; |
| } |
| typename std::list<T>::iterator list_it = map_it->second; |
| list_it++; |
| if (list_it == items_.end()) { |
| return NULL; |
| } |
| return &(*list_it); |
| } |
| |
| // Add an item on the top of the stack. |
| void AddOnTop(T item) { |
| if (Contains(item)) { |
| LOG(WARNING) << "Ignoring request to add already-present item " |
| << item << " on top"; |
| return; |
| } |
| items_.push_front(item); |
| index_.insert(make_pair(item, items_.begin())); |
| } |
| |
| // Add an item on the bottom of the stack. |
| void AddOnBottom(T item) { |
| if (Contains(item)) { |
| LOG(WARNING) << "Ignoring request to add already-present item " |
| << item << " on bottom"; |
| return; |
| } |
| items_.push_back(item); |
| index_.insert(make_pair(item, --(items_.end()))); |
| } |
| |
| // Add 'item' above 'other_item'. 'other_item' must already exist on the |
| // stack. |
| void AddAbove(T item, T other_item) { |
| if (Contains(item)) { |
| LOG(WARNING) << "Ignoring request to add already-present item " |
| << item << " above item " << other_item; |
| return; |
| } |
| typename IteratorMap::iterator other_it = index_.find(other_item); |
| if (other_it == index_.end()) { |
| LOG(WARNING) << "Ignoring request to add item " << item |
| << " above not-present item " << other_item; |
| return; |
| } |
| typename std::list<T>::iterator new_it = items_.insert(other_it->second, |
| item); |
| index_.insert(make_pair(item, new_it)); |
| } |
| |
| // Add 'item' below 'other_item'. 'other_item' must already exist on the |
| // stack. |
| void AddBelow(T item, T other_item) { |
| if (Contains(item)) { |
| LOG(WARNING) << "Ignoring request to add already-present item " |
| << item << " below item " << other_item; |
| return; |
| } |
| typename IteratorMap::iterator other_it = index_.find(other_item); |
| if (other_it == index_.end()) { |
| LOG(WARNING) << "Ignoring request to add item " << item |
| << " below not-present item " << other_item; |
| return; |
| } |
| // Lists don't support operator+ or operator-, so we need to use ++. |
| // Make a copy of the iterator before doing this so that we don't screw |
| // up the previous value in the map. |
| typename std::list<T>::iterator new_it = other_it->second; |
| typename std::list<T>::iterator it = items_.insert(++new_it, item); |
| index_.insert(make_pair(item, it)); |
| } |
| |
| // Remove an item from the stack. |
| void Remove(T item) { |
| typename IteratorMap::iterator it = index_.find(item); |
| if (it == index_.end()) { |
| LOG(WARNING) << "Ignoring request to remove not-present item " << item; |
| return; |
| } |
| items_.erase(it->second); |
| index_.erase(it); |
| } |
| |
| private: |
| // Items stacked from top to bottom. |
| std::list<T> items_; |
| |
| typedef std::map<T, typename std::list<T>::iterator> IteratorMap; |
| |
| // Index into 'items_'. |
| IteratorMap index_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Stacker); |
| }; |
| |
| |
| // ByteMap unions rectangles into a 2-D array of bytes. That's it. :-P |
| class ByteMap { |
| public: |
| ByteMap(int width, int height); |
| ~ByteMap(); |
| |
| int width() const { return width_; } |
| int height() const { return height_; } |
| const unsigned char* bytes() const { return bytes_; } |
| |
| // Copy the bytes from 'other', which must have the same dimensions as |
| // this map. |
| void Copy(const ByteMap& other); |
| |
| // Set every byte to 'value'. |
| void Clear(unsigned char value); |
| |
| // Set the bytes covered by the passed-in rectangle. |
| void SetRectangle(int rect_x, int rect_y, |
| int rect_width, int rect_height, |
| unsigned char value); |
| |
| private: |
| int width_; |
| int height_; |
| unsigned char* bytes_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ByteMap); |
| }; |
| |
| |
| template<class K, class V> |
| V FindWithDefault(const std::map<K, V>& the_map, const K& key, const V& def) { |
| typename std::map<K, V>::const_iterator it = the_map.find(key); |
| if (it == the_map.end()) { |
| return def; |
| } |
| return it->second; |
| } |
| |
| |
| // Get the number of seconds since the epoch. |
| double GetCurrentTime(); |
| |
| |
| // Fill 'tv' with the time from 'time'. |
| void FillTimeval(double time, struct timeval* tv); |
| |
| |
| // Helper method to convert an XID into a hex string. |
| static std::string XidStr(unsigned long xid) { |
| return StringPrintf("0x%lx", xid); |
| } |
| |
| } // namespace chromeos |
| |
| #endif // __UTIL_H__ |