← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2492: rework tab activation to fix latent bugs: only top-level windows can be activated, others can onl...

 

------------------------------------------------------------
revno: 2492
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Fri 2011-04-15 23:51:55 +0200
message:
  rework tab activation to fix latent bugs: only top-level windows can be activated, others can only be focused
modified:
  changelog.txt
  dwt/include/dwt/Taskbar.h
  dwt/include/dwt/aspects/AspectEraseBackground.h
  dwt/include/dwt/forward.h
  dwt/include/dwt/widgets/Composite.h
  dwt/include/dwt/widgets/Frame.h
  dwt/src/Taskbar.cpp
  dwt/src/widgets/TabView.cpp
  win32/DirectoryListingFrame.cpp
  win32/FinishedFrameBase.h
  win32/MDIChildFrame.h
  win32/MainWindow.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	2011-04-11 21:26:22 +0000
+++ changelog.txt	2011-04-15 21:51:55 +0000
@@ -18,6 +18,8 @@
 * Make more parts of the interface DPI-aware (poy)
 * Resizable and scrollable settings dialog
 * Remember the last settings page (poy)
+* Fix focus problems in dialogs (poy)
+* Fix Ctrl+W / Ctrl+F4 sometimes closing the wrong tab (poy)
 
 -- 0.782 2011-03-05 --
 * Prevent a remote crash triggered via malformed user commands (poy)

=== modified file 'dwt/include/dwt/Taskbar.h'
--- dwt/include/dwt/Taskbar.h	2011-01-02 17:12:02 +0000
+++ dwt/include/dwt/Taskbar.h	2011-04-15 21:51:55 +0000
@@ -64,7 +64,7 @@
 	virtual void setActive(ContainerPtr) = 0;
 
 	WindowPtr window;
-	std::unordered_map<ContainerPtr, ContainerPtr> tabs;
+	std::unordered_map<ContainerPtr, FramePtr> tabs;
 };
 
 }

=== modified file 'dwt/include/dwt/aspects/AspectEraseBackground.h'
--- dwt/include/dwt/aspects/AspectEraseBackground.h	2011-02-19 17:02:21 +0000
+++ dwt/include/dwt/aspects/AspectEraseBackground.h	2011-04-15 21:51:55 +0000
@@ -38,6 +38,7 @@
 
 #include "../Message.h"
 #include "../CanvasClasses.h"
