34 | 34 |
#include <atlapp.h>
|
35 | 35 |
#include <atlgdi.h>
|
36 | 36 |
#include <atlmisc.h>
|
|
37 |
#include <winuser.h>
|
37 | 38 |
|
38 | 39 |
#include <algorithm>
|
39 | 40 |
#include <limits>
|
|
42 | 43 |
#include <vector>
|
43 | 44 |
|
44 | 45 |
#include "base/logging.h"
|
|
46 |
#include "base/system_util.h"
|
45 | 47 |
#include "base/util.h"
|
46 | 48 |
#include "base/win_util.h"
|
47 | 49 |
#include "protocol/renderer_command.pb.h"
|
|
660 | 662 |
class NativeWindowPositionAPI : public WindowPositionInterface {
|
661 | 663 |
public:
|
662 | 664 |
NativeWindowPositionAPI()
|
663 | |
: logical_to_physical_point_(GetLogicalToPhysicalPoint()) {
|
|
665 |
: logical_to_physical_point_for_per_monitor_dpi_(
|
|
666 |
GetLogicalToPhysicalPointForPerMonitorDPI()) {
|
664 | 667 |
}
|
665 | 668 |
|
666 | 669 |
virtual ~NativeWindowPositionAPI() {}
|
|
675 | 678 |
if (!::IsWindow(window_handle)) {
|
676 | 679 |
return false;
|
677 | 680 |
}
|
678 | |
if (logical_to_physical_point_ == NULL) {
|
679 | |
// In Windows XP, LogicalToPhysicalPoint API is not available.
|
680 | |
// In this case, we simply returns the specified coordinate and returns
|
681 | |
// true.
|
682 | |
*physical_coordinate = logical_coordinate;
|
683 | |
return true;
|
684 | |
}
|
|
681 |
|
685 | 682 |
// The attached window is likely to be a child window but only root
|
686 | 683 |
// windows are fully supported by LogicalToPhysicalPoint API. Using
|
687 | 684 |
// root window handle instead of target window handle is likely to make
|
|
699 | 696 |
// coordinates to a DPI-aware process and convert them to physical screen
|
700 | 697 |
// coordinates by LogicalToPhysicalPoint API.
|
701 | 698 |
*physical_coordinate = logical_coordinate;
|
702 | |
return logical_to_physical_point_(root_window_handle,
|
703 | |
physical_coordinate) != FALSE;
|
|
699 |
|
|
700 |
// Despite its name, LogicalToPhysicalPoint API no longer converts
|
|
701 |
// coordinates on Windows 8.1 and later. We must use
|
|
702 |
// LogicalToPhysicalPointForPerMonitorDPI API instead when it is available.
|
|
703 |
// See http://go.microsoft.com/fwlink/?LinkID=307061
|
|
704 |
if (SystemUtil::IsWindows8_1OrLater()) {
|
|
705 |
if (logical_to_physical_point_for_per_monitor_dpi_ == nullptr) {
|
|
706 |
return false;
|
|
707 |
}
|
|
708 |
return logical_to_physical_point_for_per_monitor_dpi_(
|
|
709 |
root_window_handle, physical_coordinate) != FALSE;
|
|
710 |
}
|
|
711 |
// On Windows 8 and prior, it's OK to rely on LogicalToPhysicalPoint API.
|
|
712 |
return ::LogicalToPhysicalPoint(
|
|
713 |
root_window_handle, physical_coordinate) != FALSE;
|
704 | 714 |
}
|
705 | 715 |
|
706 | 716 |
// This method is not const to implement Win32WindowInterface.
|
|
748 | 758 |
}
|
749 | 759 |
|
750 | 760 |
private:
|
751 | |
typedef BOOL (WINAPI *FPLogicalToPhysicalPoint)(HWND window_handle,
|
752 | |
POINT *point);
|
753 | |
static FPLogicalToPhysicalPoint GetLogicalToPhysicalPoint() {
|
754 | |
// LogicalToPhysicalPoint API is available in Vista or later.
|
|
761 |
typedef BOOL (WINAPI *LogicalToPhysicalPointForPerMonitorDPIFunc)(
|
|
762 |
HWND window_handle, POINT *point);
|
|
763 |
static LogicalToPhysicalPointForPerMonitorDPIFunc
|
|
764 |
GetLogicalToPhysicalPointForPerMonitorDPI() {
|
|
765 |
// LogicalToPhysicalPointForPerMonitorDPI API is available on Windows 8.1
|
|
766 |
// and later.
|
|
767 |
if (!SystemUtil::IsWindows8_1OrLater()) {
|
|
768 |
return nullptr;
|
|
769 |
}
|
|
770 |
|
755 | 771 |
const HMODULE module = WinUtil::GetSystemModuleHandle(L"user32.dll");
|
756 | 772 |
if (module == nullptr) {
|
757 | 773 |
return nullptr;
|
758 | 774 |
}
|
759 | |
// Despite its name, LogicalToPhysicalPoint API no longer converts
|
760 | |
// coordinates on Windows 8.1 and later. We must use
|
761 | |
// LogicalToPhysicalPointForPerMonitorDPI API instead when it is available.
|
762 | |
// See http://go.microsoft.com/fwlink/?LinkID=307061
|
763 | |
void *function = ::GetProcAddress(
|
764 | |
module, "LogicalToPhysicalPointForPerMonitorDPI");
|
765 | |
if (function == nullptr) {
|
766 | |
// When LogicalToPhysicalPointForPerMonitorDPI API does not exist but
|
767 | |
// LogicalToPhysicalPoint API exists, LogicalToPhysicalPoint works fine.
|
768 | |
// This is the case on Windows Vista, Windows 7 and Windows 8.
|
769 | |
function = ::GetProcAddress(module, "LogicalToPhysicalPoint");
|
770 | |
if (function == nullptr) {
|
771 | |
return nullptr;
|
772 | |
}
|
773 | |
}
|
774 | |
return reinterpret_cast<FPLogicalToPhysicalPoint>(function);
|
775 | |
}
|
776 | |
|
777 | |
FPLogicalToPhysicalPoint logical_to_physical_point_;
|
|
775 |
return reinterpret_cast<LogicalToPhysicalPointForPerMonitorDPIFunc>(
|
|
776 |
::GetProcAddress(module, "LogicalToPhysicalPointForPerMonitorDPI"));
|
|
777 |
}
|
|
778 |
|
|
779 |
const LogicalToPhysicalPointForPerMonitorDPIFunc
|
|
780 |
logical_to_physical_point_for_per_monitor_dpi_;
|
778 | 781 |
|
779 | 782 |
DISALLOW_COPY_AND_ASSIGN(NativeWindowPositionAPI);
|
780 | 783 |
};
|