1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <test/bootstrapfixture.hxx>
21 
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/util/MeasureUnit.hpp>
24 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
25 #include <com/sun/star/awt/WindowAttribute.hpp>
26 #include <com/sun/star/awt/WindowDescriptor.hpp>
27 #include <com/sun/star/awt/XUnitConversion.hpp>
28 #include <com/sun/star/awt/XWindowPeer.hpp>
29 #include <com/sun/star/awt/XWindow.hpp>
30 
31 #ifdef _WIN32
32 #include <windows.h>
33 #endif
34 
35 using namespace ::com::sun::star;
36 
37 namespace
38 {
39 class ToolkitTest : public test::BootstrapFixture
40 {
41 public:
42     void testXUnitConversion();
43 
44     CPPUNIT_TEST_SUITE(ToolkitTest);
45     CPPUNIT_TEST(testXUnitConversion);
46     CPPUNIT_TEST_SUITE_END();
47 };
48 
49 /**
50  * Creates a floating XWindow on the given position and size.
51  * @return a floating XWindow
52  * @param X the X-Position of the floating XWindow
53  * @param Y the Y-Position of the floating XWindow
54  * @param width the width of the floating XWindow
55  * @param height the height of the floating XWindow
56  * @param xMSF the MultiServiceFactory
57  */
58 uno::Reference<awt::XWindowPeer>
createFloatingWindow(uno::Reference<lang::XMultiServiceFactory> const & xMSF,sal_Int32 const nX,sal_Int32 const nY,sal_Int32 const nWidth,sal_Int32 const nHeight)59 createFloatingWindow(uno::Reference<lang::XMultiServiceFactory> const& xMSF, sal_Int32 const nX,
60                      sal_Int32 const nY, sal_Int32 const nWidth, sal_Int32 const nHeight)
61 {
62     uno::Reference<awt::XToolkit> const xTk(xMSF->createInstance("com.sun.star.awt.Toolkit"),
63                                             uno::UNO_QUERY);
64 
65     awt::WindowDescriptor descriptor;
66     descriptor.Type = awt::WindowClass_TOP;
67     descriptor.WindowServiceName = "modelessdialog";
68     descriptor.ParentIndex = -1;
69     descriptor.Bounds.X = nX;
70     descriptor.Bounds.Y = nY;
71     descriptor.Bounds.Width = nWidth;
72     descriptor.Bounds.Height = nHeight;
73     descriptor.WindowAttributes
74         = (awt::WindowAttribute::BORDER + awt::WindowAttribute::MOVEABLE
75            + awt::WindowAttribute::SIZEABLE + awt::WindowAttribute::CLOSEABLE
76            + awt::VclWindowPeerAttribute::CLIPCHILDREN);
77 
78     return xTk->createWindow(descriptor);
79 }
80 
81 /**
82  * Not really a check,
83  * only a simple test call to convertSizeToLogic(...) with different parameters
84  */
checkSize(uno::Reference<awt::XUnitConversion> const & xConv,awt::Size const & rSize,sal_Int16 const nMeasureUnit,OUString const & rUnit)85 void checkSize(uno::Reference<awt::XUnitConversion> const& xConv, awt::Size const& rSize,
86                sal_Int16 const nMeasureUnit, OUString const& rUnit)
87 {
88     awt::Size const aSizeIn = xConv->convertSizeToLogic(rSize, nMeasureUnit);
89     std::cerr << "Window size:\n";
90     std::cerr << "Width: " << aSizeIn.Width << " " << rUnit << "\n";
91     std::cerr << "Height: " << aSizeIn.Height << " " << rUnit << "\n";
92 }
93 
94 /**
95  * The real test function
96  * 2. try to create an empty window
97  * 3. try to convert the WindowPeer to an XWindow
98  * 4. try to resize and move the window to another position, so we get a well knowing position and size.
99  * 5. run some more tests
100  */
testXUnitConversion()101 void ToolkitTest::testXUnitConversion()
102 {
103 #ifdef _WIN32
104     HKEY hkey;
105     DWORD type;
106     DWORD data;
107     DWORD size(sizeof(data));
108     LONG ret = ::RegOpenKeyW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", &hkey);
109     if (ret == ERROR_SUCCESS)
110     {
111         ret = ::RegQueryValueExW(hkey, L"LogPixels", nullptr, &type,
112                                  reinterpret_cast<LPBYTE>(&data), &size);
113         if (ret == ERROR_SUCCESS && type == REG_DWORD && data != 96)
114         {
115             std::cerr << "non-default resolution, skipping textXUnitConversion\n";
116             return;
117         }
118     }
119 #endif
120 
121     // create a window
122     sal_Int32 x = 100;
123     sal_Int32 y = 100;
124     sal_Int32 width = 640;
125     sal_Int32 height = 480;
126     uno::Reference<awt::XWindowPeer> const xWindowPeer
127         = createFloatingWindow(getMultiServiceFactory(), x, y, width, height);
128     CPPUNIT_ASSERT(xWindowPeer.is());
129 
130     // resize and move the window to a well known position and size
131     uno::Reference<awt::XWindow> const xWindow(xWindowPeer, uno::UNO_QUERY);
132     CPPUNIT_ASSERT(xWindow.is());
133 
134     xWindow->setVisible(true);
135 
136     awt::Rectangle aRect = xWindow->getPosSize();
137     awt::Point aPoint(aRect.X, aRect.Y);
138     awt::Size aSize(aRect.Width, aRect.Height);
139 
140     std::cerr << "Window position and size in pixel:\n";
141     std::cerr << "X: " << aPoint.X << "\n";
142     std::cerr << "Y: " << aPoint.Y << "\n";
143     std::cerr << "Width: " << aSize.Width << "\n";
144     std::cerr << "Height: " << aSize.Height << "\n";
145 
146     CPPUNIT_ASSERT_EQUAL_MESSAGE("Window size wrong", width, aSize.Width);
147     CPPUNIT_ASSERT_EQUAL_MESSAGE("Window size wrong", height, aSize.Height);
148     CPPUNIT_ASSERT_EQUAL_MESSAGE("Window pos wrong", x, aPoint.X);
149     CPPUNIT_ASSERT_EQUAL_MESSAGE("Window pos wrong", y, aPoint.Y);
150 
151     uno::Reference<awt::XUnitConversion> const xConv(xWindowPeer, uno::UNO_QUERY);
152 
153     // try to get the position of the window in 1/100mm with the XUnitConversion method
154     awt::Point const aPointInMM_100TH
155         = xConv->convertPointToLogic(aPoint, util::MeasureUnit::MM_100TH);
156     std::cerr << "Window position:\n";
157     std::cerr << "X: " << aPointInMM_100TH.X << " 1/100mm\n";
158     std::cerr << "Y: " << aPointInMM_100TH.Y << " 1/100mm\n";
159 
160     // try to get the size of the window in 1/100mm with the XUnitConversion method
161     awt::Size const aSizeInMM_100TH = xConv->convertSizeToLogic(aSize, util::MeasureUnit::MM_100TH);
162     std::cerr << "Window size:\n";
163     std::cerr << "Width: " << aSizeInMM_100TH.Width << " 1/100mm\n";
164     std::cerr << "Height: " << aSizeInMM_100TH.Height << " 1/100mm\n";
165 
166     // try to get the size of the window in 1/10mm with the XUnitConversion method
167     awt::Size const aSizeInMM_10TH = xConv->convertSizeToLogic(aSize, util::MeasureUnit::MM_10TH);
168     std::cerr << "Window size:\n";
169     std::cerr << "Width: " << aSizeInMM_10TH.Width << " 1/10mm\n";
170     std::cerr << "Height: " << aSizeInMM_10TH.Height << " 1/10mm\n";
171 
172     // check the size with a delta which must be smaller a given difference
173     CPPUNIT_ASSERT_MESSAGE("Size.Width  not correct",
174                            std::abs(aSizeInMM_100TH.Width - aSizeInMM_10TH.Width * 10) < 10);
175     CPPUNIT_ASSERT_MESSAGE("Size.Height not correct",
176                            std::abs(aSizeInMM_100TH.Height - aSizeInMM_10TH.Height * 10) < 10);
177 
178     // new
179     checkSize(xConv, aSize, util::MeasureUnit::PIXEL, "pixel");
180     checkSize(xConv, aSize, util::MeasureUnit::APPFONT, "appfont");
181     checkSize(xConv, aSize, util::MeasureUnit::SYSFONT, "sysfont");
182 
183     // simply check some more parameters
184     checkSize(xConv, aSize, util::MeasureUnit::MM, "mm");
185     checkSize(xConv, aSize, util::MeasureUnit::CM, "cm");
186     checkSize(xConv, aSize, util::MeasureUnit::INCH_1000TH, "1/1000inch");
187     checkSize(xConv, aSize, util::MeasureUnit::INCH_100TH, "1/100inch");
188     checkSize(xConv, aSize, util::MeasureUnit::INCH_10TH, "1/10inch");
189     checkSize(xConv, aSize, util::MeasureUnit::INCH, "inch");
190     checkSize(xConv, aSize, util::MeasureUnit::POINT, "point");
191     checkSize(xConv, aSize, util::MeasureUnit::TWIP, "twip");
192 
193     // convert the 1/100mm window size back to pixel
194     awt::Size const aNewSize
195         = xConv->convertSizeToPixel(aSizeInMM_100TH, util::MeasureUnit::MM_100TH);
196     std::cerr << "Window size:\n";
197     std::cerr << "Width: " << aNewSize.Width << " pixel\n";
198     std::cerr << "Height: " << aNewSize.Height << " pixel\n";
199 
200     // assure the pixels are the same as we already know
201     CPPUNIT_ASSERT_MESSAGE("failed: Size from pixel to 1/100mm to pixel",
202                            aSize.Width == aNewSize.Width && aSize.Height == aNewSize.Height);
203 
204     // close the window.
205     xWindow->dispose();
206 }
207 
208 CPPUNIT_TEST_SUITE_REGISTRATION(ToolkitTest);
209 }
210 
211 CPPUNIT_PLUGIN_IMPLEMENT();
212 
213 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
214