+#include "../Dispatchers.h"
 
 namespace dwt {
 

=== modified file 'dwt/include/dwt/forward.h'
--- dwt/include/dwt/forward.h	2011-04-05 19:16:53 +0000
+++ dwt/include/dwt/forward.h	2011-04-15 21:51:55 +0000
@@ -79,6 +79,9 @@
 
 class FontDialog;
 
+class Frame;
+typedef Frame* FramePtr;
+
 class Grid;
 typedef Grid* GridPtr;
 class GridInfo;

=== modified file 'dwt/include/dwt/widgets/Composite.h'
--- dwt/include/dwt/widgets/Composite.h	2011-01-02 17:12:02 +0000
+++ dwt/include/dwt/widgets/Composite.h	2011-04-15 21:51:55 +0000
@@ -32,7 +32,6 @@
 #ifndef DWT_COMPOSITE_H_
 #define DWT_COMPOSITE_H_
 
-#include "../aspects/AspectActivate.h"
 #include "../aspects/AspectContainer.h"
 #include "../aspects/AspectEraseBackground.h"
 #include "../aspects/AspectText.h"
@@ -45,7 +44,6 @@
 class Composite :
 	public Control,
 	// Aspects
-	public AspectActivate<Composite>,
 	public AspectContainer<Composite>,
 	public AspectEraseBackground<Composite>,
 	public AspectText<Composite>

=== modified file 'dwt/include/dwt/widgets/Frame.h'
--- dwt/include/dwt/widgets/Frame.h	2011-01-02 17:12:02 +0000
+++ dwt/include/dwt/widgets/Frame.h	2011-04-15 21:51:55 +0000
@@ -37,39 +37,16 @@
 #define DWT_Frame_h
 
 #include "../resources/Icon.h"
+#include "../aspects/AspectActivate.h"
 #include "../aspects/AspectMinMax.h"
 #include "Composite.h"
 
 namespace dwt {
 
-/// Main Window class
-/** \ingroup WidgetControls
-  * \WidgetUsageInfo
-  * \image html widgetwindow.png
-  * This class defines a "normal" window or the most commonly used "container
-  * Widget", normally you would define your own class which (indirectly) derives from
-  * this one. <br>
-  * You would normally derive directly from WidgetFactory and then supply this class
-  * as the first template parameter. <br>
-  * The second parameter would then be YOUR CLASS. <br>
-  * Example <br>
-  * <b>class MyMainWindow : public dwt::WidgetFactory<dwt::Window,
-  * MyMainWindow> { ... };</b> <br>
-  * Note especially that the second template argument to the WidgetFactory template
-  * class would almost ALWAYS be the name of your class derived from WidgetFactory.
-  * <br>
-  * You can also derive directly from Window and skip around the WidgetFactory
-  * factory class, the inheritance string would then become: <br>
-  * <b>class MyMainWindow : public dwt::Window<MyMainWindow></b> <br>
-  * But then you wouldn't have access to all the "createxxx" functions from class
-  * WidgetFactory which automatically gurantees that your Widgets get the right parent
-  * etc. <br>
-  * Look at (almost) any of the example projects distributed with the main download of
-  * the library residing in the dwtUnitTests directory for an example of how to
-  * use  this class with the factory class WidgetFactory.
-  */
+/** Base class for a top-level window (either a main app window or a dialog). */
 class Frame :
 	public Composite,
+	public AspectActivate<Frame>,
 	public AspectMinMax<Frame>
 {
 	typedef Composite BaseType;

=== modified file 'dwt/src/Taskbar.cpp'
--- dwt/src/Taskbar.cpp	2011-03-02 16:06:03 +0000
+++ dwt/src/Taskbar.cpp	2011-04-15 21:51:55 +0000
@@ -113,6 +113,24 @@
 	}
 }
 
+class Proxy : public Frame {
+	typedef Frame BaseType;
+	friend class WidgetCreator<Proxy>;
+
+public:
+	typedef Proxy ThisType;
+	typedef ThisType* ObjectType;
+	struct Seed : BaseType::Seed {
+		typedef ThisType WidgetType;
+		Seed(const tstring& caption) : BaseType::Seed(caption, 0, 0) {
+			style = WS_POPUP | WS_CAPTION;
+			exStyle = WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE;
+			location = Rectangle();
+		}
+	};
+	Proxy(Widget* parent) : BaseType(parent, NormalDispatcher::getDefault()) { }
+};
+
 void Taskbar::addToTaskbar(ContainerPtr tab) {
 	/* for Windows to acknowledge that our tab window is worthy of having its own thumbnail in the
 	taskbar, we have to create an invisible popup window that will act as a proxy between the
@@ -120,16 +138,7 @@
 	this technique is illustrated in MFC as well as the Windows SDK sample at
 	"Samples\winui\shell\appshellintegration\TabThumbnails". */
 
-	ContainerPtr proxy;
-	{
-		Container::Seed seed;
-		seed.caption = tab->getText();
-		seed.style &= ~WS_VISIBLE;
-		seed.style |= WS_POPUP | WS_CAPTION;
-		seed.exStyle |= WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE;
-		seed.location = Rectangle();
-		proxy = window->addChild(seed);
-	}
+	auto proxy = window->addChild(Proxy::Seed(tab->getText()));
 	tabs[tab] = proxy;
 
 	// keep the proxy window in sync with the actual tab window.
@@ -187,9 +196,9 @@
 }
 
 void Taskbar::removeFromTaskbar(ContainerPtr tab) {
-	ContainerPtr proxy = tabs[tab];
+	auto proxy = tabs[tab];
 	taskbar->UnregisterTab(proxy->handle());
-	::DestroyWindow(proxy->handle());
+	proxy->close();
 	tabs.erase(tab);
 }
 

=== modified file 'dwt/src/widgets/TabView.cpp'
--- dwt/src/widgets/TabView.cpp	2011-03-30 20:13:51 +0000
+++ dwt/src/widgets/TabView.cpp	2011-04-15 21:51:55 +0000
@@ -296,10 +296,9 @@
 	newW->resize(clientSize);
 	newW->setVisible(true);
 	if(oldW) {
-		oldW->sendMessage(WM_ACTIVATE, WA_INACTIVE, reinterpret_cast<LPARAM>(newW->handle()));
 		oldW->setVisible(false);
 	}
-	newW->sendMessage(WM_ACTIVATE, WA_ACTIVE, oldW ? reinterpret_cast<LPARAM>(oldW->handle()) : 0);
+	newW->setFocus();
 }
 
 void TabView::handleTabSelected() {

=== modified file 'win32/DirectoryListingFrame.cpp'
--- win32/DirectoryListingFrame.cpp	2011-04-13 19:16:51 +0000
+++ win32/DirectoryListingFrame.cpp	2011-04-15 21:51:55 +0000
@@ -112,7 +112,7 @@
 		frame->activate();
 	} else {
 		frame->setDirty(SettingsManager::BOLD_FL);
-		frame->onActivate([frame, aDir](bool b) {
+		frame->onVisibilityChanged([frame, aDir](bool b) {
 			if(b && !frame->loaded && !WinUtil::mainWindow->closing())
 				frame->loadFile(aDir);
 		});

=== modified file 'win32/FinishedFrameBase.h'
--- win32/FinishedFrameBase.h	2011-04-05 19:16:53 +0000
+++ win32/FinishedFrameBase.h	2011-04-15 21:51:55 +0000
@@ -134,7 +134,7 @@
 				onlyFull->onClicked([this] { this->handleOnlyFullClicked(); });
 			}
 
-			filesWindow->onActivate([this](bool active) { this->onlyFull->setVisible(active); });
+			filesWindow->onVisibilityChanged([this](bool b) { this->onlyFull->setVisible(b); });
 		}
 
 		this->initStatus();
@@ -148,8 +148,8 @@
 
 		layout();
 
-		filesWindow->onActivate([this](bool active) { this->updateStatus(active); });
-		usersWindow->onActivate([this](bool active) { this->updateStatus(active); });
+		filesWindow->onVisibilityChanged([this](bool b) { if(b) this->updateStatus(); });
+		usersWindow->onVisibilityChanged([this](bool b) { if(b) this->updateStatus(); });
 
 		FinishedManager::getInstance()->addListener(this);
 
@@ -524,10 +524,7 @@
 		updateStatus();
 	}
 
