aboutsummaryrefslogtreecommitdiff
path: root/guilib/GUIWindowManager.cpp
diff options
context:
space:
mode:
authorAlTheKiller <AlTheKiller@svn>2009-09-23 01:49:50 +0000
committerAlTheKiller <AlTheKiller@svn>2009-09-23 01:49:50 +0000
commit45285e8a9300cd754a760560640b75b09f98035e (patch)
treead9f093885ad5c98e9dd4156674e7691c22ed0a2 /guilib/GUIWindowManager.cpp
step 3/4: Move linuxport to trunk. How'd I get roped into this?
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@23097 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
Diffstat (limited to 'guilib/GUIWindowManager.cpp')
-rw-r--r--guilib/GUIWindowManager.cpp891
1 files changed, 891 insertions, 0 deletions
diff --git a/guilib/GUIWindowManager.cpp b/guilib/GUIWindowManager.cpp
new file mode 100644
index 0000000000..e2ec0761d8
--- /dev/null
+++ b/guilib/GUIWindowManager.cpp
@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2005-2008 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "GUIWindowManager.h"
+#include "GUIAudioManager.h"
+#include "GUIDialog.h"
+#include "Application.h"
+#include "GUIPassword.h"
+#include "utils/GUIInfoManager.h"
+#include "Util.h"
+#include "GUISettings.h"
+#include "Settings.h"
+
+using namespace std;
+
+CGUIWindowManager m_gWindowManager;
+
+CGUIWindowManager::CGUIWindowManager(void)
+{
+ InitializeCriticalSection(&m_critSection);
+
+ m_pCallback = NULL;
+ m_bShowOverlay = true;
+}
+
+CGUIWindowManager::~CGUIWindowManager(void)
+{
+ DeleteCriticalSection(&m_critSection);
+}
+
+void CGUIWindowManager::Initialize()
+{
+ g_graphicsContext.setMessageSender(this);
+ LoadNotOnDemandWindows();
+}
+
+bool CGUIWindowManager::SendMessage(CGUIMessage& message)
+{
+ bool handled = false;
+// CLog::Log(LOGDEBUG,"SendMessage: mess=%d send=%d control=%d param1=%d", message.GetMessage(), message.GetSenderId(), message.GetControlId(), message.GetParam1());
+ // Send the message to all none window targets
+ for (int i = 0; i < (int) m_vecMsgTargets.size(); i++)
+ {
+ IMsgTargetCallback* pMsgTarget = m_vecMsgTargets[i];
+
+ if (pMsgTarget)
+ {
+ if (pMsgTarget->OnMessage( message )) handled = true;
+ }
+ }
+
+ // A GUI_MSG_NOTIFY_ALL is send to any active modal dialog
+ // and all windows whether they are active or not
+ if (message.GetMessage()==GUI_MSG_NOTIFY_ALL)
+ {
+ for (rDialog it = m_activeDialogs.rbegin(); it != m_activeDialogs.rend(); ++it)
+ {
+ CGUIWindow *dialog = *it;
+ dialog->OnMessage(message);
+ }
+
+ for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++)
+ {
+ CGUIWindow *pWindow = (*it).second;
+ pWindow->OnMessage(message);
+ }
+ return true;
+ }
+
+ // Normal messages are sent to:
+ // 1. All active modeless dialogs
+ // 2. The topmost dialog that accepts the message
+ // 3. The underlying window (only if it is the sender or receiver if a modal dialog is active)
+
+ bool hasModalDialog(false);
+ bool modalAcceptedMessage(false);
+ // don't use an iterator for this loop, as some messages mean that m_activeDialogs is altered,
+ // which will invalidate any iterator
+ unsigned int topWindow = m_activeDialogs.size();
+ while (topWindow)
+ {
+ CGUIWindow* dialog = m_activeDialogs[--topWindow];
+ if (!modalAcceptedMessage && dialog->IsModalDialog())
+ { // modal window
+ hasModalDialog = true;
+ if (!modalAcceptedMessage && dialog->OnMessage( message ))
+ {
+ modalAcceptedMessage = handled = true;
+ }
+ }
+ else if (!dialog->IsModalDialog())
+ { // modeless
+ if (dialog->OnMessage( message ))
+ handled = true;
+ }
+ }
+
+ // now send to the underlying window
+ CGUIWindow* window = GetWindow(GetActiveWindow());
+ if (window)
+ {
+ if (hasModalDialog)
+ {
+ // only send the message to the underlying window if it's the recipient
+ // or sender (or we have no sender)
+ if (message.GetSenderId() == window->GetID() ||
+ message.GetControlId() == window->GetID() ||
+ message.GetSenderId() == 0 )
+ {
+ if (window->OnMessage(message)) handled = true;
+ }
+ }
+ else
+ {
+ if (window->OnMessage(message)) handled = true;
+ }
+ }
+ return handled;
+}
+
+bool CGUIWindowManager::SendMessage(CGUIMessage& message, int window)
+{
+ CGUIWindow* pWindow = GetWindow(window);
+ if(pWindow)
+ return pWindow->OnMessage(message);
+ else
+ return false;
+}
+
+void CGUIWindowManager::AddUniqueInstance(CGUIWindow *window)
+{
+ // increment our instance (upper word of windowID)
+ // until we get a window we don't have
+ int instance = 0;
+ while (GetWindow(window->GetID()))
+ window->SetID(window->GetID() + (++instance << 16));
+ Add(window);
+}
+
+void CGUIWindowManager::Add(CGUIWindow* pWindow)
+{
+ if (!pWindow)
+ {
+ CLog::Log(LOGERROR, "Attempted to add a NULL window pointer to the window manager.");
+ return;
+ }
+ // push back all the windows if there are more than one covered by this class
+ for (int i = 0; i < pWindow->GetIDRange(); i++)
+ {
+ WindowMap::iterator it = m_mapWindows.find(pWindow->GetID() + i);
+ if (it != m_mapWindows.end())
+ {
+ CLog::Log(LOGERROR, "Error, trying to add a second window with id %u "
+ "to the window manager",
+ pWindow->GetID());
+ return;
+ }
+ m_mapWindows.insert(pair<int, CGUIWindow *>(pWindow->GetID() + i, pWindow));
+ }
+}
+
+void CGUIWindowManager::AddCustomWindow(CGUIWindow* pWindow)
+{
+ Add(pWindow);
+ m_vecCustomWindows.push_back(pWindow);
+}
+
+void CGUIWindowManager::AddModeless(CGUIWindow* dialog)
+{
+ // only add the window if it's not already added
+ for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it)
+ if (*it == dialog) return;
+ m_activeDialogs.push_back(dialog);
+}
+
+void CGUIWindowManager::Remove(int id)
+{
+ WindowMap::iterator it = m_mapWindows.find(id);
+ if (it != m_mapWindows.end())
+ {
+ m_mapWindows.erase(it);
+ }
+ else
+ {
+ CLog::Log(LOGWARNING, "Attempted to remove window %u "
+ "from the window manager when it didn't exist",
+ id);
+ }
+}
+
+// removes and deletes the window. Should only be called
+// from the class that created the window using new.
+void CGUIWindowManager::Delete(int id)
+{
+ CGUIWindow *pWindow = GetWindow(id);
+ if (pWindow)
+ {
+ Remove(id);
+ delete pWindow;
+ }
+}
+
+void CGUIWindowManager::PreviousWindow()
+{
+ // deactivate any window
+ CLog::Log(LOGDEBUG,"CGUIWindowManager::PreviousWindow: Deactivate");
+ int currentWindow = GetActiveWindow();
+ CGUIWindow *pCurrentWindow = GetWindow(currentWindow);
+ if (!pCurrentWindow)
+ return; // no windows or window history yet
+
+ // check to see whether our current window has a <previouswindow> tag
+ if (pCurrentWindow->GetPreviousWindow() != WINDOW_INVALID)
+ {
+ // TODO: we may need to test here for the
+ // whether our history should be changed
+
+ // don't reactivate the previouswindow if it is ourselves.
+ if (currentWindow != pCurrentWindow->GetPreviousWindow())
+ ActivateWindow(pCurrentWindow->GetPreviousWindow());
+ return;
+ }
+ // get the previous window in our stack
+ if (m_windowHistory.size() < 2)
+ { // no previous window history yet - check if we should just activate home
+ if (GetActiveWindow() != WINDOW_INVALID && GetActiveWindow() != WINDOW_HOME)
+ {
+ ClearWindowHistory();
+ ActivateWindow(WINDOW_HOME);
+ }
+ return;
+ }
+ m_windowHistory.pop();
+ int previousWindow = GetActiveWindow();
+ m_windowHistory.push(currentWindow);
+
+ CGUIWindow *pNewWindow = GetWindow(previousWindow);
+ if (!pNewWindow)
+ {
+ CLog::Log(LOGERROR, "Unable to activate the previous window");
+ ClearWindowHistory();
+ ActivateWindow(WINDOW_HOME);
+ return;
+ }
+
+ // ok to go to the previous window now
+
+ // tell our info manager which window we are going to
+ g_infoManager.SetNextWindow(previousWindow);
+
+ // set our overlay state (enables out animations on window change)
+ HideOverlay(pNewWindow->GetOverlayState());
+
+ // deinitialize our window
+ g_audioManager.PlayWindowSound(pCurrentWindow->GetID(), SOUND_DEINIT);
+ CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0);
+ pCurrentWindow->OnMessage(msg);
+
+ g_infoManager.SetNextWindow(WINDOW_INVALID);
+ g_infoManager.SetPreviousWindow(currentWindow);
+
+ // remove the current window off our window stack
+ m_windowHistory.pop();
+
+ // ok, initialize the new window
+ CLog::Log(LOGDEBUG,"CGUIWindowManager::PreviousWindow: Activate new");
+ g_audioManager.PlayWindowSound(pNewWindow->GetID(), SOUND_INIT);
+ CGUIMessage msg2(GUI_MSG_WINDOW_INIT, 0, 0, WINDOW_INVALID, GetActiveWindow());
+ pNewWindow->OnMessage(msg2);
+
+ g_infoManager.SetPreviousWindow(WINDOW_INVALID);
+ return;
+}
+
+void CGUIWindowManager::RefreshWindow()
+{
+ // deactivate the current window
+ CGUIWindow *pWindow = GetWindow(GetActiveWindow());
+ if (!pWindow)
+ return;
+
+ CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0);
+ pWindow->OnMessage(msg);
+ CGUIMessage msg2(GUI_MSG_WINDOW_INIT, 0, 0, WINDOW_INVALID);
+ pWindow->OnMessage(msg2);
+}
+
+void CGUIWindowManager::ChangeActiveWindow(int newWindow, const CStdString& strPath)
+{
+ vector<CStdString> params;
+ if (!strPath.IsEmpty())
+ params.push_back(strPath);
+ ActivateWindow(newWindow, params, true);
+}
+
+void CGUIWindowManager::ActivateWindow(int iWindowID, const CStdString& strPath)
+{
+ vector<CStdString> params;
+ if (!strPath.IsEmpty())
+ params.push_back(strPath);
+ ActivateWindow(iWindowID, params, false);
+}
+
+void CGUIWindowManager::ActivateWindow(int iWindowID, const vector<CStdString>& params, bool swappingWindows)
+{
+ if (!g_application.IsCurrentThread())
+ {
+ // make sure graphics lock is not held
+ int nCount = ExitCriticalSection(g_graphicsContext);
+ g_application.getApplicationMessenger().ActivateWindow(iWindowID, params, swappingWindows);
+ RestoreCriticalSection(g_graphicsContext, nCount);
+ }
+ else
+ ActivateWindow_Internal(iWindowID, params, swappingWindows);
+}
+
+void CGUIWindowManager::ActivateWindow_Internal(int iWindowID, const vector<CStdString>& params, bool swappingWindows)
+{
+ bool passParams = true;
+ // translate virtual windows
+ // virtual music window which returns the last open music window (aka the music start window)
+ if (iWindowID == WINDOW_MUSIC)
+ {
+ iWindowID = g_stSettings.m_iMyMusicStartWindow;
+ // ensure the music virtual window only returns music files and music library windows
+ if (iWindowID != WINDOW_MUSIC_NAV)
+ iWindowID = WINDOW_MUSIC_FILES;
+ // destination path cannot be used with virtual window
+ passParams = false;
+ }
+ // virtual video window which returns the last open video window (aka the video start window)
+ if (iWindowID == WINDOW_VIDEOS)
+ {
+ iWindowID = g_stSettings.m_iVideoStartWindow;
+ // ensure the virtual video window only returns video windows
+ if (iWindowID != WINDOW_VIDEO_NAV)
+ iWindowID = WINDOW_VIDEO_FILES;
+ // destination path cannot be used with virtual window
+ passParams = false;
+ }
+ // Is the Library enabled? If not, go to Files view.
+ if (iWindowID == WINDOW_MUSIC_NAV && !g_guiSettings.GetBool("musiclibrary.enabled"))
+ {
+ iWindowID = WINDOW_MUSIC_FILES;
+ passParams = false;
+ CLog::Log(LOGDEBUG, "Trying to activate Music Library, but its disabled. Switching to Files instead.");
+ }
+ if (iWindowID == WINDOW_VIDEO_NAV && !g_guiSettings.GetBool("videolibrary.enabled"))
+ {
+ iWindowID = WINDOW_VIDEO_FILES;
+ passParams = false;
+ CLog::Log(LOGDEBUG, "Trying to activate Video Library, but its disabled. Switching to Files instead.");
+ }
+
+ // debug
+ CLog::Log(LOGDEBUG, "Activating window ID: %i", iWindowID);
+
+ if(!g_passwordManager.CheckMenuLock(iWindowID))
+ {
+ CLog::Log(LOGERROR, "MasterCode is Wrong: Window with id %d will not be loaded! Enter a correct MasterCode!", iWindowID);
+ return;
+ }
+
+ // first check existence of the window we wish to activate.
+ CGUIWindow *pNewWindow = GetWindow(iWindowID);
+ if (!pNewWindow)
+ { // nothing to see here - move along
+ CLog::Log(LOGERROR, "Unable to locate window with id %d. Check skin files", iWindowID - WINDOW_HOME);
+ return ;
+ }
+ else if (pNewWindow->IsDialog())
+ { // if we have a dialog, we do a DoModal() rather than activate the window
+ if (!pNewWindow->IsDialogRunning())
+ ((CGUIDialog *)pNewWindow)->DoModal(iWindowID, (passParams && params.size()) ? params[0] : "");
+ return;
+ }
+
+ g_infoManager.SetNextWindow(iWindowID);
+
+ // set our overlay state
+ HideOverlay(pNewWindow->GetOverlayState());
+
+ // deactivate any window
+ int currentWindow = GetActiveWindow();
+ CGUIWindow *pWindow = GetWindow(currentWindow);
+ if (pWindow)
+ {
+ // Play the window specific deinit sound
+ g_audioManager.PlayWindowSound(pWindow->GetID(), SOUND_DEINIT);
+ CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0, iWindowID);
+ pWindow->OnMessage(msg);
+ }
+ g_infoManager.SetNextWindow(WINDOW_INVALID);
+
+ // Add window to the history list (we must do this before we activate it,
+ // as all messages done in WINDOW_INIT will want to be sent to the new
+ // topmost window). If we are swapping windows, we pop the old window
+ // off the history stack
+ if (swappingWindows && m_windowHistory.size())
+ m_windowHistory.pop();
+ AddToWindowHistory(iWindowID);
+
+ g_infoManager.SetPreviousWindow(currentWindow);
+ g_audioManager.PlayWindowSound(pNewWindow->GetID(), SOUND_INIT);
+ // Send the init message
+ CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0, 0, currentWindow, iWindowID);
+ if (passParams)
+ msg.SetStringParams(params);
+ pNewWindow->OnMessage(msg);
+// g_infoManager.SetPreviousWindow(WINDOW_INVALID);
+}
+
+void CGUIWindowManager::CloseDialogs(bool forceClose)
+{
+ while (m_activeDialogs.size() > 0)
+ {
+ CGUIWindow* win = m_activeDialogs[0];
+ win->Close(forceClose);
+ }
+}
+
+bool CGUIWindowManager::OnAction(const CAction &action)
+{
+ for (rDialog it = m_activeDialogs.rbegin(); it != m_activeDialogs.rend(); ++it)
+ {
+ CGUIWindow *dialog = *it;
+ if (dialog->IsModalDialog())
+ { // we have the topmost modal dialog
+ if (!dialog->IsAnimating(ANIM_TYPE_WINDOW_CLOSE))
+ {
+ if (dialog->OnAction(action))
+ return true;
+ // dialog didn't want the action - we'd normally return true
+ // but for some dialogs we want to drop the actions through
+ if (dialog->GetID() == WINDOW_DIALOG_FULLSCREEN_INFO)
+ break;
+ return false;
+ }
+ return true; // do nothing with the action until the anim is finished
+ }
+ // music or video overlay are handled as a special case, as they're modeless, but we allow
+ // clicking on them with the mouse.
+ if (action.id == ACTION_MOUSE && (dialog->GetID() == WINDOW_VIDEO_OVERLAY ||
+ dialog->GetID() == WINDOW_MUSIC_OVERLAY))
+ {
+ if (dialog->OnAction(action))
+ return true;
+ }
+ }
+ CGUIWindow* window = GetWindow(GetActiveWindow());
+ if (window)
+ return window->OnAction(action);
+ return false;
+}
+
+void CGUIWindowManager::Render()
+{
+ if (!g_application.IsCurrentThread())
+ {
+ // make sure graphics lock is not held
+ int nCount = ExitCriticalSection(g_graphicsContext);
+ g_application.getApplicationMessenger().Render();
+ RestoreCriticalSection(g_graphicsContext, nCount);
+ }
+ else
+ Render_Internal();
+}
+
+void CGUIWindowManager::Render_Internal()
+{
+ CGUIWindow* pWindow = GetWindow(GetActiveWindow());
+ if (pWindow)
+ pWindow->Render();
+}
+
+bool RenderOrderSortFunction(CGUIWindow *first, CGUIWindow *second)
+{
+ return first->GetRenderOrder() < second->GetRenderOrder();
+}
+
+void CGUIWindowManager::RenderDialogs()
+{
+ // find the window with the lowest render order
+ vector<CGUIWindow *> renderList = m_activeDialogs;
+ stable_sort(renderList.begin(), renderList.end(), RenderOrderSortFunction);
+
+ // iterate through and render if they're running
+ for (iDialog it = renderList.begin(); it != renderList.end(); ++it)
+ {
+ if ((*it)->IsDialogRunning())
+ (*it)->Render();
+ }
+}
+
+CGUIWindow* CGUIWindowManager::GetWindow(int id) const
+{
+ if (id == WINDOW_INVALID)
+ {
+ return NULL;
+ }
+
+ WindowMap::const_iterator it = m_mapWindows.find(id);
+ if (it != m_mapWindows.end())
+ return (*it).second;
+ return NULL;
+}
+
+// Shows and hides modeless dialogs as necessary.
+void CGUIWindowManager::UpdateModelessVisibility()
+{
+ for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++)
+ {
+ CGUIWindow *pWindow = (*it).second;
+ if (pWindow && pWindow->IsDialog() && pWindow->GetVisibleCondition())
+ {
+ if (g_infoManager.GetBool(pWindow->GetVisibleCondition(), GetActiveWindow()))
+ ((CGUIDialog *)pWindow)->Show();
+ else
+ ((CGUIDialog *)pWindow)->Close();
+ }
+ }
+}
+
+void CGUIWindowManager::Process(bool renderOnly /*= false*/)
+{
+ if (!g_application.IsCurrentThread())
+ {
+ // make sure graphics lock is not held
+ DWORD locks = ExitCriticalSection(g_graphicsContext);
+ g_application.getApplicationMessenger().WindowManagerProcess(renderOnly);
+ RestoreCriticalSection(g_graphicsContext, locks);
+ }
+ else
+ Process_Internal(renderOnly);
+}
+
+void CGUIWindowManager::Process_Internal(bool renderOnly /*= false*/)
+{
+ if (m_pCallback)
+ {
+ if (!renderOnly)
+ {
+ m_pCallback->Process();
+ m_pCallback->FrameMove();
+ }
+ m_pCallback->Render();
+ }
+}
+
+void CGUIWindowManager::SetCallback(IWindowManagerCallback& callback)
+{
+ m_pCallback = &callback;
+}
+
+void CGUIWindowManager::DeInitialize()
+{
+ for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++)
+ {
+ CGUIWindow* pWindow = (*it).second;
+ if (IsWindowActive(it->first))
+ {
+ pWindow->DisableAnimations();
+ CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0);
+ pWindow->OnMessage(msg);
+ }
+ pWindow->ResetControlStates();
+ pWindow->FreeResources(true);
+ }
+ UnloadNotOnDemandWindows();
+
+ m_vecMsgTargets.erase( m_vecMsgTargets.begin(), m_vecMsgTargets.end() );
+
+ // destroy our custom windows...
+ for (int i = 0; i < (int)m_vecCustomWindows.size(); i++)
+ {
+ CGUIWindow *pWindow = m_vecCustomWindows[i];
+ Remove(pWindow->GetID());
+ delete pWindow;
+ }
+
+ // clear our vectors of windows
+ m_vecCustomWindows.clear();
+ m_activeDialogs.clear();
+}
+
+/// \brief Route to a window
+/// \param pWindow Window to route to
+void CGUIWindowManager::RouteToWindow(CGUIWindow* dialog)
+{
+ // Just to be sure: Unroute this window,
+ // #we may have routed to it before
+ RemoveDialog(dialog->GetID());
+
+ m_activeDialogs.push_back(dialog);
+}
+
+/// \brief Unroute window
+/// \param id ID of the window routed
+void CGUIWindowManager::RemoveDialog(int id)
+{
+ for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it)
+ {
+ if ((*it)->GetID() == id)
+ {
+ m_activeDialogs.erase(it);
+ return;
+ }
+ }
+}
+
+bool CGUIWindowManager::HasModalDialog() const
+{
+ for (ciDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it)
+ {
+ CGUIWindow *window = *it;
+ if (window->IsModalDialog())
+ { // have a modal window
+ if (!window->IsAnimating(ANIM_TYPE_WINDOW_CLOSE))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CGUIWindowManager::HasDialogOnScreen() const
+{
+ return (m_activeDialogs.size() > 0);
+}
+
+/// \brief Get the ID of the top most routed window
+/// \return id ID of the window or WINDOW_INVALID if no routed window available
+int CGUIWindowManager::GetTopMostModalDialogID() const
+{
+ for (crDialog it = m_activeDialogs.rbegin(); it != m_activeDialogs.rend(); ++it)
+ {
+ CGUIWindow *dialog = *it;
+ if (dialog->IsModalDialog())
+ { // have a modal window
+ return dialog->GetID();
+ }
+ }
+ return WINDOW_INVALID;
+}
+
+void CGUIWindowManager::SendThreadMessage(CGUIMessage& message)
+{
+ ::EnterCriticalSection(&m_critSection );
+
+ CGUIMessage* msg = new CGUIMessage(message);
+ m_vecThreadMessages.push_back( pair<CGUIMessage*,int>(msg,0) );
+
+ ::LeaveCriticalSection(&m_critSection );
+}
+
+void CGUIWindowManager::SendThreadMessage(CGUIMessage& message, int window)
+{
+ ::EnterCriticalSection(&m_critSection );
+
+ CGUIMessage* msg = new CGUIMessage(message);
+ m_vecThreadMessages.push_back( pair<CGUIMessage*,int>(msg,window) );
+
+ ::LeaveCriticalSection(&m_critSection );
+}
+
+void CGUIWindowManager::DispatchThreadMessages()
+{
+ ::EnterCriticalSection(&m_critSection );
+ vector< pair<CGUIMessage*,int> > messages(m_vecThreadMessages);
+ m_vecThreadMessages.erase(m_vecThreadMessages.begin(), m_vecThreadMessages.end());
+ ::LeaveCriticalSection(&m_critSection );
+
+ while ( messages.size() > 0 )
+ {
+ vector< pair<CGUIMessage*,int> >::iterator it = messages.begin();
+ CGUIMessage* pMsg = it->first;
+ int window = it->second;
+ // first remove the message from the queue,
+ // else the message could be processed more then once
+ it = messages.erase(it);
+
+ if (window)
+ SendMessage( *pMsg, window );
+ else
+ SendMessage( *pMsg );
+ delete pMsg;
+ }
+}
+
+void CGUIWindowManager::AddMsgTarget( IMsgTargetCallback* pMsgTarget )
+{
+ m_vecMsgTargets.push_back( pMsgTarget );
+}
+
+int CGUIWindowManager::GetActiveWindow() const
+{
+ if (!m_windowHistory.empty())
+ return m_windowHistory.top();
+ return WINDOW_INVALID;
+}
+
+// same as GetActiveWindow() except it first grabs dialogs
+int CGUIWindowManager::GetFocusedWindow() const
+{
+ int dialog = GetTopMostModalDialogID();
+ if (dialog != WINDOW_INVALID)
+ return dialog;
+
+ return GetActiveWindow();
+}
+
+bool CGUIWindowManager::IsWindowActive(int id, bool ignoreClosing /* = true */) const
+{
+ // mask out multiple instances of the same window
+ id &= WINDOW_ID_MASK;
+ if ((GetActiveWindow() & WINDOW_ID_MASK) == id) return true;
+ // run through the dialogs
+ for (ciDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it)
+ {
+ CGUIWindow *window = *it;
+ if ((window->GetID() & WINDOW_ID_MASK) == id && (!ignoreClosing || !window->IsAnimating(ANIM_TYPE_WINDOW_CLOSE)))
+ return true;
+ }
+ return false; // window isn't active
+}
+
+bool CGUIWindowManager::IsWindowActive(const CStdString &xmlFile, bool ignoreClosing /* = true */) const
+{
+ CGUIWindow *window = GetWindow(GetActiveWindow());
+ if (window && CUtil::GetFileName(window->GetXMLFile()).Equals(xmlFile)) return true;
+ // run through the dialogs
+ for (ciDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it)
+ {
+ CGUIWindow *window = *it;
+ if (CUtil::GetFileName(window->GetXMLFile()).Equals(xmlFile) && (!ignoreClosing || !window->IsAnimating(ANIM_TYPE_WINDOW_CLOSE)))
+ return true;
+ }
+ return false; // window isn't active
+}
+
+bool CGUIWindowManager::IsWindowVisible(int id) const
+{
+ return IsWindowActive(id, false);
+}
+
+bool CGUIWindowManager::IsWindowVisible(const CStdString &xmlFile) const
+{
+ return IsWindowActive(xmlFile, false);
+}
+
+void CGUIWindowManager::LoadNotOnDemandWindows()
+{
+ for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++)
+ {
+ CGUIWindow *pWindow = (*it).second;
+ if (!pWindow ->GetLoadOnDemand())
+ {
+ pWindow->FreeResources(true);
+ pWindow->Initialize();
+ }
+ }
+}
+
+void CGUIWindowManager::UnloadNotOnDemandWindows()
+{
+ for (WindowMap::iterator it = m_mapWindows.begin(); it != m_mapWindows.end(); it++)
+ {
+ CGUIWindow *pWindow = (*it).second;
+ if (!pWindow->GetLoadOnDemand())
+ {
+ pWindow->FreeResources(true);
+ }
+ }
+}
+
+bool CGUIWindowManager::IsOverlayAllowed() const
+{
+ return m_bShowOverlay;
+}
+
+void CGUIWindowManager::ShowOverlay(CGUIWindow::OVERLAY_STATE state)
+{
+ if (state != CGUIWindow::OVERLAY_STATE_PARENT_WINDOW)
+ m_bShowOverlay = state == CGUIWindow::OVERLAY_STATE_SHOWN;
+}
+
+void CGUIWindowManager::HideOverlay(CGUIWindow::OVERLAY_STATE state)
+{
+ if (state == CGUIWindow::OVERLAY_STATE_HIDDEN)
+ m_bShowOverlay = false;
+}
+
+void CGUIWindowManager::AddToWindowHistory(int newWindowID)
+{
+ // Check the window stack to see if this window is in our history,
+ // and if so, pop all the other windows off the stack so that we
+ // always have a predictable "Back" behaviour for each window
+ stack<int> historySave = m_windowHistory;
+ while (historySave.size())
+ {
+ if (historySave.top() == newWindowID)
+ break;
+ historySave.pop();
+ }
+ if (!historySave.empty())
+ { // found window in history
+ m_windowHistory = historySave;
+ }
+ else
+ { // didn't find window in history - add it to the stack
+ m_windowHistory.push(newWindowID);
+ }
+}
+
+void CGUIWindowManager::GetActiveModelessWindows(vector<int> &ids)
+{
+ // run through our modeless windows, and construct a vector of them
+ // useful for saving and restoring the modeless windows on skin change etc.
+ for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it)
+ {
+ if (!(*it)->IsModalDialog())
+ ids.push_back((*it)->GetID());
+ }
+}
+
+CGUIWindow *CGUIWindowManager::GetTopMostDialog() const
+{
+ // find the window with the lowest render order
+ vector<CGUIWindow *> renderList = m_activeDialogs;
+ stable_sort(renderList.begin(), renderList.end(), RenderOrderSortFunction);
+
+ if (!renderList.size())
+ return NULL;
+
+ // return the last window in the list
+ return *renderList.rbegin();
+}
+
+bool CGUIWindowManager::IsWindowTopMost(int id) const
+{
+ CGUIWindow *topMost = GetTopMostDialog();
+ if (topMost && (topMost->GetID() & WINDOW_ID_MASK) == id)
+ return true;
+ return false;
+}
+
+bool CGUIWindowManager::IsWindowTopMost(const CStdString &xmlFile) const
+{
+ CGUIWindow *topMost = GetTopMostDialog();
+ if (topMost && CUtil::GetFileName(topMost->GetXMLFile()).Equals(xmlFile))
+ return true;
+ return false;
+}
+
+void CGUIWindowManager::ClearWindowHistory()
+{
+ while (m_windowHistory.size())
+ m_windowHistory.pop();
+}
+
+#ifdef _DEBUG
+void CGUIWindowManager::DumpTextureUse()
+{
+ CGUIWindow* pWindow = GetWindow(GetActiveWindow());
+ if (pWindow)
+ pWindow->DumpTextureUse();
+
+ for (iDialog it = m_activeDialogs.begin(); it != m_activeDialogs.end(); ++it)
+ {
+ if ((*it)->IsDialogRunning())
+ (*it)->DumpTextureUse();
+ }
+}
+#endif