// Copyright (c) 2012 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/base/win/hwnd_subclass.h"

#include <algorithm>

#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/singleton.h"
#include "ui/gfx/win/dpi.h"
#include "ui/gfx/win/hwnd_util.h"

namespace {
const char kHWNDSubclassKey[] = "__UI_BASE_WIN_HWND_SUBCLASS_PROC__";

LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT message,
                         WPARAM w_param,
                         LPARAM l_param) {
  ui::HWNDSubclass* wrapped_wnd_proc =
      reinterpret_cast<ui::HWNDSubclass*>(
          ui::ViewProp::GetValue(hwnd, kHWNDSubclassKey));
  return wrapped_wnd_proc ? wrapped_wnd_proc->OnWndProc(hwnd,
                                                        message,
                                                        w_param,
                                                        l_param)
                          : DefWindowProc(hwnd, message, w_param, l_param);
}

WNDPROC GetCurrentWndProc(HWND target) {
  return reinterpret_cast<WNDPROC>(GetWindowLongPtr(target, GWLP_WNDPROC));
}

// Not defined before Win7
BOOL GetTouchInputInfoWrapper(HTOUCHINPUT handle, UINT count,
                              PTOUCHINPUT pointer, int size) {
  typedef BOOL(WINAPI *GetTouchInputInfoPtr)(HTOUCHINPUT, UINT,
                                             PTOUCHINPUT, int);
  GetTouchInputInfoPtr get_touch_input_info_func =
      reinterpret_cast<GetTouchInputInfoPtr>(
          GetProcAddress(GetModuleHandleA("user32.dll"), "GetTouchInputInfo"));
  if (get_touch_input_info_func)
    return get_touch_input_info_func(handle, count, pointer, size);
  return FALSE;
}

}  // namespace

namespace ui {

// Singleton factory that creates and manages the lifetime of all
// ui::HWNDSubclass objects.
class HWNDSubclass::HWNDSubclassFactory {
 public:
  static HWNDSubclassFactory* GetInstance() {
    return Singleton<HWNDSubclassFactory,
        LeakySingletonTraits<HWNDSubclassFactory> >::get();
  }

  // Returns a non-null HWNDSubclass corresponding to the HWND |target|. Creates
  // one if none exists. Retains ownership of the returned pointer.
  HWNDSubclass* GetHwndSubclassForTarget(HWND target) {
    DCHECK(target);
    HWNDSubclass* subclass = reinterpret_cast<HWNDSubclass*>(
        ui::ViewProp::GetValue(target, kHWNDSubclassKey));
    if (!subclass) {
      subclass = new ui::HWNDSubclass(target);
      hwnd_subclasses_.push_back(subclass);
    }
    return subclass;
  }

  const ScopedVector<HWNDSubclass>& hwnd_subclasses() {
    return hwnd_subclasses_;
  }

 private:
  friend struct DefaultSingletonTraits<HWNDSubclassFactory>;

  HWNDSubclassFactory() {}

  ScopedVector<HWNDSubclass> hwnd_subclasses_;

  DISALLOW_COPY_AND_ASSIGN(HWNDSubclassFactory);
};

// static
void HWNDSubclass::AddFilterToTarget(HWND target, HWNDMessageFilter* filter) {
  HWNDSubclassFactory::GetInstance()->GetHwndSubclassForTarget(
      target)->AddFilter(filter);
}

// static
void HWNDSubclass::RemoveFilterFromAllTargets(HWNDMessageFilter* filter) {
  HWNDSubclassFactory* factory = HWNDSubclassFactory::GetInstance();
  ScopedVector<ui::HWNDSubclass>::const_iterator it;
  for (it = factory->hwnd_subclasses().begin();
      it != factory->hwnd_subclasses().end(); ++it)
    (*it)->RemoveFilter(filter);
}

// static
HWNDSubclass* HWNDSubclass::GetHwndSubclassForTarget(HWND target) {
  return HWNDSubclassFactory::GetInstance()->GetHwndSubclassForTarget(target);
}

void HWNDSubclass::AddFilter(HWNDMessageFilter* filter) {
  DCHECK(filter);
  if (std::find(filters_.begin(), filters_.end(), filter) == filters_.end())
    filters_.push_back(filter);
}

void HWNDSubclass::RemoveFilter(HWNDMessageFilter* filter) {
  std::vector<HWNDMessageFilter*>::iterator it =
      std::find(filters_.begin(), filters_.end(), filter);
  if (it != filters_.end())
    filters_.erase(it);
}

HWNDSubclass::HWNDSubclass(HWND target)
    : target_(target),
      original_wnd_proc_(GetCurrentWndProc(target)),
      prop_(target, kHWNDSubclassKey, this) {
  gfx::SetWindowProc(target_, &WndProc);
}

HWNDSubclass::~HWNDSubclass() {
}

LRESULT HWNDSubclass::OnWndProc(HWND hwnd,
                                UINT message,
                                WPARAM w_param,
                                LPARAM l_param) {

  // Touch messages are always passed in screen coordinates. If the OS is
  // scaled, but the app is not DPI aware, then then WM_TOUCH might be
  // intended for a different window.
  if (message == WM_TOUCH) {
    TOUCHINPUT point;

    if (GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(l_param), 1,
                                 &point, sizeof(TOUCHINPUT))) {
      POINT touch_location = {TOUCH_COORD_TO_PIXEL(point.x),
                              TOUCH_COORD_TO_PIXEL(point.y)};
      HWND actual_target = WindowFromPoint(touch_location);
      if (actual_target != hwnd) {
        return SendMessage(actual_target, message, w_param, l_param);
      }
    }
  }

  for (std::vector<HWNDMessageFilter*>::iterator it = filters_.begin();
      it != filters_.end(); ++it) {
    LRESULT l_result = 0;
    if ((*it)->FilterMessage(hwnd, message, w_param, l_param, &l_result))
      return l_result;
  }

  // In most cases, |original_wnd_proc_| will take care of calling
  // DefWindowProc.
  return CallWindowProc(original_wnd_proc_, hwnd, message, w_param, l_param);
}

HWNDMessageFilter::~HWNDMessageFilter() {
  HWNDSubclass::RemoveFilterFromAllTargets(this);
}

}  // namespace ui