-	void updateStatus(bool activate = true) {
-		if(!activate)
-			return;
-
+	void updateStatus() {
 		size_t count = 0;
 		int64_t bytes = 0;
 		int64_t time = 0;

=== modified file 'win32/MDIChildFrame.h'
--- win32/MDIChildFrame.h	2011-04-05 19:16:53 +0000
+++ win32/MDIChildFrame.h	2011-04-15 21:51:55 +0000
@@ -60,8 +60,8 @@
 
 		onClosing([this] { return this->handleClosing(); });
 		onFocus([this] { this->handleFocus(); });
+		onVisibilityChanged([this](bool b) { this->handleVisibilityChanged(b); });
 		onWindowPosChanged([this](const dwt::Rectangle &r) { this->handleSized(r); });
-		onActivate([this](bool active) { this->handleActivate(active); });
 		addDlgCodeMessage(this);
 
 		addAccel(FCONTROL, 'W', [this] { this->close(true); });
@@ -74,12 +74,6 @@
 		getParent()->remove(this);
 	}
 
-	void handleFocus() {
-		if(lastFocus != NULL) {
-			::SetFocus(lastFocus);
-		}
-	}
-
 	/**
 	 * The first of two close phases, used to disconnect from other threads that might affect this window.
 	 * This is where all stuff that might be affected by other threads goes - it should make sure
@@ -195,14 +189,17 @@
 		t().layout();
 	}
 
-	void handleActivate(bool active) {
-		if(active) {
-			if(lastFocus) {
-				::SetFocus(lastFocus);
-			}
-		} else if(!alwaysSameFocus) {
+	void handleFocus() {
+		if(lastFocus) {
+			::SetFocus(lastFocus);
+		}
+	}
+
+	void handleVisibilityChanged(bool b) {
+		if(!b && !alwaysSameFocus) {
+			// remember the previously focused window.
 			HWND focus = ::GetFocus();
-			if(focus != NULL && ::IsChild(t().handle(), focus))
+			if(focus && ::IsChild(t().handle(), focus))
 				lastFocus = focus;
 		}
 	}

=== modified file 'win32/MainWindow.cpp'
--- win32/MainWindow.cpp	2011-04-15 20:53:17 +0000
+++ win32/MainWindow.cpp	2011-04-15 21:51:55 +0000
@@ -1079,10 +1079,10 @@
 }
 
 void MainWindow::handleActivate(bool active) {
-	// Forward to active tab window
+	// focus the active tab window
 	Container* w = getTabView()->getActive();
 	if(w) {
-		w->sendMessage(WM_ACTIVATE, active ? WA_ACTIVE : WA_INACTIVE);
+		w->setFocus();
 	}
 }