1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include "rtl/ustrbuf.hxx"
24 #include "tools/debug.hxx"
26 #include "vcl/window.hxx"
28 #include "win/salsys.h"
29 #include "win/salframe.h"
30 #include "win/salinst.h"
31 #include "win/saldata.hxx"
35 #include <boost/unordered_map.hpp>
37 SalSystem
* WinSalInstance::CreateSalSystem()
39 return new WinSalSystem();
42 WinSalSystem::~WinSalSystem()
46 // -----------------------------------------------------------------------
48 static BOOL CALLBACK
ImplEnumMonitorProc( HMONITOR hMonitor
,
53 WinSalSystem
* pSys
= reinterpret_cast<WinSalSystem
*>(dwData
);
54 return pSys
->handleMonitorCallback( reinterpret_cast<sal_IntPtr
>(hMonitor
),
55 reinterpret_cast<sal_IntPtr
>(hDC
),
56 reinterpret_cast<sal_IntPtr
>(lpRect
) );
59 sal_Bool
WinSalSystem::handleMonitorCallback( sal_IntPtr hMonitor
, sal_IntPtr
, sal_IntPtr
)
62 aInfo
.cbSize
= sizeof( aInfo
);
63 if( GetMonitorInfoW( reinterpret_cast<HMONITOR
>(hMonitor
), &aInfo
) )
65 aInfo
.szDevice
[CCHDEVICENAME
-1] = 0;
66 OUString
aDeviceName( reinterpret_cast<const sal_Unicode
*>(aInfo
.szDevice
) );
67 std::map
< OUString
, unsigned int >::const_iterator it
=
68 m_aDeviceNameToMonitor
.find( aDeviceName
);
69 if( it
!= m_aDeviceNameToMonitor
.end() )
71 DisplayMonitor
& rMon( m_aMonitors
[ it
->second
] );
72 rMon
.m_aArea
= Rectangle( Point( aInfo
.rcMonitor
.left
,
73 aInfo
.rcMonitor
.top
),
74 Size( aInfo
.rcMonitor
.right
- aInfo
.rcMonitor
.left
,
75 aInfo
.rcMonitor
.bottom
- aInfo
.rcMonitor
.top
) );
76 rMon
.m_aWorkArea
= Rectangle( Point( aInfo
.rcWork
.left
,
78 Size( aInfo
.rcWork
.right
- aInfo
.rcWork
.left
,
79 aInfo
.rcWork
.bottom
- aInfo
.rcWork
.top
) );
80 if( (aInfo
.dwFlags
& MONITORINFOF_PRIMARY
) != 0 )
81 m_nPrimary
= it
->second
;
87 void WinSalSystem::clearMonitors()
93 bool WinSalSystem::initMonitors()
95 if( m_aMonitors
.size() > 0 )
98 int nMonitors
= GetSystemMetrics( SM_CMONITORS
);
101 int w
= GetSystemMetrics( SM_CXSCREEN
);
102 int h
= GetSystemMetrics( SM_CYSCREEN
);
103 m_aMonitors
.push_back( DisplayMonitor( OUString(),
105 Rectangle( Point(), Size( w
, h
) ),
106 Rectangle( Point(), Size( w
, h
) ),
108 m_aDeviceNameToMonitor
[ OUString() ] = 0;
111 if( SystemParametersInfo( SPI_GETWORKAREA
, 0, &aWorkRect
, 0 ) )
112 m_aMonitors
.back().m_aWorkArea
= Rectangle( aWorkRect
.left
, aWorkRect
.top
,
113 aWorkRect
.right
, aWorkRect
.bottom
);
117 DISPLAY_DEVICEW aDev
;
118 aDev
.cb
= sizeof( aDev
);
120 boost::unordered_map
< OUString
, int, OUStringHash
> aDeviceStringCount
;
121 while( EnumDisplayDevicesW( NULL
, nDevice
++, &aDev
, 0 ) )
123 if( (aDev
.StateFlags
& DISPLAY_DEVICE_ACTIVE
)
124 && !(aDev
.StateFlags
& DISPLAY_DEVICE_MIRRORING_DRIVER
) ) // sort out non/disabled monitors
126 aDev
.DeviceName
[31] = 0;
127 aDev
.DeviceString
[127] = 0;
128 OUString
aDeviceName( reinterpret_cast<const sal_Unicode
*>(aDev
.DeviceName
) );
129 OUString
aDeviceString( reinterpret_cast<const sal_Unicode
*>(aDev
.DeviceString
) );
130 if( aDeviceStringCount
.find( aDeviceString
) == aDeviceStringCount
.end() )
131 aDeviceStringCount
[ aDeviceString
] = 1;
133 aDeviceStringCount
[ aDeviceString
]++;
134 m_aDeviceNameToMonitor
[ aDeviceName
] = m_aMonitors
.size();
135 m_aMonitors
.push_back( DisplayMonitor( aDeviceString
,
142 HDC aDesktopRC
= GetDC( NULL
);
143 EnumDisplayMonitors( aDesktopRC
, NULL
, ImplEnumMonitorProc
, reinterpret_cast<LPARAM
>(this) );
145 // append monitor numbers to name strings
146 boost::unordered_map
< OUString
, int, OUStringHash
> aDevCount( aDeviceStringCount
);
147 unsigned int nMonitorCount
= m_aMonitors
.size();
148 for( unsigned int i
= 0; i
< nMonitorCount
; i
++ )
150 const OUString
& rDev( m_aMonitors
[i
].m_aName
);
151 if( aDeviceStringCount
[ rDev
] > 1 )
153 int nInstance
= aDeviceStringCount
[ rDev
] - (-- aDevCount
[ rDev
] );
154 OUStringBuffer
aBuf( rDev
.getLength() + 8 );
156 aBuf
.appendAscii( " (" );
157 aBuf
.append( sal_Int32( nInstance
) );
158 aBuf
.append( sal_Unicode(')') );
159 m_aMonitors
[ i
].m_aName
= aBuf
.makeStringAndClear();
164 return m_aMonitors
.size() > 0;
167 unsigned int WinSalSystem::GetDisplayScreenCount()
170 return m_aMonitors
.size();
173 unsigned int WinSalSystem::GetDisplayBuiltInScreen()
179 Rectangle
WinSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen
)
182 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aArea
: Rectangle();
185 Rectangle
WinSalSystem::GetDisplayScreenWorkAreaPosSizePixel( unsigned int nScreen
)
188 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aWorkArea
: Rectangle();
191 OUString
WinSalSystem::GetDisplayScreenName( unsigned int nScreen
)
194 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aName
: OUString();
197 // -----------------------------------------------------------------------
198 /* We have to map the button identifier to the identifier used by the Win32
199 Platform SDK to specify the default button for the MessageBox API.
200 The first dimension is the button combination, the second dimension
201 is the button identifier.
203 static int DEFAULT_BTN_MAPPING_TABLE
[][8] =
205 // Undefined OK CANCEL ABORT RETRY IGNORE YES NO
206 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //OK
207 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //OK_CANCEL
208 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON3
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //ABORT_RETRY_IGNO
209 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON3
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
}, //YES_NO_CANCEL
210 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
}, //YES_NO
211 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
} //RETRY_CANCEL
214 int WinSalSystem::ShowNativeMessageBox(const OUString
& rTitle
, const OUString
& rMessage
, int nButtonCombination
, int nDefaultButton
, SAL_UNUSED_PARAMETER
bool)
216 DBG_ASSERT( nButtonCombination
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
&&
217 nButtonCombination
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL
&&
218 nDefaultButton
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
&&
219 nDefaultButton
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO
, "Invalid arguments!" );
221 int nFlags
= MB_TASKMODAL
| MB_SETFOREGROUND
| MB_ICONWARNING
| nButtonCombination
;
223 if (nButtonCombination
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
&&
224 nButtonCombination
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL
&&
225 nDefaultButton
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
&&
226 nDefaultButton
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO
)
227 nFlags
|= DEFAULT_BTN_MAPPING_TABLE
[nButtonCombination
][nDefaultButton
];
232 reinterpret_cast<LPCWSTR
>(rMessage
.getStr()),
233 reinterpret_cast<LPCWSTR
>(rTitle
.getStr()),
237 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */