← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2815: Improve multiple monitor support

 

------------------------------------------------------------
revno: 2815
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Fri 2012-01-13 18:10:09 +0100
message:
  Improve multiple monitor support
modified:
  changelog.txt
  dwt/include/dwt/Rectangle.h
  dwt/include/dwt/Widget.h
  dwt/include/dwt/aspects/Sizable.h
  dwt/include/dwt/widgets/ComboBox.h
  dwt/src/Rectangle.cpp
  dwt/src/Widget.cpp
  dwt/src/widgets/ComboBox.cpp
  win32/MainWindow.cpp
  win32/SplashWindow.cpp
  win32/WinUtil.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt	2012-01-12 16:14:38 +0000
+++ changelog.txt	2012-01-13 17:10:09 +0000
@@ -6,6 +6,7 @@
 * Reclaim memory after a file list match
 * Improve file reading operations
 * [L#678432] Context-sensitive help tooltips in the settings dialog (poy)
+* [L#804993] Improve multiple monitor support (poy)
 
 -- 0.790 2011-12-29 --
 * Fav users frame becomes users frame and shows all users

=== modified file 'dwt/include/dwt/Rectangle.h'
--- dwt/include/dwt/Rectangle.h	2012-01-08 22:14:11 +0000
+++ dwt/include/dwt/Rectangle.h	2012-01-13 17:10:09 +0000
@@ -299,6 +299,10 @@
 
 	/// Produce a Rectangle with the right portion removed
 	Rectangle cropRight( const int a_ToRemove ) const;
+
+	/** Adjust the rectangle to make sure it is not outside of the desktop of the monitor closest
+	to the given base widget. */
+	Rectangle& ensureVisibility(Widget* base);
 };
 
 bool operator==(const Rectangle& lhs, const Rectangle& rhs);

=== modified file 'dwt/include/dwt/Widget.h'
--- dwt/include/dwt/Widget.h	2011-11-15 19:05:59 +0000
+++ dwt/include/dwt/Widget.h	2012-01-13 17:10:09 +0000
@@ -141,6 +141,11 @@
 	Point getWindowSize() const;
 	Point getClientSize() const;
 
+	/** Return the desktop size of the primary monitor (at coords 0, 0). */
+	static Point getPrimaryDesktopSize();
+	/** Return the desktop size of the monitor closest to this widget. */
+	Rectangle getDesktopSize() const;
+
 	/// Sets the enabled property of the Widget
 	/** Changes the enabled property of the Widget. Use this function to change the
 	  * enabled property of the Widget
@@ -225,6 +230,8 @@
 	friend class Application;
 	template<typename T> friend T hwnd_cast(HWND hwnd);
 
+	static Rectangle getDesktopSize(HMONITOR mon);
+
 	// Contains the list of signals we're (this window) processing
 	CallbackCollectionType handlers;
 

=== modified file 'dwt/include/dwt/aspects/Sizable.h'
--- dwt/include/dwt/aspects/Sizable.h	2011-12-05 19:17:57 +0000
+++ dwt/include/dwt/aspects/Sizable.h	2012-01-13 17:10:09 +0000
@@ -81,12 +81,6 @@
 	typedef Dispatchers::ConvertBase<Point, &Point::fromMSG, 0, false> MoveDispatcher;
 
 public:
-	/// Returns the screen size.
-	/** This is the screen size, and useful for making applications that must adapt
-	 * to different screen sizes.
-	 */
-	static Point getDesktopSize();
-
 	/// Brings the widget to the front
 	/** Makes the widget become the front most widget meaning it will not be obscured
 	  * by other widgets which are contained in the same container widget. <br>
@@ -108,16 +102,7 @@
 		rect.pos.y = (rect.top() + rect.bottom() - size.y) / 2;
 		rect.size = size;
 
-		// make sure the window is still in the screen area.
-		MONITORINFO mi = { sizeof(MONITORINFO) };
-		if(::GetMonitorInfo(::MonitorFromWindow(root->handle(), MONITOR_DEFAULTTONEAREST), &mi)) {
-			if(rect.right() > mi.rcWork.right) { rect.pos.x = mi.rcWork.right - rect.width(); }
-			if(rect.left() < mi.rcWork.left) { rect.pos.x = mi.rcWork.left; }
-			if(rect.bottom() > mi.rcWork.bottom) { rect.pos.y = mi.rcWork.bottom - rect.height(); }
-			if(rect.top() < mi.rcWork.top) { rect.pos.y = mi.rcWork.top; }
-		}
-
-		resize(rect);
+		resize(rect.ensureVisibility(root));
 	}
 
 	/// Brings the widget to the bottom
@@ -160,14 +145,6 @@
 };
 
 template< class WidgetType >
-Point Sizable< WidgetType >::getDesktopSize()
-{
-	RECT rc;
-	::GetWindowRect( ::GetDesktopWindow(), & rc );
-	return Point( rc.right - rc.left, rc.bottom - rc.top );
-}
-
-template< class WidgetType >
 void Sizable< WidgetType >::bringToFront()
 {
 	::SetWindowPos(H(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );

=== modified file 'dwt/include/dwt/widgets/ComboBox.h'
--- dwt/include/dwt/widgets/ComboBox.h	2011-11-19 00:10:54 +0000
+++ dwt/include/dwt/widgets/ComboBox.h	2012-01-13 17:10:09 +0000
@@ -119,10 +119,6 @@
 
 	virtual Point getPreferredSize();
 
-	virtual void layout();
-
-	void setDropDownHeight(size_t h);
-
 	using aspects::Clickable<ThisType>::onClicked;
 	using aspects::Clickable<ThisType>::onDblClicked;
 
@@ -138,8 +134,6 @@
 	friend class ChainingDispatcher;
 	static const TCHAR windowClass[];
 
-	size_t dropDownHeight;
-
 	// aspects::Selection
 	int getSelectedImpl() const;
 	void setSelectedImpl( int idx );

=== modified file 'dwt/src/Rectangle.cpp'
--- dwt/src/Rectangle.cpp	2012-01-08 22:14:11 +0000
+++ dwt/src/Rectangle.cpp	2012-01-13 17:10:09 +0000
@@ -31,6 +31,8 @@
 
 #include <dwt/Rectangle.h>
 
+#include <dwt/Widget.h>
+
 namespace dwt {
 
 Rectangle::Rectangle( long x, long y, long width, long height )
@@ -183,6 +185,15 @@
 	return Rectangle( pos.x, pos.y, d_NewSize > 0 ? d_NewSize : 0, size.y );
 }
 
+Rectangle& Rectangle::ensureVisibility(Widget* base) {
+	auto desktop = base->getDesktopSize();
+	if(right() > desktop.right()) { pos.x = desktop.right() - width(); }
+	if(left() < desktop.left()) { pos.x = desktop.left(); }
+	if(bottom() > desktop.bottom()) { pos.y = desktop.bottom() - height(); }
+	if(top() < desktop.top()) { pos.y = desktop.top(); }
+	return *this;
+}
+
 bool operator==(const Rectangle& lhs, const Rectangle& rhs) {
 	return lhs.pos == rhs.pos && lhs.size == rhs.size;
 }

=== modified file 'dwt/src/Widget.cpp'
--- dwt/src/Widget.cpp	2011-12-22 22:14:45 +0000
+++ dwt/src/Widget.cpp	2012-01-13 17:10:09 +0000
@@ -165,4 +165,25 @@
 
 void Widget::layout() { }
 
+Point Widget::getPrimaryDesktopSize() {
+	POINT pt = { 0 };
+	return getDesktopSize(::MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY)).size;
+}
+
+Rectangle Widget::getDesktopSize() const {
+	return getDesktopSize(::MonitorFromWindow(handle(), MONITOR_DEFAULTTONEAREST));
+}
+
+Rectangle Widget::getDesktopSize(HMONITOR mon) {
+	MONITORINFO mi = { sizeof(MONITORINFO) };
+	if(::GetMonitorInfo(mon, &mi)) {
+		return Rectangle(mi.rcWork);
+	}
+
+	// the following should never be needed, but better be safe...
+	RECT rc = { 0 };
+	::GetWindowRect(::GetDesktopWindow(), &rc);
+	return Rectangle(rc);
+}
+
 }

=== modified file 'dwt/src/widgets/ComboBox.cpp'
--- dwt/src/widgets/ComboBox.cpp	2011-06-28 20:07:49 +0000
+++ dwt/src/widgets/ComboBox.cpp	2012-01-13 17:10:09 +0000
@@ -42,8 +42,9 @@
 {
 }
 
-ComboBox::ComboBox(Widget* parent ) : BaseType(parent, ChainingDispatcher::superClass<ComboBox>()), dropDownHeight(::GetSystemMetrics(SM_CYSCREEN) / 3) {
-
+ComboBox::ComboBox(Widget* parent ) :
+BaseType(parent, ChainingDispatcher::superClass<ComboBox>())
+{
 }
 
 void ComboBox::create( const Seed & cs ) {
@@ -78,15 +79,6 @@
 	return ret;
 }
 
-void ComboBox::layout() {
-	/* TODO
-	Rectangle copy(r);
-	copy.size.y = dropDownHeight;
-	BaseType::layout(copy);
-	*/
-	BaseType::layout();
-}
-
 LPARAM ComboBox::getDataImpl(int i) {
 	return sendMessage(CB_GETITEMDATA, i);
 }

=== modified file 'win32/MainWindow.cpp'
--- win32/MainWindow.cpp	2012-01-12 16:14:38 +0000
+++ win32/MainWindow.cpp	2012-01-13 17:10:09 +0000
@@ -200,7 +200,27 @@
 
 	callAsync([this] {
 		int cmdShow = dwt::Application::instance().getCmdShow();
-		::ShowWindow(handle(), (cmdShow == SW_SHOWDEFAULT || cmdShow == SW_SHOWNORMAL) ? SETTING(MAIN_WINDOW_STATE) : cmdShow);
+		if(cmdShow == SW_SHOWDEFAULT || cmdShow == SW_SHOWNORMAL)
+			cmdShow = SETTING(MAIN_WINDOW_STATE);
+
+		int pos_x = SETTING(MAIN_WINDOW_POS_X);
+		int pos_y = SETTING(MAIN_WINDOW_POS_Y);
+		int size_x = SETTING(MAIN_WINDOW_SIZE_X);
+		int size_y = SETTING(MAIN_WINDOW_SIZE_Y);
+		if(pos_x != static_cast<int>(CW_USEDEFAULT) && pos_y != static_cast<int>(CW_USEDEFAULT) &&
+			size_x != static_cast<int>(CW_USEDEFAULT) && size_y != static_cast<int>(CW_USEDEFAULT) &&
+			size_x > 10 && size_y > 10)
+		{
+			WINDOWPLACEMENT wp = { sizeof(WINDOWPLACEMENT) };
+			wp.showCmd = cmdShow;
+			wp.rcNormalPosition = dwt::Rectangle(pos_x, pos_y, size_x, size_y);
+			::SetWindowPlacement(handle(), &wp);
+		} else {
+			/* invalid pos / size values; just show the window (Windows will have decided a
+			position for the window by itself). */
+			::ShowWindow(handle(), cmdShow);
+		}
+
 		if(cmdShow == SW_MINIMIZE || cmdShow == SW_SHOWMINIMIZED || cmdShow == SW_SHOWMINNOACTIVE)
 			handleMinimized();
 	});
@@ -224,18 +244,6 @@
 
 	Seed cs(_T(APPNAME) _T(" ") _T(VERSIONSTRING));
 
-	int pos_x = SETTING(MAIN_WINDOW_POS_X);
-	int pos_y = SETTING(MAIN_WINDOW_POS_Y);
-	int size_x = SETTING(MAIN_WINDOW_SIZE_X);
-	int size_y = SETTING(MAIN_WINDOW_SIZE_Y);
-	if(pos_x != static_cast<int>(CW_USEDEFAULT) && pos_y != static_cast<int>(CW_USEDEFAULT) &&
-		size_x != static_cast<int>(CW_USEDEFAULT) && size_y != static_cast<int>(CW_USEDEFAULT) &&
-		pos_x > 0 && pos_y > 0 && size_x > 10 && size_y > 10 &&
-		pos_x < getDesktopSize().x && pos_y < getDesktopSize().y)
-	{
-		cs.location = dwt::Rectangle(pos_x, pos_y, size_x, size_y);
-	}
-
 	cs.style &= ~WS_VISIBLE;
 	cs.exStyle |= WS_EX_APPWINDOW;
 	if (ResourceManager::getInstance()->isRTL())
@@ -895,16 +903,19 @@
 
 	SettingsManager::getInstance()->set(SettingsManager::TRANSFERS_PANED_POS, paned->getSplitterPos(0));
 
-	WINDOWPLACEMENT wp = { sizeof(wp)};
-	::GetWindowPlacement(this->handle(), &wp);
-	if(wp.showCmd == SW_SHOW || wp.showCmd == SW_SHOWNORMAL) {
-		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_POS_X, static_cast<int>(wp.rcNormalPosition.left));
-		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_POS_Y, static_cast<int>(wp.rcNormalPosition.top));
-		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_SIZE_X, static_cast<int>(wp.rcNormalPosition.right - wp.rcNormalPosition.left));
-		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_SIZE_Y, static_cast<int>(wp.rcNormalPosition.bottom - wp.rcNormalPosition.top));
+	WINDOWPLACEMENT wp = { sizeof(wp) };
+	if(::GetWindowPlacement(this->handle(), &wp)) {
+
+		dwt::Rectangle rect(wp.rcNormalPosition);
+		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_POS_X, static_cast<int>(rect.left()));
+		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_POS_Y, static_cast<int>(rect.top()));
+		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_SIZE_X, static_cast<int>(rect.width()));
+		SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_SIZE_Y, static_cast<int>(rect.height()));
+
+		if(wp.showCmd == SW_SHOWNORMAL || wp.showCmd == SW_SHOW || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_MAXIMIZE) {
+			SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_STATE, static_cast<int>(wp.showCmd));
+		}
 	}
-	if(wp.showCmd == SW_SHOWNORMAL || wp.showCmd == SW_SHOW || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_MAXIMIZE)
-	SettingsManager::getInstance()->set(SettingsManager::MAIN_WINDOW_STATE, (int)wp.showCmd);
 }
 
 bool MainWindow::handleClosing() {

=== modified file 'win32/SplashWindow.cpp'
--- win32/SplashWindow.cpp	2011-12-23 14:08:07 +0000
+++ win32/SplashWindow.cpp	2012-01-13 17:10:09 +0000
@@ -88,7 +88,7 @@
 		}
 	}
 
-	auto desktop = getDesktopSize();
+	auto desktop = getPrimaryDesktopSize();
 	POINT pt = { std::max(desktop.x - size.cx, 0L) / 2, std::max(desktop.y - size.cy - iconSize, 0L) / 2 };
 	POINT canvasPt = { 0 };
 	BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };

=== modified file 'win32/WinUtil.cpp'
--- win32/WinUtil.cpp	2012-01-12 16:14:38 +0000
+++ win32/WinUtil.cpp	2012-01-13 17:10:09 +0000
@@ -927,7 +927,7 @@
 		if(multiline)
 			seed.style |= ES_MULTILINE;
 		seed.exStyle = WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_CLIENTEDGE;
-		seed.location.size.x = std::min(getDesktopSize().x, static_cast<long>(maxWidth * dwt::util::dpiFactor()));
+		seed.location.size.x = std::min(getParent()->getDesktopSize().width(), static_cast<long>(maxWidth * dwt::util::dpiFactor()));
 		create(seed);
 
 		const auto margins = sendMessage(EM_GETMARGINS);
@@ -965,12 +965,8 @@
 		rect.size.x += ::GetSystemMetrics(SM_CXEDGE) * 2;
 		rect.size.y += ::GetSystemMetrics(SM_CYEDGE) * 2 + margin;
 
-		// make sure the window fits in within the screen
-		const auto screen = getDesktopSize();
-		if(rect.right() > screen.x) { rect.pos.x -= rect.right() - screen.x; }
-		if(rect.left() < 0) { rect.pos.x = 0; }
-		if(rect.bottom() > screen.y) { rect.pos.y -= rect.bottom() - screen.y; }
-		if(rect.top() < 0) { rect.pos.y = 0; }
+		// make sure the window fits in within the desktop of the parent widget.
+		rect.ensureVisibility(getParent());
 
 		setColor(dwt::Color::predefined(COLOR_INFOTEXT), dwt::Color::predefined(COLOR_INFOBK));