diff options
Diffstat (limited to 'chrome/browser/window_clipping_info.cc')
-rw-r--r-- | chrome/browser/window_clipping_info.cc | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/chrome/browser/window_clipping_info.cc b/chrome/browser/window_clipping_info.cc new file mode 100644 index 0000000..70a2262 --- /dev/null +++ b/chrome/browser/window_clipping_info.cc @@ -0,0 +1,189 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/window_clipping_info.h" + +#define DEBUG_WINDOW_CLIPPING_INFO 0 + +WindowClippingInfo::WindowClippingInfo(HWND aWindow, + HWND ignore_wnd) : hwnd_(aWindow), + ignore_(ignore_wnd), + rgn_(NULL) { + ::GetWindowRect(hwnd_, &hwnd_rect_); + ComputeScreenClipping(); + ComputeWindowsClipping(); + if (rgn_) { + ::OffsetRgn(rgn_, -hwnd_rect_.left, -hwnd_rect_.top); +#if DEBUG_WINDOW_CLIPPING_INFO + RECT r; + ::GetRgnBox(rgn_, &r); + LOG(INFO) << "Window clip rect is (" << r.left << ", " << r.top << ", " + << r.right << ", " << r.bottom << ")"; +#endif + } +} + +WindowClippingInfo::~WindowClippingInfo() { + if (rgn_) { + DeleteObject(rgn_); + } +} + +HRGN WindowClippingInfo::GetClippedRegion() const { + return rgn_; +} + +BOOL WindowClippingInfo::IsClipped() const { + if (rgn_ == NULL) { + return FALSE; + } else { + CRect r; + ::GetRgnBox(rgn_, &r); + if (r.Width() > 0 && r.Height() > 0) { + return TRUE; + } else { + return FALSE; + } + } +} + +HRGN WindowClippingInfo::CombineRegions(HRGN existing, HRGN additional) const { + if (existing == NULL) { + return additional; + } else { + HRGN new_dest = CreateRectRgn(0, 0, 0, 0); + ::CombineRgn(new_dest, existing, additional, RGN_OR); + DeleteObject(existing); + DeleteObject(additional); + return new_dest; + } +} + +void WindowClippingInfo::ComputeScreenClipping() { + int screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); + int screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); + CRect c; + + if (hwnd_rect_.left < 0) { + c.left = 0; + c.right = -hwnd_rect_.left; + c.top = 0; + c.bottom = hwnd_rect_.Height(); + rgn_ = CombineRegions(rgn_, + CreateRectRgn(c.left, c.top, c.right, c.bottom)); + } + + if (hwnd_rect_.top < 0) { + c.left = 0; + c.right = hwnd_rect_.Width(); + c.top = 0; + c.bottom = -hwnd_rect_.top; + rgn_ = CombineRegions(rgn_, + CreateRectRgn(c.left, c.top, c.right, c.bottom)); + } + + if (hwnd_rect_.right > screen_width) { + c.left = screen_width - hwnd_rect_.left; + c.right = hwnd_rect_.right - screen_width + c.left; + c.top = 0; + c.bottom = hwnd_rect_.Height(); + rgn_ = CombineRegions(rgn_, + CreateRectRgn(c.left, c.top, c.right, c.bottom)); + } + + if (hwnd_rect_.bottom > screen_height) { + c.left = 0; + c.right = hwnd_rect_.Width(); + c.top = screen_height - hwnd_rect_.top; + c.bottom = hwnd_rect_.bottom - screen_height + c.top; + rgn_ = CombineRegions(rgn_, + CreateRectRgn(c.left, c.top, c.right, c.bottom)); + } + + if (rgn_) { + // Convert the region in screen coordinate system to be compatible with + // the the windows clipping regions + ::OffsetRgn(rgn_, hwnd_rect_.left, hwnd_rect_.top); +#if DEBUG_WINDOW_CLIPPING_INFO + RECT cr; + ::GetRgnBox(rgn_, &cr); + LOG(INFO) << "Screen Clip is (" << cr.left << ", " << cr.top << ", " << + cr.right << ", " << cr.bottom << ")"; +#endif + } else { +#if DEBUG_WINDOW_CLIPPING_INFO + LOG(INFO) << "Screen Clip is null"; +#endif + } +} + + +// WindowEnumProc is called for every top level windows until we +// return FALSE or all top level windows have been enumerated. +// +// Windows are ordered per Z-Order with higher level windows first and +// lower level windows last. +// +//static +BOOL CALLBACK WindowClippingInfo::WindowEnumProc(HWND hwnd, LPARAM lParam) { + WindowClippingInfo* wci = + reinterpret_cast<WindowClippingInfo*>(lParam); + + if (hwnd == wci->ignore_) { + return TRUE; + } + + if (hwnd == wci->hwnd_) { + // We have enumerated all the windows above us so we are done + return FALSE; + } + + if (::IsWindowVisible(hwnd)) { + RECT r; + ::GetWindowRect(hwnd, &r); + RECT intersection; + if (::IntersectRect(&intersection, &r, &wci->hwnd_rect_)) { + HRGN rgn = CreateRectRgn(intersection.left, + intersection.top, + intersection.right, + intersection.bottom); + if (wci->rgn_ == NULL) { + wci->rgn_ = rgn; + } else { + ::CombineRgn(wci->rgn_, wci->rgn_, rgn, RGN_OR); + ::DeleteObject(rgn); + } + } + } + return TRUE; +} + +void WindowClippingInfo::ComputeWindowsClipping() { + ::EnumWindows(WindowEnumProc, reinterpret_cast<LPARAM>(this)); +} |