mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-24 04:34:56 +01:00
734 lines
18 KiB
C++
734 lines
18 KiB
C++
|
#include <precomp.h>
|
||
|
#include "skinembed.h"
|
||
|
#include <api/wndmgr/layout.h>
|
||
|
#include <api/wnd/wndclass/wndholder.h>
|
||
|
#include <api/skin/skinparse.h>
|
||
|
#include <api/wnd/wndtrack.h>
|
||
|
#include <api/config/items/cfgitemi.h>
|
||
|
#include <api/config/items/attrint.h>
|
||
|
#include <bfc/named.h>
|
||
|
#include <api/wndmgr/autopopup.h>
|
||
|
#include <api/syscb/callbacks/wndcb.h>
|
||
|
#include <api/wndmgr/skinwnd.h>
|
||
|
#include <api/script/scriptmgr.h>
|
||
|
#include <bfc/critsec.h>
|
||
|
|
||
|
CriticalSection skinembed_cs;
|
||
|
|
||
|
SkinEmbedder *skinEmbedder = NULL;
|
||
|
|
||
|
SkinEmbedder::SkinEmbedder()
|
||
|
{
|
||
|
ASSERTPR(skinEmbedder == NULL, "only one skin embedder please!");
|
||
|
skinEmbedder = this;
|
||
|
}
|
||
|
|
||
|
SkinEmbedder::~SkinEmbedder()
|
||
|
{
|
||
|
inserted.deleteAll();
|
||
|
allofthem.deleteAll();
|
||
|
}
|
||
|
|
||
|
int SkinEmbedder::toggle(GUID g, const wchar_t *prefered_container, int container_flag, RECT *r, int transcient)
|
||
|
{
|
||
|
ifc_window *w = enumItem(g, 0);
|
||
|
if (w != NULL)
|
||
|
{
|
||
|
destroy(w, r);
|
||
|
return 0;
|
||
|
}
|
||
|
ifc_window *wnd = create(g, NULL, prefered_container, container_flag, r, transcient);
|
||
|
if (wnd == NULL)
|
||
|
{
|
||
|
#ifdef ON_CREATE_EXTERNAL_WINDOW_GUID
|
||
|
int y;
|
||
|
ON_CREATE_EXTERNAL_WINDOW_GUID(g, y);
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int SkinEmbedder::toggle(const wchar_t *groupid, const wchar_t *prefered_container, int container_flag, RECT *r, int transcient)
|
||
|
{
|
||
|
ifc_window *w = enumItem(groupid, 0);
|
||
|
if (w != NULL)
|
||
|
{
|
||
|
destroy(w, r);
|
||
|
return 0;
|
||
|
}
|
||
|
create(INVALID_GUID, groupid, prefered_container, container_flag, r, transcient);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ifc_window *SkinEmbedder::create(GUID g, const wchar_t *prefered_container, int container_flag, RECT *r, int transcient, int starthidden, int *isnew)
|
||
|
{
|
||
|
return create(g, NULL, prefered_container, container_flag, r, transcient, starthidden, isnew);
|
||
|
}
|
||
|
|
||
|
ifc_window *SkinEmbedder::create(const wchar_t *groupid, const wchar_t *prefered_container, int container_flag, RECT *r, int transcient, int starthidden, int *isnew)
|
||
|
{
|
||
|
return create(INVALID_GUID, groupid, prefered_container, container_flag, r, transcient, starthidden, isnew);
|
||
|
}
|
||
|
|
||
|
WindowHolder *SkinEmbedder::getSuitableWindowHolder(GUID g, const wchar_t *group_id, Container *cont, Layout *lay, int _visible, int _dynamic, int _empty, int _hasself, int _autoavail)
|
||
|
{
|
||
|
foreach(wndholders)
|
||
|
WindowHolder *h = wndholders.getfor();
|
||
|
|
||
|
ifc_window *w = h->getRootWndPtr()->getDesktopParent();
|
||
|
int dyn = 1;
|
||
|
int visible = 0;
|
||
|
int hasself = 0;
|
||
|
int empty = 0;
|
||
|
int autoavail = h->wndholder_isAutoAvailable();
|
||
|
|
||
|
Layout *l = (NULL != w) ? static_cast<Layout *>(w->getInterface(layoutGuid)) : NULL;
|
||
|
Container *c = NULL;
|
||
|
|
||
|
if (l)
|
||
|
{
|
||
|
c = l->getParentContainer();
|
||
|
if (c)
|
||
|
{
|
||
|
dyn = c->isDynamic();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NULL == w || !w->isInited()) visible = -1;
|
||
|
else
|
||
|
{
|
||
|
if (_visible == 1)
|
||
|
{
|
||
|
if (h->getRootWndPtr()->isVisible()) visible = 1;
|
||
|
}
|
||
|
else if (_visible == 0)
|
||
|
{
|
||
|
if (w->isVisible()) visible = 1;
|
||
|
}
|
||
|
}
|
||
|
if (!h->getCurRootWnd()) empty = 1;
|
||
|
|
||
|
if (g != INVALID_GUID)
|
||
|
{
|
||
|
if (g == h->getCurGuid())
|
||
|
hasself = 1;
|
||
|
}
|
||
|
else if (group_id && h->getCurGroupId())
|
||
|
{
|
||
|
if (!WCSICMP(group_id, h->getCurGroupId()))
|
||
|
hasself = 1;
|
||
|
}
|
||
|
|
||
|
if (_visible != -1)
|
||
|
{
|
||
|
if (visible != _visible) continue;
|
||
|
}
|
||
|
if (_dynamic != -1)
|
||
|
{
|
||
|
if (_dynamic != dyn) continue;
|
||
|
}
|
||
|
if (_empty != -1)
|
||
|
{
|
||
|
if (empty != _empty) continue;
|
||
|
}
|
||
|
if (_hasself != -1)
|
||
|
{
|
||
|
if (hasself != _hasself) continue;
|
||
|
}
|
||
|
if (_autoavail != -1)
|
||
|
{
|
||
|
if (autoavail != _autoavail) continue;
|
||
|
}
|
||
|
|
||
|
if (cont != NULL)
|
||
|
{
|
||
|
if (c != cont) continue;
|
||
|
}
|
||
|
|
||
|
if (lay != NULL)
|
||
|
{
|
||
|
if (l != lay) continue;
|
||
|
}
|
||
|
|
||
|
if (g != INVALID_GUID)
|
||
|
{
|
||
|
if (h->wantGuid(g)) return h;
|
||
|
}
|
||
|
else if (group_id)
|
||
|
{
|
||
|
if (h->wantGroup(group_id)) return h;
|
||
|
}
|
||
|
endfor;
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
ifc_window *SkinEmbedder::create(GUID g, const wchar_t *groupid, const wchar_t *prefered_container, int container_flag, RECT *r, int transcient, int starthidden, int *isnew)
|
||
|
{
|
||
|
// InCriticalSection in_cs(&skinembed_cs);
|
||
|
|
||
|
foreach(in_deferred_callback)
|
||
|
SkinEmbedEntry *e = in_deferred_callback.getfor();
|
||
|
if ((e->guid != INVALID_GUID && e->guid == g) || WCSCASEEQLSAFE(groupid, e->groupid))
|
||
|
{
|
||
|
#ifdef _DEBUG
|
||
|
DebugStringW(L"trying to show a window that is being destroyed, hm, try again later\n");
|
||
|
#endif
|
||
|
// too soon! try later dude
|
||
|
return NULL;
|
||
|
}
|
||
|
endfor;
|
||
|
|
||
|
RECT destrect = {0};
|
||
|
|
||
|
if (isnew) *isnew = 0;
|
||
|
|
||
|
WindowHolder *wh = NULL;
|
||
|
// todo: get from c++ callback
|
||
|
|
||
|
if (SOM::checkAbortShowHideWindow(g, 1))
|
||
|
return NULL;
|
||
|
|
||
|
if (g != INVALID_GUID)
|
||
|
wh = SOM::getSuitableWindowHolderFromScript(g);
|
||
|
|
||
|
if (!wh) wh = getSuitableWindowHolder(g, groupid, NULL, NULL, 1 /*visible*/, 0 /*static*/, 1 /*empty*/, -1 /*donttest*/, -1 /*donttest*/);
|
||
|
if (!wh) wh = getSuitableWindowHolder(g, groupid, NULL, NULL, 0 /*hidden*/, 0 /*static*/, 0 /*notempty*/, 1 /*hasself*/, -1 /*donttest*/);
|
||
|
if (!wh) wh = getSuitableWindowHolder(g, groupid, NULL, NULL, 0 /*hidden*/, 0 /*static*/, 1 /*empty*/, -1 /*donttest*/, 1 /*autoavail*/);
|
||
|
if (!wh) wh = getSuitableWindowHolder(g, groupid, NULL, NULL, 1 /*visible*/, 1 /*dynamic*/, 1 /*empty*/, -1 /*donttest*/, -1 /*donttest*/);
|
||
|
ifc_window *whrw = wh ? wh->getRootWndPtr() : NULL;
|
||
|
Container *cont = NULL;
|
||
|
Layout *lay = NULL;
|
||
|
ifc_window *wnd = NULL;
|
||
|
int newcont = 0;
|
||
|
|
||
|
if (!wh)
|
||
|
{ // no hidden static container, so lets create a dynamic one
|
||
|
if (isnew) *isnew = 1;
|
||
|
if (container_flag == 0 && (prefered_container == NULL || !*prefered_container))
|
||
|
{
|
||
|
prefered_container = AutoPopup::getDefaultContainerParams(groupid, g, &container_flag);
|
||
|
}
|
||
|
if (container_flag == 0 && (prefered_container == NULL || !*prefered_container))
|
||
|
{
|
||
|
prefered_container = WASABI_DEFAULT_STDCONTAINER;
|
||
|
}
|
||
|
cont = SkinParser::loadContainerForWindowHolder(groupid, g, 0, transcient, prefered_container, container_flag);
|
||
|
if (cont)
|
||
|
{
|
||
|
cont->setTranscient(transcient);
|
||
|
newcont = 1;
|
||
|
lay = cont->enumLayout(0);
|
||
|
/* if (prefered_layout) { // find its target layout
|
||
|
cont->setDefaultLayout(prefered_layout);
|
||
|
lay = cont->getLayout(prefered_layout);
|
||
|
if (!lay) {
|
||
|
if (!layout_flag) // see if we can fallback
|
||
|
lay = cont->enumLayout(0);
|
||
|
else {
|
||
|
destroyContainer(cont); // deferred
|
||
|
api->console_outputString(9, StringPrintf("could not find the requested layout (%s) to host the window", prefered_container));
|
||
|
return NULL;
|
||
|
}
|
||
|
}*/
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DebugStringW(L"no container found to hold the window... not even a default one :/\n");
|
||
|
}
|
||
|
wh = getSuitableWindowHolder(g, groupid, cont, lay, -1 /*donttest*/, -1 /*donttest*/, 0 /*notempty*/, 1 /*hasself*/, -1 /*donttest*/);
|
||
|
if (!wh) wh = getSuitableWindowHolder(g, groupid, cont, lay, -1 /*donttest*/, -1 /*donttest*/, 1 /*empty*/, -1 /*donttest*/, -1 /*donttest*/);
|
||
|
whrw = wh ? wh->getRootWndPtr() : NULL;
|
||
|
}
|
||
|
|
||
|
if (wh)
|
||
|
{
|
||
|
GuiObject *o = static_cast<GuiObject *>(whrw->getInterface(guiObjectGuid));
|
||
|
ASSERT(o != NULL);
|
||
|
if (o)
|
||
|
{
|
||
|
lay = o->guiobject_getParentLayout();
|
||
|
if (lay)
|
||
|
cont = lay->getParentContainer();
|
||
|
}
|
||
|
if ((g != INVALID_GUID && (g == wh->getCurGuid())) || (groupid && (wh->getCurGroupId() == groupid)))
|
||
|
wnd = wh->getCurRootWnd();
|
||
|
else
|
||
|
{
|
||
|
if (wh->getCurRootWnd())
|
||
|
wh->onRemoveWindow();
|
||
|
wnd = wh->onInsertWindow(g, groupid);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!wnd)
|
||
|
{
|
||
|
if (cont)
|
||
|
{
|
||
|
if (!WCSCASEEQLSAFE(cont->getId(), L"main"))
|
||
|
cont->close();
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//int anim = 1;
|
||
|
//if (wh && !whrw->getAnimatedRects()) anim = 0; // FIXME!!
|
||
|
|
||
|
if (lay && r)
|
||
|
{
|
||
|
lay->getWindowRect(&destrect);
|
||
|
}
|
||
|
|
||
|
if (cont /*&& cont->isDynamic()*/)
|
||
|
{
|
||
|
const wchar_t *text = wnd->getRootWndName();
|
||
|
cont->setTranscient(transcient);
|
||
|
if (text != NULL)
|
||
|
if (cont->isDynamic()) cont->setName(text);
|
||
|
if (cont->isDynamic() && !transcient) cont->resetLayouts();
|
||
|
if (newcont) cont->onInit(1);
|
||
|
}
|
||
|
|
||
|
#ifdef WASABI_COMPILE_CONFIG
|
||
|
// {280876CF-48C0-40bc-8E86-73CE6BB462E5}
|
||
|
const GUID options_guid =
|
||
|
{ 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
|
||
|
CfgItem *cfgitem = WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid);
|
||
|
int findopenrect = _int_getValue(cfgitem, L"Find open rect");
|
||
|
#else
|
||
|
int findopenrect = WASABI_WNDMGR_FINDOPENRECT;
|
||
|
#endif
|
||
|
|
||
|
if (wh && findopenrect)
|
||
|
{
|
||
|
if (lay)
|
||
|
{
|
||
|
RECT rl;
|
||
|
lay->getWindowRect(&rl);
|
||
|
RECT nr = windowTracker->findOpenRect(rl, lay);
|
||
|
destrect = nr; // rewrite destrect
|
||
|
int w = rl.right - rl.left;
|
||
|
int h = rl.bottom - rl.top;
|
||
|
lay->divRatio(&w, &h);
|
||
|
nr.right = nr.left + w;
|
||
|
nr.bottom = nr.top + h;
|
||
|
lay->resizeToRect(&nr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (wh)
|
||
|
{
|
||
|
if (r)
|
||
|
/*if (anim)*/ WASABI_API_WNDMGR->drawAnimatedRects(r, &destrect);
|
||
|
/*else
|
||
|
{
|
||
|
RECT r;
|
||
|
r.left = destrect.left + (destrect.right - destrect.left) / 2 - 1;
|
||
|
r.top = destrect.top + (destrect.bottom - destrect.top) / 2 + 1;
|
||
|
r.right = r.left + 2;
|
||
|
r.bottom = r.top + 2;
|
||
|
if (anim) WASABI_API_WNDMGR->drawAnimatedRects(&r, &destrect);
|
||
|
}*/
|
||
|
}
|
||
|
|
||
|
if (!starthidden)
|
||
|
{
|
||
|
if (cont && cont->isVisible())
|
||
|
{ // we were already shown, duh
|
||
|
// cont->setVisible(0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (cont) cont->setVisible(1);
|
||
|
else if (lay) lay->setVisible(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (wnd && newcont && !transcient)
|
||
|
{
|
||
|
inserted.addItem(new SkinEmbedEntry(wnd->getDependencyPtr(), wnd, g, groupid, prefered_container, container_flag, cont, wh));
|
||
|
viewer_addViewItem(wnd->getDependencyPtr());
|
||
|
}
|
||
|
|
||
|
if (!transcient && wnd)
|
||
|
allofthem.addItem(new SkinEmbedEntry(wnd->getDependencyPtr(), wnd, g, groupid, prefered_container, container_flag, cont, wh));
|
||
|
|
||
|
return wnd;
|
||
|
}
|
||
|
|
||
|
void SkinEmbedder::destroy(ifc_window *w, RECT *r)
|
||
|
{
|
||
|
int donecheck = 0;
|
||
|
SkinEmbedEntry *e = NULL;
|
||
|
for (int i = 0; i < allofthem.getNumItems();i++)
|
||
|
{
|
||
|
e = allofthem.enumItem(i);
|
||
|
if (e->wnd == w)
|
||
|
{
|
||
|
donecheck = 1;
|
||
|
if (SOM::checkAbortShowHideWindow(e->guid, 0))
|
||
|
return ;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (WASABI_API_WND->rootwndIsValid(w))
|
||
|
{
|
||
|
if (!donecheck)
|
||
|
{
|
||
|
ifc_window *ww = w->findWindowByInterface(windowHolderGuid);
|
||
|
if (ww)
|
||
|
{
|
||
|
WindowHolder *wh = static_cast<WindowHolder*>(ww->getInterface(windowHolderGuid));
|
||
|
if (wh)
|
||
|
{
|
||
|
GUID g = wh->getCurGuid();
|
||
|
if (g != INVALID_GUID)
|
||
|
{
|
||
|
donecheck = 1;
|
||
|
if (SOM::checkAbortShowHideWindow(g, 0))
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// checkAbort can render w invalid !!! check again
|
||
|
if (WASABI_API_WND->rootwndIsValid(w))
|
||
|
{
|
||
|
ifc_window *wnd = w->getDesktopParent();
|
||
|
GuiObject *go = static_cast<GuiObject *>(wnd->getInterface(guiObjectGuid));
|
||
|
if (go)
|
||
|
{
|
||
|
Layout *l = go->guiobject_getParentLayout();
|
||
|
if (l)
|
||
|
{
|
||
|
Container *c = l->getParentContainer();
|
||
|
if (c)
|
||
|
{
|
||
|
if (!WCSCASEEQLSAFE(c->getId(), L"main"))
|
||
|
{
|
||
|
c->close(); // deferred if needed
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
softclose:
|
||
|
ifc_window *wnd = w->findWindowByInterface(windowHolderGuid);
|
||
|
if (wnd != NULL)
|
||
|
{
|
||
|
WindowHolder *wh = static_cast<WindowHolder *>(wnd->getInterface(windowHolderGuid));
|
||
|
if (wh != NULL)
|
||
|
{
|
||
|
wh->onRemoveWindow(1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else goto softclose;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int SkinEmbedder::getNumItems(GUID g)
|
||
|
{
|
||
|
int n = 0;
|
||
|
for (int i = 0;i < wndholders.getNumItems();i++)
|
||
|
if (wndholders.enumItem(i)->getRootWndPtr()->isVisible() && wndholders.enumItem(i)->getCurGuid() == g) n++;
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
int SkinEmbedder::getNumItems(const wchar_t *groupid)
|
||
|
{
|
||
|
int n = 0;
|
||
|
for (int i = 0;i < wndholders.getNumItems();i++)
|
||
|
{
|
||
|
WindowHolder *wh = wndholders.enumItem(i);
|
||
|
if (wh->getRootWndPtr()->isVisible()
|
||
|
&& WCSCASEEQLSAFE(wh->getCurGroupId(), groupid))
|
||
|
n++;
|
||
|
}
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
ifc_window *SkinEmbedder::enumItem(GUID g, int n)
|
||
|
{
|
||
|
ASSERT(n >= 0);
|
||
|
for (int i = 0;i < wndholders.getNumItems();i++)
|
||
|
{
|
||
|
WindowHolder *wh = wndholders.enumItem(i);
|
||
|
if (wh->getCurGuid() == g)
|
||
|
{
|
||
|
ifc_window *w = wh->getRootWndPtr();
|
||
|
Container *c = NULL;
|
||
|
if (w)
|
||
|
{
|
||
|
w = w->getDesktopParent();
|
||
|
if (w)
|
||
|
{
|
||
|
Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
|
||
|
if (l)
|
||
|
{
|
||
|
c = l->getParentContainer();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (c && c->isVisible() || (!c && wndholders.enumItem(i)->getRootWndPtr()->isVisible()))
|
||
|
{
|
||
|
if (n == 0)
|
||
|
return wndholders.enumItem(i)->getCurRootWnd();
|
||
|
n--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
ifc_window *SkinEmbedder::enumItem(const wchar_t *groupid, int n)
|
||
|
{
|
||
|
ASSERT(n >= 0);
|
||
|
for (int i = 0;i < wndholders.getNumItems();i++)
|
||
|
{
|
||
|
WindowHolder *wh = wndholders.enumItem(i);
|
||
|
const wchar_t *curgroupid = wndholders[i]->getCurGroupId();
|
||
|
if (WCSCASEEQLSAFE(curgroupid, groupid))
|
||
|
{
|
||
|
ifc_window *w = wh->getRootWndPtr();
|
||
|
Container *c = NULL;
|
||
|
if (w)
|
||
|
{
|
||
|
w = w->getDesktopParent();
|
||
|
if (w)
|
||
|
{
|
||
|
Layout *l = static_cast<Layout *>(w->getInterface(layoutGuid));
|
||
|
if (l)
|
||
|
{
|
||
|
c = l->getParentContainer();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (c && c->isVisible() || (!c && wndholders.enumItem(i)->getRootWndPtr()->isVisible()))
|
||
|
{
|
||
|
if (n == 0)
|
||
|
return wndholders.enumItem(i)->getCurRootWnd();
|
||
|
n--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void SkinEmbedder::registerWindowHolder(WindowHolder *wh)
|
||
|
{
|
||
|
if (wndholders.haveItem(wh)) return ;
|
||
|
wndholders.addItem(wh);
|
||
|
}
|
||
|
|
||
|
void SkinEmbedder::unregisterWindowHolder(WindowHolder *wh)
|
||
|
{
|
||
|
if (!wndholders.haveItem(wh)) return ;
|
||
|
wndholders.removeItem(wh);
|
||
|
}
|
||
|
|
||
|
int SkinEmbedder::viewer_onItemDeleted(api_dependent *item)
|
||
|
{
|
||
|
foreach(in_deferred_callback)
|
||
|
if (in_deferred_callback.getfor()->dep == item)
|
||
|
in_deferred_callback.removeByPos(foreach_index);
|
||
|
endfor
|
||
|
foreach(inserted)
|
||
|
SkinEmbedEntry *e = inserted.getfor();
|
||
|
if (e->dep == item)
|
||
|
{
|
||
|
inserted.removeItem(e);
|
||
|
allofthem.removeItem(e);
|
||
|
delete e;
|
||
|
break;
|
||
|
}
|
||
|
endfor;
|
||
|
foreach(allofthem)
|
||
|
SkinEmbedEntry *e = allofthem.getfor();
|
||
|
if (e->dep == item)
|
||
|
{
|
||
|
allofthem.removeItem(e);
|
||
|
delete e;
|
||
|
break;
|
||
|
}
|
||
|
endfor;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void SkinEmbedder::cancelDestroyContainer(Container *c)
|
||
|
{
|
||
|
if (!cancel_deferred_destroy.haveItem(c)) cancel_deferred_destroy.addItem(c);
|
||
|
}
|
||
|
|
||
|
void SkinEmbedder::destroyContainer(Container *o)
|
||
|
{
|
||
|
ASSERT(o);
|
||
|
//fg>disabled as of 11/4/2003, side effect of cancelling fullscreen video (ie, notifier while playing video fullscreen)
|
||
|
//delt with the problem in basewnd directly
|
||
|
//#ifdef WIN32
|
||
|
//SetFocus(NULL); // FG> this avoids Win32 calling directly WM_KILLFOCUS into a child's wndproc (couldn't they just have posted the damn msg ?), who would then call some of his parent's virtual functions while it is being deleted
|
||
|
// perhaps it would be good to add a generic way to disable most child wnd messages while the parent is being deleted
|
||
|
//#endif
|
||
|
|
||
|
cancel_deferred_destroy.removeItem(o);
|
||
|
|
||
|
foreach(inserted)
|
||
|
SkinEmbedEntry *e = inserted.getfor();
|
||
|
if (e->container == o)
|
||
|
{
|
||
|
if (!in_deferred_callback.haveItem(e))
|
||
|
in_deferred_callback.addItem(e);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
endfor
|
||
|
deferred_destroy.addItem(o);
|
||
|
timerclient_setTimer(CB_DESTROYCONTAINER, 20);
|
||
|
//o->setVisible(0);
|
||
|
//timerclient_postDeferredCallback(CB_DESTROYCONTAINER, (intptr_t)o);
|
||
|
}
|
||
|
|
||
|
void SkinEmbedder::timerclient_timerCallback(int id)
|
||
|
{
|
||
|
if (id == CB_DESTROYCONTAINER)
|
||
|
{
|
||
|
foreach(deferred_destroy)
|
||
|
Container *c = deferred_destroy.getfor();
|
||
|
foreach(in_deferred_callback)
|
||
|
if (in_deferred_callback.getfor()->container == c)
|
||
|
{
|
||
|
in_deferred_callback.removeByPos(foreach_index);
|
||
|
}
|
||
|
endfor;
|
||
|
if (cancel_deferred_destroy.haveItem(c))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
if (SkinParser::isContainer(c)) // otherwise i'ts already gone while we were waiting for the callback, duh!
|
||
|
delete c;
|
||
|
endfor
|
||
|
cancel_deferred_destroy.removeAll();
|
||
|
deferred_destroy.removeAll();
|
||
|
timerclient_killTimer(CB_DESTROYCONTAINER);
|
||
|
return ;
|
||
|
}
|
||
|
TimerClientDI::timerclient_timerCallback(id);
|
||
|
}
|
||
|
|
||
|
int SkinEmbedder::timerclient_onDeferredCallback(intptr_t p1, intptr_t p2)
|
||
|
{
|
||
|
return TimerClientDI::timerclient_onDeferredCallback(p1, p2);
|
||
|
}
|
||
|
|
||
|
#ifdef WASABI_COMPILE_CONFIG
|
||
|
void SkinEmbedder::saveState()
|
||
|
{
|
||
|
int i = 0;
|
||
|
wchar_t t[1024] = {0};
|
||
|
foreach(inserted)
|
||
|
SkinEmbedEntry *e = inserted.getfor();
|
||
|
if (e->guid != INVALID_GUID)
|
||
|
{
|
||
|
nsGUID::toCharW(e->guid, t);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WCSCPYN(t, e->groupid, 1024);
|
||
|
}
|
||
|
WASABI_API_CONFIG->setStringPrivate(StringPrintfW(L"wndstatus/id/%d", i), t);
|
||
|
WASABI_API_CONFIG->setStringPrivate(StringPrintfW(L"wndstatus/layout/%d", i), !e->layout.isempty() ? e->layout.getValue() : L"");
|
||
|
WASABI_API_CONFIG->setIntPrivate(StringPrintfW(L"wndstatus/flag/%d", i), e->required);
|
||
|
i++;
|
||
|
endfor;
|
||
|
WASABI_API_CONFIG->setStringPrivate(StringPrintfW(L"wndstatus/id/%d", i), L"");
|
||
|
WASABI_API_CONFIG->setStringPrivate(StringPrintfW(L"wndstatus/layout/%d", i), L"");
|
||
|
WASABI_API_CONFIG->setIntPrivate(StringPrintfW(L"wndstatus/flag/%d", i), 0);
|
||
|
}
|
||
|
|
||
|
void SkinEmbedder::restoreSavedState()
|
||
|
{
|
||
|
int i = 0;
|
||
|
wchar_t t[1024] = {0};
|
||
|
wchar_t l[256] = {0};
|
||
|
while (1)
|
||
|
{
|
||
|
WASABI_API_CONFIG->getStringPrivate(StringPrintfW(L"wndstatus/id/%d", i), t, 1024, L"");
|
||
|
if (!*t) break;
|
||
|
WASABI_API_CONFIG->getStringPrivate(StringPrintfW(L"wndstatus/layout/%d", i), l, 256, L"");
|
||
|
int flag = WASABI_API_CONFIG->getIntPrivate(StringPrintfW(L"wndstatus/flag/%d", i), 0);
|
||
|
GUID g = nsGUID::fromCharW(t);
|
||
|
//ifc_window *created = NULL;
|
||
|
//int tried = 0;
|
||
|
if (g != INVALID_GUID)
|
||
|
{
|
||
|
ifc_window *w = enumItem(g, 0);
|
||
|
if (w == NULL)
|
||
|
{
|
||
|
//tried = 1;
|
||
|
/*created = */create(g, l, flag);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ifc_window *w = enumItem(t, 0);
|
||
|
if (w == NULL)
|
||
|
{
|
||
|
//tried = 1;
|
||
|
/*created = */create(t, l, flag);
|
||
|
}
|
||
|
}
|
||
|
/* if (tried && !created) {
|
||
|
for (int j=0;j<inserted.getNumItems();j++) {
|
||
|
SkinEmbedEntry *e = inserted.enumItem(j);
|
||
|
int yes = 0;
|
||
|
if (g != INVALID_GUID) {
|
||
|
if (e->guid == g && e->required == flag && STRCASEEQLSAFE(e->layout, l))
|
||
|
yes = 1;
|
||
|
} else {
|
||
|
if (STRCASEEQLSAFE(e->groupid, t) && e->required == flag && STRCASEEQLSAFE(e->layout, l))
|
||
|
yes = 1;
|
||
|
}
|
||
|
if (yes) {
|
||
|
inserted.removeByPos(j);
|
||
|
j--;
|
||
|
delete e;
|
||
|
}
|
||
|
}
|
||
|
}*/
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void SkinEmbedder::attachToSkin(ifc_window *w, int side, int size)
|
||
|
{
|
||
|
RECT r;
|
||
|
if (w == NULL) return ;
|
||
|
ifc_window *_w = w->getDesktopParent();
|
||
|
if (_w == NULL) _w = w;
|
||
|
SkinParser::getSkinRect(&r, _w);
|
||
|
|
||
|
switch (side)
|
||
|
{
|
||
|
case SKINWND_ATTACH_RIGHT:
|
||
|
_w->resize(r.right, r.top, size, r.bottom - r.top);
|
||
|
break;
|
||
|
case SKINWND_ATTACH_TOP:
|
||
|
_w->resize(r.left, r.top - size, r.right - r.left, size);
|
||
|
break;
|
||
|
case SKINWND_ATTACH_LEFT:
|
||
|
_w->resize(r.left - size, r.top, size, r.bottom - r.top);
|
||
|
break;
|
||
|
case SKINWND_ATTACH_BOTTOM:
|
||
|
_w->resize(r.left, r.bottom, r.right - r.left, size);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PtrList<SkinEmbedEntry> SkinEmbedder::in_deferred_callback;
|
||
|
PtrList<Container> SkinEmbedder::cancel_deferred_destroy;
|
||
|
PtrList<Container> SkinEmbedder::deferred_destroy;
|