diff options
Diffstat (limited to 'Src/Wasabi/api/wndmgr')
30 files changed, 8230 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wndmgr/alphamgr.cpp b/Src/Wasabi/api/wndmgr/alphamgr.cpp new file mode 100644 index 00000000..0bcf7fe0 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/alphamgr.cpp @@ -0,0 +1,661 @@ +#include <precomp.h> +#include "alphamgr.h" +#include <api/wndmgr/layout.h> +#include <api/skin/skinparse.h> +#ifdef _WIN32 +#include <tataki/blending/blending.h> +#endif +#include <bfc/util/profiler.h> +#include <bfc/wasabi_std_wnd.h> + +#ifndef PI +#define PI 3.1415926536 +#endif + +#define ALPHAMGR_HOVERCHECK 100 +#define ALPHAMGR_UPDATEALPHA 200 + +AlphaMgr::AlphaMgr() { + overlayout = NULL; + timerclient_setTimer(ALPHAMGR_HOVERCHECK, 200); + alllinked = 0; + autoopacify = 0; + fast_timer_on = 0; + big_curtransparency = 0; + big_status = STATUS_UNKNOWN; + big_startalpha = 0; + big_lasttimein = 0; + extend_px = 0; + global_alpha = 0; + big_enterleave_time = 0; + fadein_ms = 1; + fadeout_ms = 1; + holdtime_ms = 1; +} + +AlphaMgr::~AlphaMgr() +{ + timerclient_killTimer(ALPHAMGR_HOVERCHECK); +} + +void AlphaMgr::addLayout(Layout *l) +{ + checkTimer(); + + if (layouts.findItem((const wchar_t *)l)) + return; + + layouts.addItem(new AlphaMgrEntry(l)); +} + +void AlphaMgr::removeLayout(Layout *l) { + int p=-1; + AlphaMgrEntry *e = layouts.findItem((const wchar_t *)l, &p); + if (p != -1) { + if (e->getStatus() == STATUS_IN_FADINGON || e->getStatus() == STATUS_IN_ON) { + updateInList(e, 0); + checkTimer(); + } + layouts.removeByPos(p); + in_layouts.removeItem(e); + delete e; + checkTimer(); + } +} + +// gets the currently needed transparency, according to layout overrides and global link, and then applies this +// transparency to the layout, it does not change anything in any data structure, this is only a visual update function +void AlphaMgr::updateTransparency(Layout *l) { + if (!l) return; + if (l->isInited()) { + if (l->isTransparencySafe()) { + int a = l->getTransparencyOverride(); + if (a == -1) { + if (l->getNoParent()!=1) { + if (a == -1 && hasAutoOpacity(l)) + a = getTransparency(l); + else if (a == -1 && getAllLinked()) + a = getGlobalAlpha(); + } + if (a == -1) { + /* why the hell would it care if it's alllinked if it's an independent window ?? (noparent=1) + if (getAllLinked()) + a = getGlobalAlpha(); + else + */ + a = l->getPaintingAlpha(); + } + } + l->setTransparency(a); + } else { + l->setTransparency(255); + } + } +} + +// returns the alpha value for this slot, that's not necessarily the transparency that should be applied to the layout +// since overrides & calculations in updateTransparency and getTransparency should apply. +int AlphaMgr::getAlpha(AlphaMgrEntry *e) { + if (alllinked && e->getLayout()->getNoParent() != 1) return getGlobalAlpha(); + return e->getLayout()->getAlpha(); +} + +int AlphaMgr::getAlpha(Layout *l) { + int p=-1; + AlphaMgrEntry *e = layouts.findItem((const wchar_t *)l, &p); + if (p != -1) return getAlpha(e); + return l->getAlpha(); +} + +int AlphaMgr::getGlobalAlpha() { + return global_alpha; +} + +void AlphaMgr::updateAllTransparency() { + foreach(layouts) + updateTransparency(layouts.getfor()->getLayout()); + endfor; +} + +void AlphaMgr::setGlobalAlpha(int a) { + global_alpha = a; + updateAllTransparency(); +} + +int AlphaMgr::getCurve(AlphaMgrEntry *e) { + int n; + int status = e ? e->getStatus() : getBigStatus(); + if (e == NULL) { + n = MulDiv(Wasabi::Std::getTickCount()-getBigEnterLeaveTime(),256,status == STATUS_IN_FADINGON ? fadein_ms : fadeout_ms); + if (n > 255) n = 255; if (n < 0) n = 0; + } else { + if (e->getEnterLeaveTime() == -1) return -1; + n = MulDiv(Wasabi::Std::getTickCount()-e->getEnterLeaveTime(),256,status == STATUS_IN_FADINGON ? fadein_ms : fadeout_ms); + if (n > 255) n = 255; if (n < 0) n = 0; + } + return n; +} + +// returns the value of the transparency if no override applies, you still need to check overrides (see updatetransparency) +int AlphaMgr::getTransparency(Layout *l) { + if (getAutoOpacify()) + l = NULL; + if (l == NULL) { + if (getBigStatus() == STATUS_UNKNOWN) { + setBigStatus(STATUS_OUT_OFF); + Layout *main = SkinParser::getMainLayout(); + if (main) + big_curtransparency = main->getTransparency(); + else + big_curtransparency = 255; + } + } + AlphaMgrEntry *e = NULL; + if (l) e = layouts.findItem((const wchar_t *)l); + int s = e ? e->getStatus() : getBigStatus(); + if (e && s == STATUS_UNKNOWN) { + initStatus(e); + s = e->getStatus(); + } + switch (s) { + case STATUS_IN_OFF: return e ? getAlpha(e) : getGlobalAlpha(); + case STATUS_OUT_OFF: return e ? getAlpha(e) : getGlobalAlpha(); + case STATUS_IN_ON: return 255; + case STATUS_OUT_FADINGOUT: { + int n = e ? getCurve(e) : getCurve(NULL); + float sintrans = (float)(sin(((float)n/255)*PI-PI/2)/2+0.5); + int na; + if (e) + na = (int)(((float)(getAlpha(e) - e->getStartAlpha()) * sintrans) + e->getStartAlpha()); + else + na = (int)(((float)(getGlobalAlpha() - getBigStartAlpha()) * sintrans) + getBigStartAlpha()); + return na; + } + case STATUS_IN_FADINGON: { + int n = e ? getCurve(e) : getCurve(NULL); + float sintrans = (float)(sin(((float)n/255)*PI-PI/2)/2+0.5); + int na; + if (e) + na = (int)(((float)(255 - e->getStartAlpha()) * sintrans) + e->getStartAlpha()); + else + na = (int)(((float)(255 - getBigStartAlpha()) * sintrans) + getBigStartAlpha()); + return na; + } + default: return e ? getAlpha(e) : getGlobalAlpha(); + } +} + +int AlphaMgr::hasAutoOpacityOnHover(Layout *l) { + AlphaMgrEntry *e = layouts.findItem((const wchar_t *)l); + if (e) return hasAutoOpacityOnHover(e); + return 0; +} + +int AlphaMgr::hasAutoOpacity(Layout *l) { + AlphaMgrEntry *e = layouts.findItem((const wchar_t *)l); + if (e) return hasAutoOpacity(e); + return 0; +} + +int AlphaMgr::hasAutoOpacityOnFocus(Layout *l) { + AlphaMgrEntry *e = layouts.findItem((const wchar_t *)l); + if (e) return hasAutoOpacityOnFocus(e); + return 0; +} + +int AlphaMgr::hasAutoOpacityOnFocus(AlphaMgrEntry *e) { + if (alllinked) return autoopacify == 2; + return e->getLayout()->getAutoOpacify() == 2 && e->getLayout()->getNoParent() != 1; +} + +int AlphaMgr::hasAutoOpacityOnHover(AlphaMgrEntry *e) { + if (alllinked) return autoopacify == 1; + return e->getLayout()->getAutoOpacify() == 1 && e->getLayout()->getNoParent() != 1; +} + +int AlphaMgr::hasAutoOpacity(AlphaMgrEntry *e) { + if (alllinked) return autoopacify; + return e->getLayout()->getAutoOpacify() && e->getLayout()->getNoParent() != 1; +} + +// we got a new layout to manage, and its status flags is not set, we should init it to something safe +void AlphaMgr::initStatus(AlphaMgrEntry *l, int applytransparency) { + if (isMouseInLayout(l->getLayout())) { + l->setEnterLeaveTime((uint32_t)-1); + if (hasAutoOpacity(l)) { + l->setStatus(STATUS_IN_FADINGON); + l->onEnterLeave(); + l->setStartAlpha(l->getLayout()->getTransparency()); + checkTimer(); + } else { + l->setStatus(STATUS_IN_OFF); + } + l->getLayout()->onMouseEnterLayout(); + } else { + if (hasAutoOpacityOnHover(l)) { + l->setStartAlpha(l->getLayout()->getTransparency()); + l->onEnterLeave(); + l->setStatus(STATUS_OUT_FADINGOUT); + checkTimer(); + } else { + l->setStatus(STATUS_OUT_OFF); + } + l->getLayout()->onMouseLeaveLayout(); + } + if (applytransparency) updateTransparency(l->getLayout()); +} + +int AlphaMgr::isPointInLayout(Layout *l, int x, int y, api_region **rgn) +{ + api_region *rg = NULL; + if (!l) return 0; + if (!l->isVisible()) return 0; + RECT r,r2; + l->getClientRect(&r); + if (l->renderRatioActive()) l->multRatio(&r); + l->getWindowRect(&r2); + Wasabi::Std::offsetRect(&r, r2.left, r2.top); +// OffsetRect(&r, r2.left, r2.top); + if (x < r.left || x > r.right || y < r.top || y > r.bottom) return 0; + if (rgn) { + if (!*rgn) { + rg = l->getComposedRegion(); + *rgn = rg; + } else { + rg = *rgn; + } + } else { + rg = l->getComposedRegion(); + } + if (!rgn) return 1; + x -= r.left; y -= r.top; + POINT pt={x,y}; + if (l->renderRatioActive()) l->divRatio((int*)&pt.x, (int*)&pt.y); + if (l->getComposedRegion()->ptInRegion(&pt)) return 1; + return 0; +} + +int AlphaMgr::isFocusInLayout(Layout *l) { + if (l->gotFocus()) return 1; + OSWINDOWHANDLE fw = Wasabi::Std::Wnd::getFocus(); + while (fw) + { + if (fw == l->gethWnd()) return 1; + fw = Wasabi::Std::Wnd::getParent(fw); + } + return 0; +} + +int AlphaMgr::isMouseInLayout(Layout *l) { + int isin = 0; + if (hasAutoOpacityOnFocus(l)) { + return isFocusInLayout(l); + } else { + int x, y; + api_region *r = NULL; + Wasabi::Std::getMousePos(&x, &y); + isin = isPointInLayout(l, x, y, &r); + int ext = getExtendAutoOpacity(); + if (!isin && ext > 0) { + isin = isPointInLayout(l, x-ext, y, &r); + if (!isin) isin = isPointInLayout(l, x-ext, y-ext, &r); + if (!isin) isin = isPointInLayout(l, x, y-ext, &r); + if (!isin) isin = isPointInLayout(l, x+ext, y-ext, &r); + if (!isin) isin = isPointInLayout(l, x+ext, y, &r); + if (!isin) isin = isPointInLayout(l, x+ext, y+ext, &r); + if (!isin) isin = isPointInLayout(l, x, y+ext, &r); + if (!isin) isin = isPointInLayout(l, x-ext, y+ext, &r); + if (!isin) isin = isPointInLayout(l, x-ext, y, &r); + } + } + return isin; +} + +int AlphaMgr::needForcedTransparencyFlag(Layout *l) { + if (!l->isTransparencySafe()) return 0; + if (l->isAlphaForced()) return 1; + if (l->getTransparencyOverride() > 0) return 1; // should not be testing for < 255 here + AlphaMgrEntry *e = layouts.findItem((const wchar_t *)l); + if (hasAutoOpacity(e) && getAlpha(e) < 255) return 1; + return 0; +} + +void AlphaMgr::checkTimer() { + int fading = 0; + foreach(layouts) + AlphaMgrEntry *e = layouts.getfor(); + if (e->getStatus() == STATUS_IN_FADINGON || e->getStatus() == STATUS_OUT_FADINGOUT) { fading++; break; } + endfor; + if (getAutoOpacify() && getBigStatus() == STATUS_IN_FADINGON || getBigStatus() == STATUS_OUT_FADINGOUT) + fading++; + if (fading && !fast_timer_on) { + timerclient_setTimer(ALPHAMGR_UPDATEALPHA, 20); + fast_timer_on = 1; + } else if (!fading && fast_timer_on) { + timerclient_killTimer(ALPHAMGR_UPDATEALPHA); + fast_timer_on = 0; + } +} + +void AlphaMgr::doEndCheck(AlphaMgrEntry *e) { + if (getCurve(e) == 255) { + switch (e ? e->getStatus() : getBigStatus()) { + case STATUS_IN_FADINGON: + if (e) e->setStatus(STATUS_IN_ON); else setBigStatus(STATUS_IN_ON); + break; + case STATUS_OUT_FADINGOUT: + if (e) e->setStatus(STATUS_OUT_OFF); else setBigStatus(STATUS_OUT_OFF); + break; + } + checkTimer(); + } +} + +void AlphaMgr::updateInList(AlphaMgrEntry *e, int isin) { + if (isin) { + if (in_layouts.searchItem(e) == -1) + in_layouts.addItem(e); + } else { + in_layouts.removeItem(e); + } + + int big_isin = in_layouts.getNumItems() > 0; + + if (getAutoOpacify()) { + if (big_isin) { + // mouse is in a layout, autoopacity is on + switch (getBigStatus()) { + case STATUS_OUT_OFF: + case STATUS_OUT_FADINGOUT: + case STATUS_IN_OFF: { + setBigStartAlpha(e->getLayout()->getTransparency()); + onBigEnterLeave(); + setBigStatus(STATUS_IN_FADINGON); + checkTimer(); + break; + } + case STATUS_IN_FADINGON: + doEndCheck(NULL); + break; + } + } else { + // mouse out of all layouts, autoopacity is on + switch (getBigStatus()) { + case STATUS_IN_FADINGON: + case STATUS_IN_ON: { + setBigStartAlpha(getTransparency(NULL)); + onBigEnterLeave(); + setBigStatus(STATUS_OUT_FADINGOUT); + checkTimer(); + break; + } + case STATUS_OUT_FADINGOUT: + doEndCheck(NULL); + break; + } + } + } else { + if (big_isin) { + // mouse is in a layout, no autoopacity + setBigStatus(STATUS_IN_OFF); + } else { + // mouse is out of all layouts, no autoopacity + setBigStatus(STATUS_OUT_OFF); + } + } +} + +int AlphaMgr::isFocusingExternalWindow() +{ + OSWINDOWHANDLE fw = Wasabi::Std::Wnd::getFocus(); + if (isOurExternalWindow(fw)) return 1; + return 0; +} + +int AlphaMgr::isOverExternalWindow() +{ + int x, y; + Wasabi::Std::getMousePos(&x, &y); + int ext = getExtendAutoOpacity(); + + POINT pt; + pt.x = x; pt.y = y; + OSWINDOWHANDLE w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x-ext; pt.y = y-ext; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x; pt.y = y-ext; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x+ext; pt.y = y-ext; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x+ext; pt.y = y; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x+ext; pt.y = y+ext; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x; pt.y = y+ext; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x-ext; pt.y = y+ext; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + pt.x = x-ext; pt.y = y; + w = Wasabi::Std::Wnd::getWindowFromPoint(pt); + if (isOurExternalWindow(w)) return 1; + return 0; +} + +int AlphaMgr::isWasabiWindow(OSWINDOWHANDLE w) +{ +#ifdef _WIN32 + wchar_t classname[256]=L""; + GetClassNameW(w, classname, 255); + return (w == WASABI_API_WND->main_getRootWnd()->gethWnd() || !wcscmp(classname, BASEWNDCLASSNAME)); +#else +#warning port me + return 1; +#endif +} + +int AlphaMgr::isMenuWindow(OSWINDOWHANDLE w) +{ +#ifdef _WIN32 + char classname[256]=""; + GetClassNameA(w, classname, 255); + return STRCASEEQL(classname, "#32768"); +#else + return 0; +#warning port me +#endif +} + +int AlphaMgr::isOurExternalWindow(OSWINDOWHANDLE w) +{ + OSWINDOWHANDLE wnd = w; + if (isWasabiWindow(w)) + return 0; + + if (isMenuWindow(wnd)) { + wnd = Wasabi::Std::Wnd::getFocus(); + if (isWasabiWindow(wnd) || isOurExternalWindow(wnd)) + return 1; + } + + while (wnd) + { + if (Wasabi::Std::Wnd::isPopup(wnd)) + { + if (isWasabiWindow(wnd)) + return 0; + OSWINDOWHANDLE _w = Wasabi::Std::Wnd::getParent(wnd); +#ifdef _WIN32 + if (!_w) _w = GetWindow(wnd, GW_OWNER); +#else +#warning port me +#endif + if (!wnd) _w = wnd; + return (_w == WASABI_API_WND->main_getRootWnd()->gethWnd() || isWasabiWindow(_w) || isOurExternalWindow(_w)); + } + wnd = Wasabi::Std::Wnd::getParent(wnd); + } + return 0; +} + +void AlphaMgr::preHoverCheck(AlphaMgrEntry *e) { + int isin = isMouseInLayout(e->getLayout()); + uint32_t last = e->getLastTimeIn(); + uint32_t lastbig = getBigLastTimeIn(); + if (isin) { e->onLastIn(); onBigLastIn(); } + if (!getAutoOpacify()) { + if (!isin && last != 0 && (last > Wasabi::Std::getTickCount() - holdtime_ms)) + isin = 1; + } else { + if (!isin && lastbig != 0 && (lastbig > Wasabi::Std::getTickCount() - holdtime_ms)) + isin = 1; + } + if (!isin) { + if (hasAutoOpacityOnFocus(e)) { + if (isFocusingExternalWindow()) isin = 1; + } else { + if (isOverExternalWindow()) isin = 1; + } + } + e->setNextIn(isin); + updateInList(e, isin); +} + +void AlphaMgr::hoverCheck(Layout *l) { + AlphaMgrEntry *e = layouts.findItem((const wchar_t *)l); + if (e) hoverCheck(e); +} + +void AlphaMgr::hoverCheck(AlphaMgrEntry *e, int applytransparency) { + if (e->getStatus() == STATUS_UNKNOWN) + initStatus(e); + + int isin = e->getNextIn(); + + if (getAutoOpacify()) { + isin = big_status == STATUS_IN_FADINGON || big_status == STATUS_IN_ON || big_status == STATUS_IN_OFF; + } + if (hasAutoOpacity(e)) { + if (isin) { + // mouse is in, autoopacity is on + switch (e->getStatus()) { + case STATUS_OUT_OFF: + case STATUS_OUT_FADINGOUT: + case STATUS_IN_OFF: + e->setStartAlpha(e->getLayout()->getTransparency()); + e->onEnterLeave(); + e->setStatus(STATUS_IN_FADINGON); + checkTimer(); + e->getLayout()->onMouseEnterLayout(); + break; + case STATUS_IN_FADINGON: + doEndCheck(e); + break; + } + } else { + // mouse is out, autoopacity is on + switch (e->getStatus()) { + case STATUS_IN_FADINGON: + case STATUS_IN_ON: + e->setStartAlpha(e->getLayout()->getTransparency()); + e->onEnterLeave(); + e->setStatus(STATUS_OUT_FADINGOUT); + checkTimer(); + e->getLayout()->onMouseLeaveLayout(); + break; + case STATUS_OUT_FADINGOUT: + doEndCheck(e); + break; + } + } + } else { + if (isin) { + // mouse is in, no autoopacity + e->setStatus(STATUS_IN_OFF); + } else { + // mouse is out, no autoopacity + e->setStatus(STATUS_OUT_OFF); + } + } +// if (applytransparency) updateTransparency(e->getLayout()); +} + +void AlphaMgr::timerclient_timerCallback(int id) { + switch(id) { + case ALPHAMGR_HOVERCHECK: { + foreach(layouts) + AlphaMgrEntry *e = layouts.getfor(); + preHoverCheck(e); + endfor; + foreach(layouts) + AlphaMgrEntry *e = layouts.getfor(); + hoverCheck(e); + endfor; + } + break; + case ALPHAMGR_UPDATEALPHA: { + foreach(layouts) + AlphaMgrEntry *e = layouts.getfor(); + if (e->getStatus() == STATUS_IN_FADINGON || e->getStatus() == STATUS_OUT_FADINGOUT) updateTransparency(e->getLayout()); + endfor; + } + break; + } +} + +int AlphaMgr::getBigCurTransparency() { + switch (getBigStatus()) { + case STATUS_IN_FADINGON: + case STATUS_OUT_FADINGOUT: + return getTransparency(NULL); + case STATUS_IN_ON: + return 255; + case STATUS_IN_OFF: + case STATUS_OUT_OFF: + return getGlobalAlpha(); + default: return getTransparency(NULL); + } +} + +void AlphaMgr::setBigStartAlpha(int a) { + big_startalpha = a; +} + +void AlphaMgr::setBigStatus(int s) { + big_status = s; +} + +void AlphaMgr::onBigEnterLeave() { + big_enterleave_time = Wasabi::Std::getTickCount(); +} + +uint32_t AlphaMgr::getBigEnterLeaveTime() { + return big_enterleave_time; +} + +void AlphaMgr::setAutoOpacify(int l) { + autoopacify = l; + resetTimer(); + if (l == 0) { + foreach(layouts) + if (layouts.getfor()->getStatus() == STATUS_IN_FADINGON) layouts.getfor()->setStatus(STATUS_IN_OFF); + if (layouts.getfor()->getStatus() == STATUS_OUT_FADINGOUT) layouts.getfor()->setStatus(STATUS_OUT_OFF); + endfor; + } + updateAllTransparency(); +} + +void AlphaMgr::resetTimer() { + timerclient_killTimer(ALPHAMGR_HOVERCHECK); + if (autoopacify == 1 && alllinked) + timerclient_setTimer(ALPHAMGR_HOVERCHECK, 99); + else + timerclient_setTimer(ALPHAMGR_HOVERCHECK, 300); +}
\ No newline at end of file diff --git a/Src/Wasabi/api/wndmgr/alphamgr.h b/Src/Wasabi/api/wndmgr/alphamgr.h new file mode 100644 index 00000000..240485dd --- /dev/null +++ b/Src/Wasabi/api/wndmgr/alphamgr.h @@ -0,0 +1,136 @@ +#ifndef _ALPHAMGR_H +#define _ALPHAMGR_H + +#include <api/timer/timerclient.h> + +class Layout; + +#define STATUS_UNKNOWN -1 +#define STATUS_OUT_OFF 0 +#define STATUS_IN_ON 1 +#define STATUS_OUT_FADINGOUT 2 +#define STATUS_IN_FADINGON 3 +#define STATUS_IN_OFF 4 // when no autoopacity + +class AlphaMgrEntry { + public: + AlphaMgrEntry(Layout *l) : layout(l), status(STATUS_UNKNOWN), fade_val(-1), startalpha(-1), lasttime_in(0), next_in(-1) {} + virtual ~AlphaMgrEntry() { } + + Layout *getLayout() { return layout; } + int getStatus() { return status; } + + void onEnterLeave() { enterleave_time = Wasabi::Std::getTickCount(); } + int getEnterLeaveTime() { return enterleave_time; } + void setEnterLeaveTime(uint32_t t) { enterleave_time = t; } + void setStatus(int s) { status = s; } + int getStartAlpha() { return startalpha; } + void setStartAlpha(int s) { startalpha = s; } + uint32_t getLastTimeIn() { return lasttime_in; } + void onLastIn() { lasttime_in = Wasabi::Std::getTickCount(); } + void setNextIn(int i) { next_in = i; } + int getNextIn() { return next_in; } + + private: + Layout *layout; + int status; + int fade_val; + uint32_t enterleave_time; + int startalpha; + uint32_t lasttime_in; + int next_in; +}; + +class AlphaMgrEntryComparator { +public: + static int compareItem(AlphaMgrEntry *p1, AlphaMgrEntry* p2) { + return CMP3((void*)p1->getLayout(), (void *)p2->getLayout()); + } + static int compareAttrib(const wchar_t *attrib, AlphaMgrEntry *item) { + return CMP3((void *)attrib, (void *)item->getLayout()); + } +}; + +class AlphaMgr : public TimerClientDI { + public: + AlphaMgr(); + virtual ~AlphaMgr(); + + void addLayout(Layout *l); + void removeLayout(Layout *l); + + virtual void timerclient_timerCallback(int id); + + void updateTransparency(Layout *l); + int getTransparency(Layout *l); + int getGlobalAlpha(); + void setGlobalAlpha(int a); + int isFocusInLayout(Layout *l); + int isMouseInLayout(Layout *l); + int isPointInLayout(Layout *l, int x, int y, api_region **rgn=NULL); + int needForcedTransparencyFlag(Layout *l); + int hasAutoOpacity(Layout *l); + int hasAutoOpacityOnHover(Layout *l); + int hasAutoOpacityOnFocus(Layout *l); + + void setAllLinked(int l) { alllinked = l; resetTimer(); updateAllTransparency(); } + void setAutoOpacify(int l); + int getAllLinked() { return alllinked; } + int getAutoOpacify() { return (autoopacify && alllinked) ? autoopacify : 0; } + void setExtendAutoOpacity(int n) { extend_px = n; } + int getExtendAutoOpacity() { return extend_px; } + int getBigCurTransparency(); + + void setFadeInTime(int ms) { fadein_ms = MAX(ms, 1); } + void setFadeOutTime(int ms) { fadeout_ms = MAX(ms, 1); } + void setHoldTime(int ms) { holdtime_ms = ms; } + void hoverCheck(Layout *l); + int getAlpha(Layout *l); + + private: + void updateAllTransparency(); + void updateInList(AlphaMgrEntry *e, int isin); + void setBigStartAlpha(int a); + int getBigStartAlpha() { return big_startalpha; } + void onBigEnterLeave(); + uint32_t getBigEnterLeaveTime(); + void setBigStatus(int s); + int getBigStatus() { return big_status; } + void initStatus(AlphaMgrEntry *e, int applytransparency=0); + int getAlpha(AlphaMgrEntry *e); + int hasAutoOpacityOnHover(AlphaMgrEntry *e); + int hasAutoOpacityOnFocus(AlphaMgrEntry *e); + int hasAutoOpacity(AlphaMgrEntry *e); + void checkTimer(); + void hoverCheck(AlphaMgrEntry *e, int applytransparency=1); + void preHoverCheck(AlphaMgrEntry *e); + int getCurve(AlphaMgrEntry *e); + void doEndCheck(AlphaMgrEntry *e); + void onBigLastIn() { big_lasttimein = Wasabi::Std::getTickCount(); } + uint32_t getBigLastTimeIn() { return big_lasttimein; } + int isFocusingExternalWindow(); + int isOverExternalWindow(); + int isOurExternalWindow(OSWINDOWHANDLE w); + int isWasabiWindow(OSWINDOWHANDLE w); + int isMenuWindow(OSWINDOWHANDLE w); + void resetTimer(); + + PtrListQuickSorted<AlphaMgrEntry, AlphaMgrEntryComparator> layouts; + PtrListQuickSortedByPtrVal<AlphaMgrEntry> in_layouts; + Layout *overlayout; + int alllinked; + int autoopacify; + int global_alpha; + int fast_timer_on; + int big_status; + int big_curtransparency; + int big_startalpha; + uint32_t big_enterleave_time; + int big_lasttimein; + int fadein_ms; + int fadeout_ms; + int holdtime_ms; + int extend_px; +}; + +#endif diff --git a/Src/Wasabi/api/wndmgr/animate.cpp b/Src/Wasabi/api/wndmgr/animate.cpp new file mode 100644 index 00000000..c5f789b7 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/animate.cpp @@ -0,0 +1,96 @@ +#include <precomp.h> +#include <wasabicfg.h> +#include "animate.h" + +#include <api/config/items/cfgitem.h> + +//--------------------------------------------------------------------------- +void AnimatedRects::draw(const RECT *source, const RECT *dest, int steps) +{ +#ifdef WASABI_COMPILE_CONFIG + // {280876CF-48C0-40bc-8E86-73CE6BB462E5} + const GUID options_guid = + { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } }; + if (!_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid), L"Animated rects")) return; +#else + if (!WASABI_WNDMGR_ANIMATEDRECTS) return; +#endif + + //FG> Not anymore, old code, old bugs + //BU you're so cool, Francis + //FG> thank you, you're not too bad either :) + int sizex=source->right-source->left-(dest->right-dest->left); + int sizey=source->bottom-source->top-(dest->bottom-dest->top); + int diffx=source->left-dest->left; + int diffy=(source->top)-dest->top; + +#ifdef WIN32 + HDC dc; + dc=GetDC(0); + HBRUSH brush = CreateSolidBrush(0xFFFFFF); + HPEN pen = CreatePen(PS_SOLID,0,0xFFFFFF); + HBRUSH obrush = (HBRUSH)SelectObject(dc, brush); + HPEN open = (HPEN)SelectObject(dc, pen); + int oldrop = SetROP2(dc,R2_XORPEN); +#endif +#ifdef LINUX + HDC dc = (HDC)MALLOC( sizeof( hdc_typ ) ); + XGCValues gcv; + gcv.foreground = 0xffffff; + gcv.function = GXxor; + gcv.subwindow_mode = IncludeInferiors; + dc->gc = XCreateGC( Linux::getDisplay(), Linux::RootWin(), GCForeground | GCFunction | GCSubwindowMode, &gcv ); +#endif +//PORTME + + for(int i=0;i<steps;i++) { + int x=dest->left+diffx-((diffx*i)/steps); + int y=dest->top+diffy-((diffy*i)/steps); + int maxx=(source->right-source->left)-((sizex*i)/steps); + int maxy=(source->bottom-source->top)-((sizey*i)/steps); + +#ifdef WIN32 + int p1x=x,p1y=y; + int p2x=x+maxx,p2y=y; + int p3x=x+maxx,p3y=y+maxy; + int p4x=x,p4y=y+maxy; + MoveToEx(dc,p1x,p1y,NULL); + LineTo(dc,p2x,p2y); + LineTo(dc,p3x,p3y); + LineTo(dc,p4x,p4y); + LineTo(dc,p1x,p1y); +#endif +#ifdef LINUX + XDrawRectangle( Linux::getDisplay(), Linux::RootWin(), dc->gc, + x, y, maxx, maxy ); +#endif +//PORTME + Wasabi::Std::usleep(5); +#ifdef WIN32 + MoveToEx(dc,p1x,p1y,NULL); + LineTo(dc,p2x,p2y); + LineTo(dc,p3x,p3y); + LineTo(dc,p4x,p4y); + LineTo(dc,p1x,p1y); +#endif +#ifdef LINUX + XDrawRectangle( Linux::getDisplay(), Linux::RootWin(), dc->gc, + x, y, maxx, maxy ); +#endif +//PORTME + } +#ifdef WIN32 + SetROP2(dc, oldrop); + SelectObject(dc, open); + SelectObject(dc, obrush); + DeleteObject(brush); + DeleteObject(pen); + ReleaseDC(0,dc); +#endif +#ifdef LINUX + XFreeGC( Linux::getDisplay(), dc->gc ); + FREE( dc ); +#endif +//PORTME +} + diff --git a/Src/Wasabi/api/wndmgr/animate.h b/Src/Wasabi/api/wndmgr/animate.h new file mode 100644 index 00000000..23a98318 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/animate.h @@ -0,0 +1,11 @@ +#ifndef _ANIMATE_H +#define _ANIMATE_H + +#include <bfc/wasabi_std.h> + +class AnimatedRects { +public: + static void draw(const RECT *src, const RECT *dst, int nsteps=5); +}; + +#endif diff --git a/Src/Wasabi/api/wndmgr/api_wndmgr.cpp b/Src/Wasabi/api/wndmgr/api_wndmgr.cpp new file mode 100644 index 00000000..c2206aeb --- /dev/null +++ b/Src/Wasabi/api/wndmgr/api_wndmgr.cpp @@ -0,0 +1,47 @@ +#include <precomp.h> +#include "api_wndmgr.h" + +#ifdef CBCLASS +#undef CBCLASS +#endif +#define CBCLASS wndmgr_apiI +START_DISPATCH; + VCB(WNDMGR_API_WNDTRACKADD, wndTrackAdd); + VCB(WNDMGR_API_WNDTRACKREMOVE, wndTrackRemove); + CB(WNDMGR_API_WNDTRACKDOCK, wndTrackDock); + CB(WNDMGR_API_WNDTRACKDOCK2, wndTrackDock2); + VCB(WNDMGR_API_WNDTRACKSTARTCOOPERATIVE, wndTrackStartCooperative); + VCB(WNDMGR_API_WNDTRACKENDCOOPERATIVE, wndTrackEndCooperative); + CB(WNDMGR_API_WNDTRACKWASCOOPERATIVE, wndTrackWasCooperative); + VCB(WNDMGR_API_WNDTRACKINVALIDATEALL, wndTrackInvalidateAll); + CB(WNDMGR_API_SKINWND_TOGGLEBYGUID, skinwnd_toggleByGuid); + CB(WNDMGR_API_SKINWND_TOGGLEBYGROUPID, skinwnd_toggleByGroupId); + CB(WNDMGR_API_SKINWND_CREATEBYGUID, skinwnd_createByGuid); + CB(WNDMGR_API_SKINWND_CREATEBYGROUPID, skinwnd_createByGroupId); + VCB(WNDMGR_API_SKINWND_DESTROY, skinwnd_destroy); + CB(WNDMGR_API_SKINWND_GETNUMBYGUID, skinwnd_getNumByGuid); + CB(WNDMGR_API_SKINWND_ENUMBYGUID, skinwnd_enumByGuid); + CB(WNDMGR_API_SKINWND_GETNUMBYGROUPID, skinwnd_getNumByGroupId); + CB(WNDMGR_API_SKINWND_ENUMBYGROUPID, skinwnd_enumByGroupId); + VCB(WNDMGR_API_SKINWND_ATTACHTOSKIN, skinwnd_attachToSkin); + //CB(WNDMGR_API_SKIN_GETCONTAINER, skin_getContainer); + //CB(WNDMGR_API_SKIN_GETLAYOUT, skin_getLayout); + VCB(WNDMGR_API_WNDHOLDER_REGISTER, wndholder_register); + VCB(WNDMGR_API_WNDHOLDER_UNREGISTER, wndholder_unregister); + CB(WNDMGR_API_MESSAGEBOX, messageBox); + CB(WNDMGR_API_GETMODALWND, getModalWnd); + VCB(WNDMGR_API_PUSHMODALWND, pushModalWnd); + VCB(WNDMGR_API_POPMODALWND, popModalWnd); + VCB(WNDMGR_API_DRAWANIMATEDRECTS, drawAnimatedRects); + CB(WNDMGR_API_AUTOPOPUP_REGISTERGUID, autopopup_registerGuid); + CB(WNDMGR_API_AUTOPOPUP_REGISTERGROUPID, autopopup_registerGroupId); + VCB(WNDMGR_API_AUTOPOPUP_UNREGISTER, autopopup_unregister); + CB(WNDMGR_API_AUTOPOPUP_GETNUMGUIDS, autopopup_getNumGuids); + CB(WNDMGR_API_AUTOPOPUP_ENUMGUID, autopopup_enumGuid); + CB(WNDMGR_API_AUTOPOPUP_GETNUMGROUPS, autopopup_getNumGroups); + CB(WNDMGR_API_AUTOPOPUP_ENUMGROUPS, autopopup_enumGroup); + CB(WNDMGR_API_AUTOPOPUP_ENUMGUIDDESC, autopopup_enumGuidDescription); + CB(WNDMGR_API_AUTOPOPUP_ENUMGROUPDESC, autopopup_enumGroupDescription); + CB(WNDMGR_API_VARMGR_TRANSLATE, varmgr_translate); + CB(WNDMGR_API_NEWDYNAMICCONTAINER, newDynamicContainer); +END_DISPATCH; diff --git a/Src/Wasabi/api/wndmgr/api_wndmgr.h b/Src/Wasabi/api/wndmgr/api_wndmgr.h new file mode 100644 index 00000000..667ddd38 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/api_wndmgr.h @@ -0,0 +1,305 @@ +#ifndef __WNDMGR_API_H +#define __WNDMGR_API_H + +#include <bfc/dispatch.h> +#include <bfc/nsguid.h> + +class ifc_window; +class WindowHolder; +class Container; +class ScriptObject; + +#ifndef MODALWND_DEF +#define MODALWND_DEF +ifc_window *const MODALWND_NOWND = reinterpret_cast<ifc_window*>(-1); +#endif + +class wndmgr_api : public Dispatchable { + public: + void wndTrackAdd(ifc_window *wnd); + void wndTrackRemove(ifc_window *wnd); + bool wndTrackDock(ifc_window *wnd, RECT *r, int mask); + bool wndTrackDock(ifc_window *wnd, RECT *r, RECT *orig_r, int mask); + void wndTrackStartCooperative(ifc_window *wnd); + void wndTrackEndCooperative(); + int wndTrackWasCooperative(); + void wndTrackInvalidateAll(); + int skinwnd_toggleByGuid(GUID g, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0); + int skinwnd_toggleByGroupId(const wchar_t *groupid, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0); + ifc_window *skinwnd_createByGuid(GUID g, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0, int starthidden = 0, int *isnew = NULL); + ifc_window *skinwnd_createByGroupId(const wchar_t *groupid, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0, int starthidden = 0, int *isnew = NULL); + void skinwnd_destroy(ifc_window *w, RECT *destanimrect = NULL); + int skinwnd_getNumByGuid(GUID g); + ifc_window *skinwnd_enumByGuid(GUID g, int n); + int skinwnd_getNumByGroupId(const wchar_t *groupid); + ifc_window *skinwnd_enumByGroupId(const wchar_t *groupid, int n); + void skinwnd_attachToSkin(ifc_window *w, int side, int size); + //ScriptObject *skin_getContainer(const wchar_t *container_name); + //ScriptObject *skin_getLayout(ScriptObject *container, const wchar_t *layout_name); + void wndholder_register(WindowHolder *wh); + void wndholder_unregister(WindowHolder *wh); + int messageBox(const wchar_t *txt, const wchar_t *title, int flags, const wchar_t *not_anymore_identifier, ifc_window *parenwnt); + ifc_window *getModalWnd(); + void pushModalWnd(ifc_window *w = MODALWND_NOWND); + void popModalWnd(ifc_window *w = MODALWND_NOWND); + void drawAnimatedRects(const RECT *r1, const RECT *r2); + int autopopup_registerGuid(GUID g, const wchar_t *desc, const wchar_t *prefered_container = NULL, int container_flag = 0); + int autopopup_registerGroupId(const wchar_t *groupid, const wchar_t *desc, const wchar_t *prefered_container = NULL, int container_flag = 0); + void autopopup_unregister(int id); + int autopopup_getNumGuids(); + GUID autopopup_enumGuid(int n); + int autopopup_getNumGroups(); + const wchar_t *autopopup_enumGroup(int n); + const wchar_t *autopopup_enumGuidDescription(int n); + const wchar_t *autopopup_enumGroupDescription(int n); + const wchar_t *varmgr_translate(const wchar_t *str); + //Container *newDynamicContainer(const wchar_t *containername, int transcient = 1); + + enum { + WNDMGR_API_WNDTRACKADD = 0, + WNDMGR_API_WNDTRACKREMOVE = 10, + WNDMGR_API_WNDTRACKDOCK = 20, + WNDMGR_API_WNDTRACKDOCK2 = 30, + WNDMGR_API_WNDTRACKSTARTCOOPERATIVE = 40, + WNDMGR_API_WNDTRACKENDCOOPERATIVE = 50, + WNDMGR_API_WNDTRACKWASCOOPERATIVE = 60, + WNDMGR_API_WNDTRACKINVALIDATEALL = 70, + WNDMGR_API_SKINWND_TOGGLEBYGUID = 80, + WNDMGR_API_SKINWND_TOGGLEBYGROUPID = 90, + WNDMGR_API_SKINWND_CREATEBYGUID = 100, + WNDMGR_API_SKINWND_CREATEBYGROUPID = 110, + WNDMGR_API_SKINWND_DESTROY = 120, + WNDMGR_API_SKINWND_GETNUMBYGUID = 130, + WNDMGR_API_SKINWND_ENUMBYGUID = 140, + WNDMGR_API_SKINWND_GETNUMBYGROUPID = 150, + WNDMGR_API_SKINWND_ENUMBYGROUPID = 160, + WNDMGR_API_SKINWND_ATTACHTOSKIN = 170, + //WNDMGR_API_SKIN_GETCONTAINER = 180, + WNDMGR_API_SKIN_GETLAYOUT = 190, + WNDMGR_API_WNDHOLDER_REGISTER = 200, + WNDMGR_API_WNDHOLDER_UNREGISTER = 210, + WNDMGR_API_MESSAGEBOX = 220, + WNDMGR_API_GETMODALWND = 230, + WNDMGR_API_PUSHMODALWND = 240, + WNDMGR_API_POPMODALWND = 250, + WNDMGR_API_DRAWANIMATEDRECTS = 260, + WNDMGR_API_AUTOPOPUP_REGISTERGUID = 270, + WNDMGR_API_AUTOPOPUP_REGISTERGROUPID = 280, + WNDMGR_API_AUTOPOPUP_UNREGISTER = 290, + WNDMGR_API_VARMGR_TRANSLATE = 300, + WNDMGR_API_NEWDYNAMICCONTAINER = 310, + WNDMGR_API_AUTOPOPUP_GETNUMGUIDS = 320, + WNDMGR_API_AUTOPOPUP_ENUMGUID = 330, + WNDMGR_API_AUTOPOPUP_GETNUMGROUPS = 340, + WNDMGR_API_AUTOPOPUP_ENUMGROUPS = 350, + WNDMGR_API_AUTOPOPUP_ENUMGUIDDESC = 360, + WNDMGR_API_AUTOPOPUP_ENUMGROUPDESC = 370, + }; +}; + +inline void wndmgr_api::wndTrackAdd(ifc_window *wnd) { + _voidcall(WNDMGR_API_WNDTRACKADD, wnd); +} + +inline void wndmgr_api::wndTrackRemove(ifc_window *wnd) { + _voidcall(WNDMGR_API_WNDTRACKREMOVE, wnd); +} + +inline bool wndmgr_api::wndTrackDock(ifc_window *wnd, RECT *r, int mask) { + return _call(WNDMGR_API_WNDTRACKDOCK, (bool)FALSE, wnd, r, mask); +} + +inline bool wndmgr_api::wndTrackDock(ifc_window *wnd, RECT *r, RECT *orig_r, int mask) { + return _call(WNDMGR_API_WNDTRACKDOCK2, (bool)FALSE, wnd, r, orig_r, mask); +} + +inline void wndmgr_api::wndTrackStartCooperative(ifc_window *wnd) { + _voidcall(WNDMGR_API_WNDTRACKSTARTCOOPERATIVE, wnd); +} + +inline void wndmgr_api::wndTrackEndCooperative() { + _voidcall(WNDMGR_API_WNDTRACKENDCOOPERATIVE); +} + +inline int wndmgr_api::wndTrackWasCooperative() { + return _call(WNDMGR_API_WNDTRACKWASCOOPERATIVE, (int)0); +} + +inline void wndmgr_api::wndTrackInvalidateAll() { + _voidcall(WNDMGR_API_WNDTRACKINVALIDATEALL); +} + +inline int wndmgr_api::skinwnd_toggleByGuid(GUID g, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient) { + return _call(WNDMGR_API_SKINWND_TOGGLEBYGUID, (int)0, g, prefered_container, container_flag, sourceanimrect, transcient); +} + +inline int wndmgr_api::skinwnd_toggleByGroupId(const wchar_t *groupid, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient) { + return _call(WNDMGR_API_SKINWND_TOGGLEBYGROUPID, (int)0, groupid, prefered_container, container_flag, sourceanimrect, transcient); +} + +inline ifc_window *wndmgr_api::skinwnd_createByGuid(GUID g, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient, int starthidden, int *isnew) { + return _call(WNDMGR_API_SKINWND_CREATEBYGUID, (ifc_window *)NULL, g, prefered_container, container_flag, sourceanimrect, transcient, starthidden, isnew); +} + +inline ifc_window *wndmgr_api::skinwnd_createByGroupId(const wchar_t *groupid, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient, int starthidden, int *isnew) { + return _call(WNDMGR_API_SKINWND_CREATEBYGROUPID, (ifc_window *)NULL, groupid, prefered_container, container_flag, sourceanimrect, transcient, starthidden, isnew); +} + +inline void wndmgr_api::skinwnd_destroy(ifc_window *w, RECT *destanimrect) { + _voidcall(WNDMGR_API_SKINWND_DESTROY, w, destanimrect); +} + +inline int wndmgr_api::skinwnd_getNumByGuid(GUID g) { + return _call(WNDMGR_API_SKINWND_GETNUMBYGUID, (int)0, g); +} + +inline ifc_window *wndmgr_api::skinwnd_enumByGuid(GUID g, int n) { + return _call(WNDMGR_API_SKINWND_ENUMBYGUID, (ifc_window *)NULL, g, n); +} + +inline int wndmgr_api::skinwnd_getNumByGroupId(const wchar_t *groupid) { + return _call(WNDMGR_API_SKINWND_GETNUMBYGROUPID, (int)0, groupid); +} + +inline ifc_window *wndmgr_api::skinwnd_enumByGroupId(const wchar_t *groupid, int n) { + return _call(WNDMGR_API_SKINWND_ENUMBYGROUPID, (ifc_window *)NULL, groupid, n); +} + +inline void wndmgr_api::skinwnd_attachToSkin(ifc_window *w, int side, int size) { + _voidcall(WNDMGR_API_SKINWND_ATTACHTOSKIN, w, side, size); +} +/* +inline ScriptObject *wndmgr_api::skin_getContainer(const wchar_t *container_name) { + return _call(WNDMGR_API_SKIN_GETCONTAINER, (ScriptObject *)NULL, container_name); +} +*/ +/* +inline ScriptObject *wndmgr_api::skin_getLayout(ScriptObject *container, const wchar_t *layout_name) { + return _call(WNDMGR_API_SKIN_GETLAYOUT, (ScriptObject *)NULL, container, layout_name); +} +*/ +inline void wndmgr_api::wndholder_register(WindowHolder *wh) { + _voidcall(WNDMGR_API_WNDHOLDER_REGISTER, wh); +} + +inline void wndmgr_api::wndholder_unregister(WindowHolder *wh) { + _voidcall(WNDMGR_API_WNDHOLDER_UNREGISTER, wh); +} + +inline int wndmgr_api::messageBox(const wchar_t *txt, const wchar_t *title, int flags, const wchar_t *not_anymore_identifier, ifc_window *parenwnt) { + return _call(WNDMGR_API_MESSAGEBOX, (int)0, txt, title, flags, not_anymore_identifier, parenwnt); +} + +inline ifc_window *wndmgr_api::getModalWnd() { + return _call(WNDMGR_API_GETMODALWND, (ifc_window *)NULL); +} + +inline void wndmgr_api::pushModalWnd(ifc_window *w) { + _voidcall(WNDMGR_API_PUSHMODALWND, w); +} + +inline void wndmgr_api::popModalWnd(ifc_window *w) { + _voidcall(WNDMGR_API_POPMODALWND, w); +} + +inline void wndmgr_api::drawAnimatedRects(const RECT *r1, const RECT *r2) { + _voidcall(WNDMGR_API_DRAWANIMATEDRECTS, r1, r2); +} + +inline int wndmgr_api::autopopup_registerGuid(GUID g, const wchar_t *desc, const wchar_t *prefered_container, int container_flag) { + return _call(WNDMGR_API_AUTOPOPUP_REGISTERGUID, (int)0, g, desc, prefered_container, container_flag); +} + +inline int wndmgr_api::autopopup_registerGroupId(const wchar_t *groupid, const wchar_t *desc, const wchar_t *prefered_container, int container_flag) { + return _call(WNDMGR_API_AUTOPOPUP_REGISTERGROUPID, (int)0, groupid, desc, prefered_container, container_flag); +} + +inline void wndmgr_api::autopopup_unregister(int id) { + _voidcall(WNDMGR_API_AUTOPOPUP_UNREGISTER, id); +} + +inline const wchar_t *wndmgr_api::varmgr_translate(const wchar_t *str) { + return _call(WNDMGR_API_VARMGR_TRANSLATE, (const wchar_t *)0, str); +} +/* +inline Container *wndmgr_api::newDynamicContainer(const wchar_t *containername, int transcient) { + return _call(WNDMGR_API_NEWDYNAMICCONTAINER, (Container *)NULL, containername, transcient); +} +*/ +inline int wndmgr_api::autopopup_getNumGuids() { + return _call(WNDMGR_API_AUTOPOPUP_GETNUMGUIDS, 0); +} + +inline GUID wndmgr_api::autopopup_enumGuid(int n) { + return _call(WNDMGR_API_AUTOPOPUP_ENUMGUID, INVALID_GUID, n); +} + + +inline int wndmgr_api::autopopup_getNumGroups() { + return _call(WNDMGR_API_AUTOPOPUP_GETNUMGROUPS, 0); +} + +inline const wchar_t *wndmgr_api::autopopup_enumGroup(int n) { + return _call(WNDMGR_API_AUTOPOPUP_ENUMGROUPS, (const wchar_t*)NULL, n); +} + +inline const wchar_t *wndmgr_api::autopopup_enumGuidDescription(int n) { + return _call(WNDMGR_API_AUTOPOPUP_ENUMGUIDDESC, (const wchar_t *)NULL, n); +} + +inline const wchar_t *wndmgr_api::autopopup_enumGroupDescription(int n) { + return _call(WNDMGR_API_AUTOPOPUP_ENUMGROUPDESC, (const wchar_t *)NULL, n); +} + +class wndmgr_apiI : public wndmgr_api { + public: + virtual void wndTrackAdd(ifc_window *wnd)=0; + virtual void wndTrackRemove(ifc_window *wnd)=0; + virtual bool wndTrackDock(ifc_window *wnd, RECT *r, int mask)=0; + virtual bool wndTrackDock2(ifc_window *wnd, RECT *r, RECT *orig_r, int mask)=0; + virtual void wndTrackStartCooperative(ifc_window *wnd)=0; + virtual void wndTrackEndCooperative()=0; + virtual int wndTrackWasCooperative()=0; + virtual void wndTrackInvalidateAll()=0; + virtual int skinwnd_toggleByGuid(GUID g, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0)=0; + virtual int skinwnd_toggleByGroupId(const wchar_t *groupid, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0)=0; + virtual ifc_window *skinwnd_createByGuid(GUID g, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0, int starthidden = 0, int *isnew=NULL)=0; + virtual ifc_window *skinwnd_createByGroupId(const wchar_t *groupid, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0, int starthidden = 0, int *isnew=NULL)=0; + virtual void skinwnd_destroy(ifc_window *w, RECT *destanimrect = NULL)=0; + virtual int skinwnd_getNumByGuid(GUID g)=0; + virtual ifc_window *skinwnd_enumByGuid(GUID g, int n)=0; + virtual int skinwnd_getNumByGroupId(const wchar_t *groupid)=0; + virtual ifc_window *skinwnd_enumByGroupId(const wchar_t *groupid, int n)=0; + virtual void skinwnd_attachToSkin(ifc_window *w, int side, int size)=0; + virtual ScriptObject *skin_getContainer(const wchar_t *container_name)=0; + virtual ScriptObject *skin_getLayout(ScriptObject *container, const wchar_t *layout_name)=0; + virtual void wndholder_register(WindowHolder *wh)=0; + virtual void wndholder_unregister(WindowHolder *wh)=0; + virtual int messageBox(const wchar_t *txt, const wchar_t *title, int flags, const wchar_t *not_anymore_identifier, ifc_window *parenwnt)=0; + virtual ifc_window *getModalWnd()=0; + virtual void pushModalWnd(ifc_window *w = MODALWND_NOWND)=0; + virtual void popModalWnd(ifc_window *w = MODALWND_NOWND)=0; + virtual void drawAnimatedRects(const RECT *r1, const RECT *r2)=0; + virtual int autopopup_registerGuid(GUID g, const wchar_t *desc, const wchar_t *prefered_container = NULL, int container_flag = 0)=0; + virtual int autopopup_registerGroupId(const wchar_t *groupid, const wchar_t *desc, const wchar_t *prefered_container = NULL, int container_flag = 0)=0; + virtual void autopopup_unregister(int id)=0; + virtual int autopopup_getNumGuids()=0; + virtual GUID autopopup_enumGuid(int n)=0; + virtual int autopopup_getNumGroups()=0; + virtual const wchar_t *autopopup_enumGroup(int n)=0; + virtual const wchar_t *varmgr_translate(const wchar_t *str)=0; + virtual Container *newDynamicContainer(const wchar_t *containername, int transcient = 1)=0; + virtual const wchar_t *autopopup_enumGuidDescription(int n)=0; + virtual const wchar_t *autopopup_enumGroupDescription(int n)=0; + + protected: + RECVS_DISPATCH; +}; + +// {038A3567-1530-4062-BA87-CCB4F01DA3E9} +static const GUID wndMgrApiServiceGuid = +{ 0x38a3567, 0x1530, 0x4062, { 0xba, 0x87, 0xcc, 0xb4, 0xf0, 0x1d, 0xa3, 0xe9 } }; + +extern wndmgr_api *wndManagerApi; + +#endif //wndmgr_api_h diff --git a/Src/Wasabi/api/wndmgr/appcmds.cpp b/Src/Wasabi/api/wndmgr/appcmds.cpp new file mode 100644 index 00000000..93b6ab6d --- /dev/null +++ b/Src/Wasabi/api/wndmgr/appcmds.cpp @@ -0,0 +1,61 @@ +#include <precomp.h> +#include "appcmds.h" + +#define CBCLASS AppCmdsI +START_DISPATCH; +CB(APPCMDS_GETNUMCMDS, appcmds_getNumCmds); +CB(APPCMDS_ENUMCMD, appcmds_enumCmd); +VCB(APPCMDS_ONCOMMAND, appcmds_onCommand); +END_DISPATCH; +#undef CBCLASS + +AppCmdsI::~AppCmdsI() +{ + foreach(cmds) + if (cmds.getfor()->autodelete) + delete cmds.getfor(); + endfor +} + +void AppCmdsI::appcmds_addCmd(CmdRec *cmdrec) +{ + cmds.addItem(cmdrec); +} + +void AppCmdsI::appcmds_addCmd(const wchar_t *name, int id, int side) +{ + cmds.addItem(new CmdRec(name, id, side, TRUE)); +} + +void AppCmdsI::appcmds_deleteAll() +{ + foreach(cmds) + if (cmds.getfor()->autodelete) delete cmds.getfor(); + endfor + cmds.removeAll(); +} + +int AppCmdsI::appcmds_getNumCmds() +{ + return cmds.getNumItems(); +} + +const wchar_t *AppCmdsI::appcmds_enumCmd(int n, int *side, int *id) +{ + CmdRec *cr = cmds[n]; + if (cr == NULL) return NULL; + if (side != NULL) *side = cr->side; + if (id != NULL) *id = cr->id; + return cr->cmdname; +} + +void AppCmdsI::appcmds_onCommand(int id, const RECT *buttonRect, int which_button) +{ + foreach(cmds) + if (cmds.getfor()->id == id) + { + cmds.getfor()->onCommand(buttonRect, which_button); + break; + } + endfor +} diff --git a/Src/Wasabi/api/wndmgr/appcmds.h b/Src/Wasabi/api/wndmgr/appcmds.h new file mode 100644 index 00000000..fc3f3ec5 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/appcmds.h @@ -0,0 +1,89 @@ +#ifndef _APPCMDS_H +#define _APPCMDS_H + +#include <bfc/dispatch.h> +#include <bfc/depend.h> +#include <bfc/common.h> +#include <bfc/string/StringW.h> +#include <bfc/ptrlist.h> + +class DragItem; + +// this will be fully dispatched later on +class AppCmds : public Dispatchable +{ +public: + + int appcmds_getNumCmds(); + + const wchar_t *appcmds_enumCmd(int n, int *side, int *id); + + enum { + SIDE_LEFT = 0, SIDE_RIGHT = 1 + }; + + enum { + LEFT_CLICK = 0, + RIGHT_CLICK = 1, + }; + + void appcmds_onCommand(int id, const RECT *buttonRect, int which_button); //onscreen coords + + enum { + APPCMDS_GETNUMCMDS = 100, + APPCMDS_ENUMCMD = 200, + APPCMDS_ONCOMMAND = 300, + }; +}; + +inline int AppCmds::appcmds_getNumCmds() +{ + return _call(APPCMDS_GETNUMCMDS, 0); +} + +inline const wchar_t *AppCmds::appcmds_enumCmd(int n, int *side, int *id) +{ + return _call(APPCMDS_ENUMCMD, (const wchar_t *)NULL, n, side, id); +} + +inline void AppCmds::appcmds_onCommand(int id, const RECT *buttonRect, int which_button) +{ + _voidcall(APPCMDS_ONCOMMAND, id, buttonRect, which_button); +} + +class CmdRec +{ +public: + CmdRec(const wchar_t *name, int _id, int _side, int _autodelete = 0) : cmdname(name), id(_id), side(_side), autodelete(_autodelete) {} + virtual ~CmdRec() {} + StringW cmdname; + int id, side; + int autodelete; + + virtual void onCommand(const RECT *buttonRect, int which_button) {}} +; + +class AppCmdsI : public AppCmds +{ +public: + AppCmdsI() { } + virtual ~AppCmdsI(); + +protected: + void appcmds_addCmd(CmdRec *cmdrec); + void appcmds_addCmd(const wchar_t *name, int id, int side = SIDE_LEFT); + void appcmds_deleteAll(); //calls delete on each one + +public: + virtual int appcmds_getNumCmds(); + virtual const wchar_t *appcmds_enumCmd(int n, int *side, int *id); + + // override this and catch your commands, otherwise it'll call the CmdRec + virtual void appcmds_onCommand(int id, const RECT *buttonRect, int which_button); + +protected: + RECVS_DISPATCH; + PtrList<CmdRec> cmds; +}; + +#endif diff --git a/Src/Wasabi/api/wndmgr/autopopup.cpp b/Src/Wasabi/api/wndmgr/autopopup.cpp new file mode 100644 index 00000000..58212998 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/autopopup.cpp @@ -0,0 +1,157 @@ +#include <precomp.h> +#include "autopopup.h" + +static PtrListQuickSorted<AutoPopupEntry, AutoPopupEntrySort> entries; +static int nid=0; + +int AutoPopup::registerGuid(int skinpartid, GUID g, const wchar_t *desc, const wchar_t *prefered_container, int required) +{ + if (desc == NULL || !*desc) desc = L"[????]"; + AutoPopupEntry *ape = new AutoPopupEntry(skinpartid, g, NULL, desc, prefered_container, required); + entries.addItem(ape); + return ape->getNid(); +} + +int AutoPopup::registerGroupId(int skinpartid, const wchar_t *groupid, const wchar_t *desc, const wchar_t *prefered_container, int required) { + if (desc == NULL || !*desc) desc = L"[????]"; + AutoPopupEntry *ape = new AutoPopupEntry(skinpartid, INVALID_GUID, groupid, desc, prefered_container, required); + entries.addItem(ape); + return ape->getNid(); +} + +int AutoPopup::getNumItems() { return entries.getNumItems(); } +AutoPopupEntry *AutoPopup::enumItem(int n) { return entries.enumItem(n); } + +int AutoPopup::getNumGroups() { + int n = 0; + foreach(entries) + AutoPopupEntry *e = entries.getfor(); + if (e->getGroupId() != NULL && e->getGuid() == INVALID_GUID) n++; + endfor; + return n; +} + +int AutoPopup::getNumGuids() { + int n = 0; + foreach(entries) + AutoPopupEntry *e = entries.getfor(); + if (e->getGroupId() == NULL && e->getGuid() != INVALID_GUID) n++; + endfor; + return n; +} + +const wchar_t *AutoPopup::enumGroup(int n) { + int c = 0; + foreach(entries) + AutoPopupEntry *e = entries.getfor(); + if (e->getGroupId() != NULL && e->getGuid() == INVALID_GUID) { + if (c == n) return e->getGroupId(); + c++; + } + endfor; + return NULL; +} + +GUID AutoPopup::enumGuid(int n) { + int c = 0; + foreach(entries) + AutoPopupEntry *e = entries.getfor(); + if (e->getGroupId() == NULL && e->getGuid() != INVALID_GUID) { + if (c == n) return e->getGuid(); + c++; + } + endfor; + return INVALID_GUID; +} + +const wchar_t *AutoPopup::enumGroupDescription(int n) { + int c = 0; + foreach(entries) + AutoPopupEntry *e = entries.getfor(); + if (e->getGroupId() != NULL && e->getGuid() == INVALID_GUID) { + if (c == n) return e->getDescription(); + c++; + } + endfor; + return NULL; +} + +const wchar_t *AutoPopup::enumGuidDescription(int n) { + int c = 0; + foreach(entries) + AutoPopupEntry *e = entries.getfor(); + if (e->getGroupId() == NULL && e->getGuid() != INVALID_GUID) { + if (c == n) return e->getDescription(); + c++; + } + endfor; + return NULL; +} + + +AutoPopupEntry *AutoPopup::getByDesc(const wchar_t *desc) { + foreach(entries) + if (!WCSICMP(desc, entries.getfor()->getDescription())) + return entries.getfor(); + endfor; + return NULL; +} + +void AutoPopup::reset() { entries.deleteAll(); nid = 0; } + +const wchar_t *AutoPopup::getDefaultContainerParams(const wchar_t *groupid, GUID g, int *flag) { + if (groupid == NULL) { // guid + for (int i=entries.getNumItems()-1;i>=0;i--) { + if (entries.enumItem(i)->getGuid() == g) { + if (flag != NULL) *flag = entries.enumItem(i)->getContainerHow(); + return entries.enumItem(i)->getPreferedContainer(); + } + } + } else { // groupid + for (int i=entries.getNumItems()-1;i>=0;i--) + { + if (WCSCASEEQLSAFE(entries.enumItem(i)->getGroupId(), groupid)) + { + if (flag != NULL) *flag = entries.enumItem(i)->getContainerHow(); + return entries.enumItem(i)->getPreferedContainer(); + } + } + } + return NULL; +} + +void AutoPopup::unregister(int id) { + for (int i=0;i<entries.getNumItems();i++) { + AutoPopupEntry *ape = entries.enumItem(i); + if (ape->getNid() == id) { + delete ape; + entries.removeByPos(i); + i--; + continue; + } + } +} + +void AutoPopup::removeSkinPart(int id) { + for (int i=0;i<entries.getNumItems();i++) { + AutoPopupEntry *ape = entries.enumItem(i); + if (ape->getSkinpart() == id) { + delete ape; + entries.removeByPos(i); + i--; + } + } +} + +int AutoPopup::allocNid() { return nid++; } + +void AutoPopup::removeAllAddons() { + for (int i=0;i<entries.getNumItems();i++) { + AutoPopupEntry *ape = entries.enumItem(i); + if (ape->getSkinpart() != SKINPARTID_NONE) { + delete ape; + entries.removeByPos(i); + i--; + } + } +} diff --git a/Src/Wasabi/api/wndmgr/autopopup.h b/Src/Wasabi/api/wndmgr/autopopup.h new file mode 100644 index 00000000..c37bd122 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/autopopup.h @@ -0,0 +1,76 @@ +#ifndef __AUTOPOPUP_H +#define __AUTOPOPUP_H + +#include <bfc/ptrlist.h> +#include <bfc/string/StringW.h> + +class AutoPopupEntry; +class AutoPopupEntrySort; + +#define SKINPARTID_NONE -1 + +class AutoPopup { + + public: + + static int registerGuid(int skinpartid/*SKINPARTID_NONE*/, GUID g, const wchar_t *desc, const wchar_t *prefered_container=NULL, int required=FALSE); + static int registerGroupId(int skinpartid/*SKINPARTID_NONE*/, const wchar_t *groupid, const wchar_t *desc, const wchar_t *prefered_container=NULL, int required=FALSE); + static void unregister(int id); + + static int getNumItems(); + static AutoPopupEntry *enumItem(int n); + static AutoPopupEntry *getByDesc(const wchar_t *desc); + + static void reset(); + static void removeSkinPart(int id); + + static int allocNid(); + static void removeAllAddons(); + + static int getNumGuids(); + static GUID enumGuid(int n); + static int getNumGroups(); + static const wchar_t *enumGroup(int n); + static const wchar_t *enumGuidDescription(int n); + static const wchar_t *enumGroupDescription(int n); + + static const wchar_t *getDefaultContainerParams(const wchar_t *groupid, GUID g, int *flag); +}; + +class AutoPopupEntry { + + public: + + AutoPopupEntry(int skinpartid, GUID g, const wchar_t *grpid, const wchar_t *description, const wchar_t *prefered_container=NULL, int required=TRUE) : guid(g), groupid(grpid), desc(description), container(prefered_container), container_how(required), skinpart(skinpartid) { nid = AutoPopup::allocNid(); } + virtual ~AutoPopupEntry() { } + + GUID getGuid() { return guid; } + const wchar_t *getGroupId() { return groupid; } + const wchar_t *getDescription() { return desc; } + int getNid() { return nid; } + const wchar_t *getPreferedContainer() { return container; } + int getContainerHow() { return container_how; } + int getSkinpart() { return skinpart; } + + private: + + GUID guid; + StringW groupid; + StringW desc; + int nid; + StringW container; + int container_how; + int skinpart; +}; + +class AutoPopupEntrySort { +public: + static int compareItem(AutoPopupEntry *p1, AutoPopupEntry *p2) { + return WCSICMP(p1->getDescription(), p2->getDescription()); + } + static int compareAttrib(const wchar_t *attrib, AutoPopupEntry *item) { + return WCSICMP(attrib, item->getDescription()); + } +}; + +#endif diff --git a/Src/Wasabi/api/wndmgr/container.cpp b/Src/Wasabi/api/wndmgr/container.cpp new file mode 100644 index 00000000..cfa7485e --- /dev/null +++ b/Src/Wasabi/api/wndmgr/container.cpp @@ -0,0 +1,919 @@ +#include <precomp.h> +#include "wasabicfg.h" +#include <api/wndmgr/container.h> +#include <api/script/script.h> +#include <api/script/scriptmgr.h> +#include <api/config/items/attrbool.h> +#include <api/config/items/cfgitem.h> +#include <api/skin/skinparse.h> +#include <api/wac/compon.h> +#include <api/wnd/wndtrack.h> +#include <api/skin/skin.h> +#include <api/wndmgr/skinembed.h> +#include <api/syscb/callbacks/wndcb.h> +#include <bfc/string/stringdict.h> +#include <api/skin/widgets/xuiwndholder.h> // TODO: cut, but we need XuiWindowHolder::parseGUID for now +#include <bfc/platform/guid.h> + +#ifdef WIN32 +#include "resource.h" +#include "../Agave/Language/api_language.h" +#endif + +BEGIN_STRINGDICTIONARY(_containerparams) +SDI(L"name", CONTAINERPARAM_NAME); +SDI(L"id", CONTAINERPARAM_ID); +SDI(L"dynamic", CONTAINERPARAM_DYNAMIC); +SDI(L"default_x", CONTAINERPARAM_DEFAULTX); +SDI(L"default_y", CONTAINERPARAM_DEFAULTY); +SDI(L"default_visible", CONTAINERPARAM_DEFAULTVISIBLE); +SDI(L"canclose", CONTAINERPARAM_CANCLOSE); +SDI(L"nomenu", CONTAINERPARAM_NOMENU); +SDI(L"nofocusapponclose", CONTAINERPARAM_NOFOCUSAPPONCLOSE); +SDI(L"primarycomponent", CONTAINERPARAM_CONTENT); +END_STRINGDICTIONARY(_containerparams, containerparams); + +Container::Container(int script_id) +{ + getScriptObject()->vcpu_setInterface(containerGuid, (void *)static_cast<Container *>(this)); + getScriptObject()->vcpu_setClassName(L"Container"); + getScriptObject()->vcpu_setController(containerController); + scriptid = script_id; + currentLayout = -1; + default_visible = TRUE; + loaded_default_visible = TRUE; + dynamic = 0; + MEMCPY(&myGUID, &INVALID_GUID, sizeof(GUID)); + lastLayout = -1; + refocusapponclose = 1; + canclose = 1; + inited = 0; + deleting = 0; + transcient = 0; + switching_layout = 0; + nomenu = 0; + prevent_save_visibility = 0; + contentGuid = INVALID_GUID; + hasContentGuid=false; +} + + +void Container::setName(const wchar_t *name) +{ +#ifdef ON_TWEAK_CONTAINER_NAMEW + ON_TWEAK_CONTAINER_NAMEW(name); +#endif + containerName = name ? name : CONTAINER_UNDEFINED_NAME; + foreach(layouts) + Layout *l = layouts.getfor(); + if (l->getRootWndName() == NULL) + { + l->setOSWndName(name); + } + endfor; + updateDefaultVisible(); + + dependent_sendEvent(Container::depend_getClassGuid(), Event_NAMECHANGE, 0, this); +} + +void Container::resetLayouts() +{ + updateDefaultVisible(); + + foreach(layouts) + layouts.getfor()->loadSavedState(); + endfor; +} + +void Container::setId(const wchar_t *id) +{ + containerId = id ? id : L"undefined"; + ismain = !WCSICMP(id, L"main"); +} + +int Container::setXmlParam(const wchar_t *paramname, const wchar_t *strvalue) +{ + switch (containerparams.getId(paramname)) + { + case CONTAINERPARAM_NAME: + setName(strvalue); + return 1; + case CONTAINERPARAM_ID: + setId(strvalue); + return 1; + case CONTAINERPARAM_DYNAMIC: + setDynamic(WTOI(strvalue)); + return 1; + case CONTAINERPARAM_DEFAULTX: + default_x = WTOI(strvalue); + return 1; + case CONTAINERPARAM_DEFAULTY: + default_y = WTOI(strvalue); + return 1; + case CONTAINERPARAM_DEFAULTVISIBLE: + default_visible = WTOI(strvalue); + updateDefaultVisible(); + return 1; + case CONTAINERPARAM_CANCLOSE: + canclose = WTOI(strvalue); + return 1; + case CONTAINERPARAM_NOMENU: + nomenu = WTOI(strvalue); + return 1; + case CONTAINERPARAM_NOFOCUSAPPONCLOSE: + refocusapponclose = !WTOI(strvalue); + break; + case CONTAINERPARAM_CONTENT: + { + // TODO: move this out of XuiWindowHolder + GUID *g = XuiWindowHolder::parseGUID(strvalue); + contentGuid = *g; + hasContentGuid=true; + + break; + } + + } + return 0; +} + +Container::~Container() +{ + containerCallback(CONT_CB_HIDDEN); + layouts.deleteAll(); + contents.deleteAll(); + SkinParser::containers.removeItem(this); +} + +void Container::getWindowRect(RECT *r) +{ + Layout *l = getCurrentLayout(); + if (l) + l->getWindowRect(r); +} + +void Container::addLayout(Layout *layout) +{ + layouts.addItem(layout); +} + +const wchar_t *Container::getName() +{ + return containerName; +} + +const wchar_t *Container::getId() +{ + return containerId; +} + +int Container::getDefaultPositionX(void) +{ + return default_x; +} + +int Container::getDefaultPositionY(void) +{ + return default_y; +} + +void Container::onInit(int noshow) +{ + if (inited) return ; + inited++; + loadFromDefaults(noshow); +} + +void Container::loadFromDefaults(int noshow) +{ +#ifdef WASABI_COMPILE_CONFIG + if (last_layout.isempty()) + { + StringPrintfW tmp(L"container_%s|active", getName()); + wchar_t c[512] = {0}; + WASABI_API_CONFIG->getStringPrivate(tmp, c, 511, L""); + c[510] = 0; + last_layout = c; + } +#endif + + if (loaded_default_visible) + { + showDefaultLayout(noshow); + } +} + +void Container::setDefaultLayout(const wchar_t *name) +{ + last_layout = name; +} + +void Container::showDefaultLayout(int noshow) +{ + Layout *l = getLayout(last_layout); + + if (!l) + l = layouts.enumItem(0); + + if (l) + { + currentLayout = layouts.searchItem(l); + + if (!noshow) + l->setVisible(1); + + containerCallback(CONT_CB_VISIBLE); // since we set currentLayout prior to showing the layout, the callback will not be processed in onChildSetLayoutVisible + } +} + +void Container::setVisible(int sh) +{ + if (!sh && !canclose) + return ; + + int is = isVisible(); + + if (!!sh == !!is) + return ; + + Layout *l = getCurrentLayout(); + + if (!l && lastLayout != -1) + l = layouts[lastLayout]; + + if (sh) + { + if (!l) + showDefaultLayout(); + else + { + l->setVisible(1); + } + } + else + { + if (l) + l->setVisible(0); + } +} + +int Container::isVisible() +{ + if (switching_layout) return 1; + Layout *l = getCurrentLayout(); + if (!l) return 0; + return l->isVisible(); +} + +void Container::onChildSetLayoutVisible(Layout *l, int v) +{ + for (int i = 0;i < layouts.getNumItems();i++) + { + if (layouts[i] == l) + { + if (v) + { + if (currentLayout != i) + { + Layout *l = NULL; + if (currentLayout >= 0) + l = layouts[currentLayout]; + if (l) l->setVisible(0); + containerCallback(CONT_CB_VISIBLE); + currentLayout = i; + l = layouts[currentLayout]; +#ifdef WASABI_COMPILE_CONFIG + if (!isTranscient() && !prevent_save_visibility) + WASABI_API_CONFIG->setStringPrivate(StringPrintfW(L"container_%s|active", getName()), l->getGuiObject()->guiobject_getId()); +#endif +#ifdef WA3COMPATIBILITY + l->setForwardMsgWnd(WASABI_API_WND->main_getRootWnd()->gethWnd()); +#endif + if (l->wantActivation()) + { + l->bringToFront(); + l->setFocus(); + } + l->invalidate(); + } +#ifdef WASABI_COMPILE_CONFIG + if (!isTranscient() && !isDynamic() && !prevent_save_visibility) + WASABI_API_CONFIG->setIntPrivate(StringPrintfW(L"activated/%s", getName()), v); + WASABI_API_CONFIG->setIntPrivate(StringPrintfW(L"everloaded/%s", getName()), 1); +#endif + + } + else + { + if (i == currentLayout) + { + if (!isDeleting() && !isTranscient() && !isDynamic()) + { +#ifdef WASABI_COMPILE_CONFIG + WASABI_API_CONFIG->setIntPrivate(StringPrintfW(L"activated/%s", getName()), v); +#endif + lastLayout = currentLayout; + currentLayout = -1; + } + containerCallback(CONT_CB_HIDDEN); + } + } + return ; + } + } +} + +void Container::containerCallback(int msg) +{ + switch (msg) + { + case CONT_CB_VISIBLE: + { + foreach(contents) + ContentEntry *e = contents.getfor(); + WndInfo i; + i.groupid = e->groupid; + i.guid = e->guid; + i.c = this; + WASABI_API_SYSCB->syscb_issueCallback(SysCallback::WINDOW, WndCallback::SHOWWINDOW, reinterpret_cast<intptr_t>(&i)); + endfor + WndInfo i; + i.groupid = getId(); + i.guid = INVALID_GUID; + i.c = this; + WASABI_API_SYSCB->syscb_issueCallback(SysCallback::WINDOW, WndCallback::SHOWWINDOW, reinterpret_cast<intptr_t>(&i)); + } + break; + case CONT_CB_HIDDEN: + { + foreach(contents) + ContentEntry *e = contents.getfor(); + WndInfo i; + i.groupid = e->groupid; + i.guid = e->guid; + i.c = this; + WASABI_API_SYSCB->syscb_issueCallback(SysCallback::WINDOW, WndCallback::HIDEWINDOW, reinterpret_cast<intptr_t>(&i)); + endfor + WndInfo i; + i.groupid = getId(); + i.guid = INVALID_GUID; + i.c = this; + WASABI_API_SYSCB->syscb_issueCallback(SysCallback::WINDOW, WndCallback::HIDEWINDOW, reinterpret_cast<intptr_t>(&i)); + } + break; + } +} + +void Container::close() +{ + int norefocs = !wantRefocusApp(); + if (norefocs) WASABI_API_WND->appdeactivation_push_disallow(NULL); + if (!canclose) return ; + if (isDynamic()) + { + setVisible(0); + skinEmbedder->destroyContainer(this); // deferred + } + else + setVisible(0); + if (norefocs) WASABI_API_WND->appdeactivation_pop_disallow(NULL); +} + +void Container::toggle() +{ + if (isVisible()) close(); else setVisible(1); // close has special function hide/destroy depending on dynamic status +} + +void Container::switchToLayout(const wchar_t *name, int moveit) +{ + int l = -1; + getLayout(name, &l); + + if (l == -1) + { + // Layout not found, reverting to first in the list + if (layouts.getNumItems() > 0) l = 0; + else + return ; // none found, abort + } + + switching_layout = 1; + if (l != currentLayout) + { + int old = currentLayout; + RECT r = {0}; + Layout *oldlayout = old >= 0 ? layouts[old] : NULL; + Layout *newlayout = layouts[l]; + onBeforeSwitchToLayout(oldlayout, newlayout); + if (oldlayout) + { + oldlayout->getWindowRect(&r); + oldlayout->endCapture(); + } + int unlinked = layouts[l]->isUnlinked(); + unlinked |= oldlayout ? oldlayout->isUnlinked() : 0; + if (moveit && !unlinked && oldlayout) + layouts[l]->move(r.left, r.top); +#ifdef WASABI_COMPILE_CONFIG + // {9149C445-3C30-4e04-8433-5A518ED0FDDE} + const GUID uioptions_guid = + { 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } }; + if (_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), L"Link layouts scale")) + { +#else + if (WASABI_WNDMGR_LINKLAYOUTSCALES) + { +#endif + if (oldlayout) + { + double _r = oldlayout->getRenderRatio(); + newlayout->setRenderRatio(_r); + } + } +#ifdef WASABI_COMPILE_CONFIG + if (_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), L"Link layouts alpha")) + { +#else + if (WASABI_WNDMGR_LINKLAYOUTSALPHA) + { +#endif + if (oldlayout) + { + int a = layouts[old]->getAlpha(); + newlayout->setAlpha(a); + int autoopacify = layouts[old]->getAutoOpacify(); + newlayout->setAutoOpacify(autoopacify); + } + } + + WindowTracker::layoutChanged(oldlayout, newlayout); +#ifdef ON_LAYOUT_CHANGED + ON_LAYOUT_CHANGED; +#endif + layouts[l]->setVisible(1); + foreach(SkinParser::containers) + SkinParser::containers.getfor()->savePositions(); + endfor + onSwitchToLayout(newlayout); + } + switching_layout = 0; +} + +void Container::savePositions() +{ + foreach (layouts) + layouts.getfor()->savePosition(); + endfor +} + +Layout *Container::getLayout(const wchar_t *name, int *pos) +{ + for ( int i = 0; i < getNumLayouts(); i++ ) + { + if ( WCSCASEEQLSAFE( enumLayout( i )->getGuiObject()->guiobject_getId(), name ) ) + { + if (pos) + { + *pos = i; + } + + return enumLayout( i ); + + } + } + + return NULL; +} + +Layout *Container::getCurrentLayout() +{ + if (currentLayout < 0) + return NULL; + + return layouts.enumItem(currentLayout); +} + +void Container::otherContainerToggled(const wchar_t *id, int visible) +{ + for (int i = 0;i < layouts.getNumItems();i++) + layouts[i]->containerToggled(id, visible); +} + +void Container::componentToggled(GUID *g, int visible) +{ + for (int i = 0;i < layouts.getNumItems();i++) + layouts[i]->componentToggled(g, visible); +} + +void Container::sendNotifyToAllLayouts(int notifymsg, int param1, int param2) +{ + for (int i = 0;i < layouts.getNumItems();i++) + layouts[i]->sendNotifyToAllChildren(notifymsg, param1, param2); +} + +int Container::isMainContainer() +{ + return ismain; +} + +void Container::sysMenu() +{ + POINT p; + Wasabi::Std::getMousePos(&p); + layouts.enumItem(currentLayout)->onRightButtonDown(p.x, p.y); +} + +void Container::setDynamic(int i) +{ + dynamic = i; + if (!containerId.isempty()) + setId(containerId); +} + +int Container::isDynamic() +{ + return dynamic; +} + +void Container::onSwitchToLayout(Layout *l) +{ + ScriptObject *ls = l ? l->getGuiObject()->guiobject_getScriptObject() : NULL; + script_onSwitchToLayout(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_OBJECT(ls)); +} + +void Container::onBeforeSwitchToLayout(Layout *oldl, Layout *newl) +{ + ScriptObject *olds = oldl ? oldl->getGuiObject()->guiobject_getScriptObject() : NULL; + ScriptObject *news = newl ? newl->getGuiObject()->guiobject_getScriptObject() : NULL; + script_onBeforeSwitchToLayout(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_OBJECT(olds), MAKE_SCRIPT_OBJECT(news)); +} + + +void Container::onHideLayout(Layout *l) +{ + script_onHideLayout(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_OBJECT(l->getGuiObject()->guiobject_getScriptObject())); +} + +void Container::onShowLayout(Layout *l) +{ + script_onShowLayout(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_OBJECT(l->getGuiObject()->guiobject_getScriptObject())); +} + +int Container::getNumLayouts() +{ + return layouts.getNumItems(); +} + +Layout *Container::enumLayout(int n) +{ + return layouts.enumItem(n); +} + +const wchar_t *Container::getDescriptor() +{ + static wchar_t d[256]; + // if we've tweaked the container names then when saving out we can see and attempt to 'untweak' + // so that things like Winamp Modern's ML will be correctly positioned irrespective of language + int untweak = 0; + wchar_t tweaked[96] = {0}; + // Martin> We need to check the containerName against null - dunno why some skins cause this string to be null + if(containerName.v() != NULL && !_wcsicmp(containerName.v(), WASABI_API_LNGSTRINGW_BUF(IDS_MEDIA_LIBRARY,tweaked,96))){ + untweak = 1; + } + WCSNPRINTF(d, 256,L"%s/%s", getId(), (!untweak ? containerName.v() : L"Media Library")); + return d; +} + +void Container::updateDefaultVisible() +{ + if (!canclose) + { + loaded_default_visible = 1; + return ; + } +#ifdef WASABI_COMPILE_CONFIG + loaded_default_visible = WASABI_API_CONFIG->getIntPrivate(StringPrintfW(L"activated/%s", getName()), default_visible); +#else + loaded_default_visible = default_visible; +#endif +} + +int Container::getScriptId() +{ + return scriptid; +} + +void Container::notifyAddContent(ifc_window *w, const wchar_t *id, GUID g) +{ + contents.addItem(new ContentEntry(id, g, w)); + ScriptObject *_w = w ? w->getGuiObject()->guiobject_getScriptObject() : NULL; + wchar_t guidstr[256] = {0}; + nsGUID::toCharW(g, guidstr); + script_onAddContent(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_OBJECT(_w), MAKE_SCRIPT_STRING(id), MAKE_SCRIPT_STRING(guidstr)); +} + +void Container::notifyRemoveContent(ifc_window *w) +{ + foreach(contents) + ContentEntry *e = contents.getfor(); + if (e->wnd == w) + { + contents.removeItem(e); + delete e; + return ; + } + endfor; +} + +int Container::hasContent(GUID g) +{ + foreach(contents) + ContentEntry *e = contents.getfor(); + if (e->guid == g) + { + return 1; + } + endfor; + return 0; +} + +GUID Container::getDefaultContent() +{ + if (hasContentGuid) + return contentGuid; + if (contents.getNumItems() > 0) return contents.enumItem(0)->guid; + return INVALID_GUID; +} + +ContainerScriptController _containerController; +ContainerScriptController *containerController = &_containerController; + + +// -- Functions table ------------------------------------- +function_descriptor_struct ContainerScriptController::exportedFunction[] = { + {L"onSwitchToLayout", 1, (void*)Container::script_onSwitchToLayout }, + {L"onBeforeSwitchToLayout", 2, (void*)Container::script_onBeforeSwitchToLayout }, + {L"onHideLayout", 1, (void*)Container::script_onHideLayout }, + {L"onShowLayout", 1, (void*)Container::script_onShowLayout }, + {L"getLayout", 1, (void*)Container::script_getLayout }, + {L"getNumLayouts", 0, (void*)Container::script_getNumLayouts }, + {L"enumLayout", 1, (void*)Container::script_enumLayout }, + {L"getCurLayout", 0, (void*)Container::script_getCurrentLayout}, + {L"switchToLayout", 1, (void*)Container::script_switchToLayout }, + {L"isDynamic", 0, (void*)Container::script_isDynamic }, + {L"show", 0, (void*)Container::script_show }, + {L"hide", 0, (void*)Container::script_hide }, + {L"close", 0, (void*)Container::script_close}, + {L"toggle", 0, (void*)Container::script_toggle }, + {L"setName", 1, (void*)Container::script_setName }, + {L"getName", 0, (void*)Container::script_getName }, + {L"getGuid", 0, (void*)Container::script_getGuid }, + {L"setXmlParam", 2, (void*)Container::script_setXmlParam}, + {L"onAddContent", 3, (void*)Container::script_onAddContent}, + }; +// -------------------------------------------------------- + +/*SET_HIERARCHY(Container, SCRIPT_CONTAINER); +SET_HIERARCHY2(Container, SCRIPT_CONTAINER, CONTAINER_SCRIPTPARENT);*/ + +const wchar_t *ContainerScriptController::getClassName() +{ + return L"Container"; +} + +const wchar_t *ContainerScriptController::getAncestorClassName() +{ + return L"Object"; +} + +ScriptObjectController *ContainerScriptController::getAncestorController() +{ + return rootScriptObjectController; +} + +int ContainerScriptController::getInstantiable() +{ + return 1; +} + +ScriptObject *ContainerScriptController::instantiate() +{ + Container *c = new Container; + return c->getScriptObject(); +} + +void ContainerScriptController::destroy(ScriptObject *o) +{ + //ASSERTALWAYS("be nice, don't do that"); + Container *c = (Container *)o->vcpu_getInterface(containerGuid); + delete c; +} + +void *ContainerScriptController::encapsulate(ScriptObject *o) +{ + return NULL; +} + +void ContainerScriptController::deencapsulate(void *o) +{} + + +int ContainerScriptController::getNumFunctions() +{ + return sizeof(exportedFunction) / sizeof(function_descriptor_struct); +} + +const function_descriptor_struct *ContainerScriptController::getExportedFunctions() +{ + return exportedFunction; +} + +GUID ContainerScriptController::getClassGuid() +{ + return containerGuid; +} + +//----------------------------------------------------------------------- + +scriptVar Container::script_onSwitchToLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar l) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS1(o, containerController, l); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT1(o, l); +} + +scriptVar Container::script_onBeforeSwitchToLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar oldl, scriptVar newl) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS2(o, containerController, oldl, newl); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT2(o, oldl, newl); +} + +scriptVar Container::script_onHideLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar l) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS1(o, containerController, l); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT1(o, l); +} + +scriptVar Container::script_onShowLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar l) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS1(o, containerController, l); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT1(o, l); +} + +// Get an layout from its ID +scriptVar Container::script_getLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar obj) +{ + SCRIPT_FUNCTION_INIT + ASSERT(obj.type == SCRIPT_STRING); // compiler discarded + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) + { + for (int i = 0;i < c->layouts.getNumItems();i++) + if (!WCSICMP(obj.data.sdata, c->layouts.enumItem(i)->getGuiObject()->guiobject_getId())) + { + return MAKE_SCRIPT_OBJECT(c->layouts.enumItem(i)->getGuiObject()->guiobject_getScriptObject()); + } + } + RETURN_SCRIPT_ZERO; +} + +scriptVar Container::script_show(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) c->setVisible(1); + RETURN_SCRIPT_VOID; +} +scriptVar Container::script_hide(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) c->setVisible(0); + RETURN_SCRIPT_VOID; +} + +scriptVar Container::script_close(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) c->close(); + RETURN_SCRIPT_VOID; +} + +scriptVar Container::script_toggle(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) c->toggle(); + RETURN_SCRIPT_VOID; +} + +// Switch to another layout +scriptVar Container::script_switchToLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar l) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) + c->switchToLayout(GET_SCRIPT_STRING(l)); + RETURN_SCRIPT_VOID; +} + +scriptVar Container::script_getNumLayouts(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) return MAKE_SCRIPT_INT(c->getNumLayouts()); + RETURN_SCRIPT_ZERO; +} + +scriptVar Container::script_enumLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar n) +{ + SCRIPT_FUNCTION_INIT + ASSERT(SOM::isNumeric(&n)); // compiler discarded + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + Layout *l = NULL; + if (c) l = c->enumLayout(SOM::makeInt(&n)); + return MAKE_SCRIPT_OBJECT(l ? l->getScriptObject() : NULL); +} + +scriptVar Container::script_getCurrentLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + Layout *l = c->getCurrentLayout(); + return MAKE_SCRIPT_OBJECT(l ? l->getScriptObject() : NULL); +} + +// Switch to another layout +scriptVar Container::script_vcpu_getId(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + + if (c) + return MAKE_SCRIPT_STRING(c->getId()); + + return MAKE_SCRIPT_STRING(L""); +} + +scriptVar Container::script_isDynamic(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) return MAKE_SCRIPT_INT(c->isDynamic()); + RETURN_SCRIPT_ZERO; +} + +scriptVar Container::script_setName(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar name) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) c->setName(GET_SCRIPT_STRING(name)); + RETURN_SCRIPT_VOID; +} + +scriptVar Container::script_getName(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) return MAKE_SCRIPT_STRING(c->getName()); + return MAKE_SCRIPT_STRING(L""); +} + +scriptVar Container::script_getGuid(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) + { + static wchar_t guidstr[256]; + nsGUID::toCharW(c->getGUID(), guidstr); + return MAKE_SCRIPT_STRING(guidstr); + } + return MAKE_SCRIPT_STRING(L""); +} + +scriptVar Container::script_setXmlParam(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar p, scriptVar v) +{ + SCRIPT_FUNCTION_INIT + Container *c = static_cast<Container *>(o->vcpu_getInterface(containerGuid)); + if (c) c->setXmlParam(GET_SCRIPT_STRING(p), GET_SCRIPT_STRING(v)); + RETURN_SCRIPT_VOID; +} + +//void Container::notifyAddContent(ifc_window *w, const wchar_t *id, GUID g) +scriptVar Container::script_onAddContent(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar window, scriptVar id, scriptVar g) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS3(o, containerController, window, id, g); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT3(o, window, id, g); +} + diff --git a/Src/Wasabi/api/wndmgr/container.h b/Src/Wasabi/api/wndmgr/container.h new file mode 100644 index 00000000..0078057d --- /dev/null +++ b/Src/Wasabi/api/wndmgr/container.h @@ -0,0 +1,231 @@ +#ifdef WASABI_COMPILE_WNDMGR +#ifndef __CONTAINER_H +#define __CONTAINER_H + +class Container; +class Layout; + +#include <bfc/ptrlist.h> +#include <api/skin/xmlobject.h> + +#ifdef WASABI_WIDGETS_GUIOBJECT +#include <api/script/objects/guiobj.h> +#endif +#include <api/script/script.h> +#include <api/script/scriptobj.h> +#include <api/script/objcontroller.h> +#include <api/script/objects/rootobj.h> + + +#define CONTAINER_UNDEFINED_NAME L"undefined container name" + +enum { + CONTAINERPARAM_NAME = 0, + CONTAINERPARAM_ID, + CONTAINERPARAM_DYNAMIC, + CONTAINERPARAM_DEFAULTX, + CONTAINERPARAM_DEFAULTY, + CONTAINERPARAM_DEFAULTVISIBLE, + CONTAINERPARAM_CANCLOSE, + CONTAINERPARAM_NOMENU, + CONTAINERPARAM_NOFOCUSAPPONCLOSE, + CONTAINERPARAM_CONTENT, +}; + +class ContainerScriptController: public ScriptObjectControllerI +{ +public: + + virtual const wchar_t *getClassName(); + virtual const wchar_t *getAncestorClassName(); + virtual ScriptObjectController *getAncestorController(); + virtual int getNumFunctions(); + virtual const function_descriptor_struct *getExportedFunctions(); + virtual GUID getClassGuid(); + virtual ScriptObject *instantiate(); + virtual void destroy(ScriptObject *o); + virtual void *encapsulate(ScriptObject *o); + virtual void deencapsulate(void *o); + virtual int getInstantiable(); + +private: + + static function_descriptor_struct exportedFunction[]; + +}; + +class ContentEntry +{ +public: + ContentEntry(const wchar_t *gid, GUID g, ifc_window *w) : groupid(gid), guid(g), wnd(w) { } + + GUID guid; + StringW groupid; + ifc_window *wnd; +}; + +extern ContainerScriptController *containerController; + +#define CONTAINER_SCRIPTPARENT RootObjectInstance + +class Container : public CONTAINER_SCRIPTPARENT, public XmlObjectI, public DependentI +{ + +public: + Container(int scriptid = -1); + virtual ~Container(); + + virtual void setName(const wchar_t *name); + virtual void setId(const wchar_t *id); + + virtual const wchar_t *getName(); + virtual const wchar_t *getId(); + + virtual int setXmlParam(const wchar_t *p, const wchar_t *v); + + virtual void onInit(int noshow = 0); + + virtual void addLayout(Layout *layout); + virtual void resetLayouts(); + + virtual void setVisible(int sh); + virtual int isVisible(); + + virtual void switchToLayout(const wchar_t *name, int moveit = 1); + virtual void toggle(); + virtual void close(); + virtual void sysMenu(); + virtual int getNumLayouts(); + virtual Layout *enumLayout(int n); + virtual Layout *getLayout(const wchar_t *name, int *pos = NULL); + virtual int getScriptId(); + virtual void savePositions(); + void setDefaultLayout(const wchar_t *name); + void loadFromDefaults(int noshow = 0); + int isTranscient() { return transcient; } + void setTranscient(int is) { transcient = is; } + + // player callbacks to notify that container/component + // has been set visible/invisible + virtual void otherContainerToggled(const wchar_t *id, int visible); + virtual void componentToggled(GUID *g, int visible); + + virtual int isMainContainer(); + virtual int isDynamic(); + + virtual void onSwitchToLayout(Layout *l); + virtual void onBeforeSwitchToLayout(Layout *oldl, Layout *newl); + virtual void onHideLayout(Layout *l); + virtual void onShowLayout(Layout *l); + virtual Layout *getCurrentLayout(); + virtual int getDefaultPositionX(void); + virtual int getDefaultPositionY(void); + virtual void onChildSetLayoutVisible(Layout *l, int v); + + virtual void notifyAddContent(ifc_window *w, const wchar_t *groupid, GUID guid = INVALID_GUID); + virtual void notifyRemoveContent(ifc_window *w); + virtual int hasContent(GUID g); + virtual GUID getDefaultContent(); + + const wchar_t *getDescriptor(void); + + virtual void getWindowRect(RECT *r); + + virtual void sendNotifyToAllLayouts(int notifymsg, int param1, int param2); + void setDynamic(int i); + + void updateDefaultVisible(); + void setDeleting() { deleting = 1; } + int isDeleting() { return deleting; } + int isInited() { return inited; } + + int canClose() { return canclose; } + void setCanClose(int c) { canclose = c; } + GUID getGUID() { return myGUID; } + + int getNoMenu() { return nomenu; } + + void setPreventSaveVisibility(int p) { prevent_save_visibility = p; } + int wantRefocusApp() { return refocusapponclose; } + void setWantRefocusApp(int rf) { refocusapponclose = rf; } + + public: + // ifc_dependent stuff + + static const GUID *depend_getClassGuid() { + // {C439D9F4-34F5-453c-B947-448ED20203FC} + static const GUID ret = + { 0xc439d9f4, 0x34f5, 0x453c, { 0xb9, 0x47, 0x44, 0x8e, 0xd2, 0x2, 0x3, 0xfc } }; + + return &ret; + } + enum + { + Event_NAMECHANGE = 0, + }; + + +private: + void containerCallback(int msg); + StringW containerName; + StringW containerId; + PtrList<Layout> layouts; + int currentLayout; + StringW last_layout; + int canclose; + int lastLayout; + int default_visible, loaded_default_visible; + int ismain; + int dynamic; + int default_x = -1; + int default_y = -1; + int default_w = -1; + int default_h = -1; + int scriptid; + int inited; + int deleting; + int transcient; + PtrList<ContentEntry> contents; + int switching_layout; + int nomenu; + int prevent_save_visibility; + int refocusapponclose; + GUID contentGuid; + bool hasContentGuid; + +private: + GUID myGUID; + void showDefaultLayout(int noshow = 0); + +public: + static scriptVar script_vcpu_getId(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_onSwitchToLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar l); + static scriptVar script_onBeforeSwitchToLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar oldl, scriptVar newl); + static scriptVar script_onHideLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar l); + static scriptVar script_onShowLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar l); + static scriptVar script_getLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar obj); + static scriptVar script_switchToLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar s); + static scriptVar script_getCurrentLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_show(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_hide(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_close(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_toggle(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_getNumLayouts(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_enumLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar n); + static scriptVar script_isDynamic(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_setName(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar name); + static scriptVar script_getName(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_getGuid(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_setXmlParam(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar p, scriptVar v); + static scriptVar script_onAddContent(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar window, scriptVar id, scriptVar g); + +}; + +enum { + CONT_CB_NONE, + CONT_CB_VISIBLE, + CONT_CB_HIDDEN +}; + +#endif +#endif diff --git a/Src/Wasabi/api/wndmgr/gc.cpp b/Src/Wasabi/api/wndmgr/gc.cpp new file mode 100644 index 00000000..c312b9ea --- /dev/null +++ b/Src/Wasabi/api/wndmgr/gc.cpp @@ -0,0 +1,24 @@ +#include <precomp.h> +#include "gc.h" + +GarbageCollector *garbageCollector=NULL; + +GarbageCollector::GarbageCollector() { + last = 0; + WASABI_API_SYSCB->syscb_registerCallback(this); +} + +GarbageCollector::~GarbageCollector() { + WASABI_API_SYSCB->syscb_deregisterCallback(this); +} + +int GarbageCollector::gccb_onGarbageCollect() { + uint32_t tc = Wasabi::Std::getTickCount(); + if (tc < last + 10000) return 0; + + last = tc; +#ifdef WIN32 + //SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1); +#endif + return 0; +} diff --git a/Src/Wasabi/api/wndmgr/gc.h b/Src/Wasabi/api/wndmgr/gc.h new file mode 100644 index 00000000..a57d24b4 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/gc.h @@ -0,0 +1,19 @@ +#ifndef __GARBAGECOLLECT_H +#define __GARBAGECOLLECT_H + +#include <api/syscb/callbacks/gccb.h> + +class GarbageCollector : public GarbageCollectCallbackI { + public: + GarbageCollector(); + virtual ~GarbageCollector(); + + virtual int gccb_onGarbageCollect(); + + private: + uint32_t last; +}; + +extern GarbageCollector *garbageCollector; + +#endif diff --git a/Src/Wasabi/api/wndmgr/guistatuscb.cpp b/Src/Wasabi/api/wndmgr/guistatuscb.cpp new file mode 100644 index 00000000..761a18a1 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/guistatuscb.cpp @@ -0,0 +1,15 @@ +#include <precomp.h> +#include "guistatuscb.h" + +#define CBCLASS GuiStatusCallbackI +START_DISPATCH; + CB(STATUS_GETDEP, status_getDependencyPtr); + VCB(STATUS_ONSETTEXT, onSetStatusText); + VCB(STATUS_ADDCTXTCMDS, onAddAppCmds); + VCB(STATUS_REMCTXTCMDS, onRemoveAppCmds); + VCB(STATUS_PUSHCOMPLETED, pushCompleted); + VCB(STATUS_INCCOMPLETED, incCompleted); + VCB(STATUS_SETCOMPLETED, setCompleted); + VCB(STATUS_POPCOMPLETED, popCompleted); +END_DISPATCH; +#undef CBCLASS diff --git a/Src/Wasabi/api/wndmgr/guistatuscb.h b/Src/Wasabi/api/wndmgr/guistatuscb.h new file mode 100644 index 00000000..f35a4d9f --- /dev/null +++ b/Src/Wasabi/api/wndmgr/guistatuscb.h @@ -0,0 +1,83 @@ +#ifndef _GUISTATUSCB_H +#define _GUISTATUSCB_H + +#include <bfc/dispatch.h> + +class AppCmds; +class ifc_dependent; + +class GuiStatusCallback : public Dispatchable { + public: + void onSetStatusText(const wchar_t *text, int overlay); + void onAddAppCmds(AppCmds *commands); + void onRemoveAppCmds(AppCmds *commands); + void pushCompleted(int max=100); + void incCompleted(int add=1); + void setCompleted(int pos); + void popCompleted(); + + api_dependent *status_getDependencyPtr(); + enum { + STATUS_ONSETTEXT = 101, + STATUS_GETDEP = 200, + STATUS_ADDCTXTCMDS = 300, + STATUS_REMCTXTCMDS = 400, + STATUS_PUSHCOMPLETED = 500, + STATUS_INCCOMPLETED = 600, + STATUS_SETCOMPLETED = 700, + STATUS_POPCOMPLETED = 800, + }; +}; + +inline void GuiStatusCallback ::onSetStatusText(const wchar_t *text, int overlay) { + _voidcall(STATUS_ONSETTEXT, text, overlay); +} + +inline api_dependent *GuiStatusCallback ::status_getDependencyPtr() { + return _call(STATUS_GETDEP, (api_dependent *)NULL); +} + +inline void GuiStatusCallback ::onAddAppCmds(AppCmds *commands) { + _voidcall(STATUS_ADDCTXTCMDS, commands); +} + +inline void GuiStatusCallback ::onRemoveAppCmds(AppCmds *commands) { + _voidcall(STATUS_REMCTXTCMDS, commands); +} + +inline +void GuiStatusCallback::pushCompleted(int max) { + _voidcall(STATUS_PUSHCOMPLETED, max); +} + +inline +void GuiStatusCallback::incCompleted(int add) { + _voidcall(STATUS_INCCOMPLETED, add); +} + +inline +void GuiStatusCallback::setCompleted(int pos) { + _voidcall(STATUS_SETCOMPLETED, pos); +} + +inline +void GuiStatusCallback::popCompleted() { + _voidcall(STATUS_POPCOMPLETED); +} + +class GuiStatusCallbackI : public GuiStatusCallback { + public: + virtual void onSetStatusText(const wchar_t *text, int overlay)=0; + virtual api_dependent *status_getDependencyPtr()=0; + virtual void onAddAppCmds(AppCmds *commands)=0; + virtual void onRemoveAppCmds(AppCmds *commands)=0; + virtual void pushCompleted(int max=100)=0; + virtual void incCompleted(int add=1)=0; + virtual void setCompleted(int pos)=0; + virtual void popCompleted()=0; + + protected: + RECVS_DISPATCH; +}; + +#endif diff --git a/Src/Wasabi/api/wndmgr/layout.cpp b/Src/Wasabi/api/wndmgr/layout.cpp new file mode 100644 index 00000000..006a953d --- /dev/null +++ b/Src/Wasabi/api/wndmgr/layout.cpp @@ -0,0 +1,2586 @@ +#include <precomp.h> +#include <api/skin/widgets/mb/scriptbrowser.h> +#include <tataki/bitmap/bitmap.h> +#include <api/wnd/popup.h> +#include <api/wndmgr/msgbox.h> +#include <api/skin/widgets/group.h> +#include "layout.h" +#include <api/skin/skinparse.h> +#include <api/skin/widgets/button.h> +#include <api/core/buttons.h> +#include <api/wnd/wndtrack.h> +//#include <api/wac/main.h> //CUT! +#include <api/skin/widgets/compbuck2.h> +#include <api/wac/compon.h> +#include <api/skin/skin.h> +#include <api/wnd/notifmsg.h> +#include <api/config/items/intarray.h> +#include <api/config/items/cfgitem.h> +#include <api/config/options.h> +#include <api/script/script.h> +#include <api/script/scriptmgr.h> +#include <bfc/parse/pathparse.h> +#include <api/skin/groupmgr.h> +#include <api/wndmgr/skinembed.h> +#include <api/skin/skinparse.h> +#include <api/service/svcs/svc_action.h> +#include <api/config/items/attrbool.h> +#include <api/config/items/attrint.h> +#include <api/wndmgr/alphamgr.h> +#include <bfc/wasabi_std_wnd.h> +#include <api/wnd/PaintCanvas.h> +#ifdef _WIN32 +#include <windowsx.h> // for SetWindowRedraw +#endif + +#ifdef WASABINOMAINAPI +#include <api/wndmgr/gc.h> +#include <api/syscb/callbacks/gccb.h> +#endif + +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x20A +#endif + +#define TIMER_SETTINGCHANGED 0x8791 +#define TIMER_AUTOOPACIFY 0x8792 +#define TIMER_AUTOOPACIFY2 0x8793 +#define TIMER_OFFSCREENCHECK 0x8794 +#define TIMER_TRANSPARENCY_AUTOON 0x8795 +#define TIMER_SAVE_POSITION 0x8796 +#define TIMER_SAVE_ALL_POSITIONS 0x8797 + +#ifdef WASABI_COMPILE_CONFIG +extern _bool cfg_uioptions_linkallalpha; +extern _bool cfg_uioptions_linkallratio; +extern _int cfg_uioptions_autoopacitylinked; +extern _int cfg_uioptions_autoopacitytime; +extern _int cfg_uioptions_extendautoopacity; +extern _int cfg_uioptions_autoopacityfadein; +extern _int cfg_uioptions_autoopacityfadeout; +extern _int cfg_uioptions_linkedalpha; +extern _bool cfg_options_appbarondrag; +#endif + +AlphaMgr *alphaMgr = NULL; +XMLParamPair Layout::params[] = + { + {LAYOUT_SETALPHA, L"ALPHA"}, + {LAYOUT_SETALPHABACKGROUND, L"ALPHABACKGROUND"}, + {LAYOUT_SETDESKTOPALPHA, L"DESKTOPALPHA"}, + {LAYOUT_FORCEALPHA, L"FORCEALPHA"}, + {LAYOUT_SETINDESKTOP, L"INDESKTOP"}, + {LAYOUT_SETLINKHEIGHT, L"LINKHEIGHT"}, + {LAYOUT_SETLINKWIDTH, L"LINKWIDTH"}, + {LAYOUT_SETLOCKTO, L"LOCKTO"}, + {LAYOUT_SETNOACTIVATION, L"NOACTIVATION"}, + {LAYOUT_NODOCK, L"NODOCK"}, + {LAYOUT_NOOFFSCREENCHECK, L"NOOFFSCREENCHECK"}, + {LAYOUT_NOPARENT, L"NOPARENT"}, + {LAYOUT_SETONTOP, L"ONTOP"}, + {LAYOUT_SETOSFRAME, L"OSFRAME"}, + {LAYOUT_SETOWNER, L"OWNER"}, + {LAYOUT_SNAPADJUSTBOTTOM, L"SNAPADJUSTBOTTOM"}, + {LAYOUT_SNAPADJUSTLEFT, L"SNAPADJUSTLEFT"}, + {LAYOUT_SNAPADJUSTRIGHT, L"SNAPADJUSTRIGHT"}, + {LAYOUT_SNAPADJUSTTOP, L"SNAPADJUSTTOP"}, + {LAYOUT_UNLINKED, L"UNLINKED"}, + {LAYOUT_RESIZABLE, L"RESIZABLE"}, + {LAYOUT_SCALABLE, L"SCALABLE"}, + }; + +Layout::Layout() +{ + getScriptObject()->vcpu_setInterface(layoutGuid, (void *)static_cast<Layout *>(this)); + getScriptObject()->vcpu_setInterface(guiResizableGuid, (void *)static_cast<GuiResizable *>(this)); + getScriptObject()->vcpu_setClassName(L"Layout"); + getScriptObject()->vcpu_setController(layoutController); +#ifdef _WIN32 + forwardMsgWnd = INVALIDOSWINDOWHANDLE; +#endif + transparency_reenabled_at = 0; + transparency_autooff = 0; + captured = 0; resizing = 0; + m_forceunlink = 0; + inresize = 0; + autoopacify = 0; + x = 0; y = 0; +#ifdef USEAPPBAR + appbar_want_autohide = 1; + appbar_want_alwaysontop = 1; + m_allowsavedock = 0; +#endif + size_w = 0; size_h = 0; + reg = NULL; + //subregionlayers = new PtrList<Layer>; + setStartHidden(TRUE); + moving = 0; + setVirtual(0); + indesktop = 0; + p_container = NULL; + alpha = 255; + linkedheight = NULL; + linkedwidth = NULL; + inlinkwidth = 0; + inlinkheight = 0; + wantactiv = 1; + wantdesktopalpha = 0; + alllayouts.addItem(this); + galphadisabled = 0; + lockedto = NULL; + osframe = 0; + scalelocked = 0; + initontop = 0; + wantredrawonresize = 1; + getGuiObject()->guiobject_setMover(1); + snap_adjust_left = snap_adjust_right = snap_adjust_top = snap_adjust_bottom = 0; + disable_auto_alpha = 0; + unlinked = 0; + scaling = 0; + transparencyoverride = -1; + noparent = 0; + forcealpha = 0; + nodock = 0; + resizable = 1; + scalable = 1; + nooffscreencheck = 0; + m_w = m_h = m_endmovesize = 0; + + xuihandle = newXuiHandle(); + CreateXMLParameters(xuihandle); + + if (!alphaMgr) + { + alphaMgr = new AlphaMgr(); + #ifdef WASABI_COMPILE_CONFIG + alphaMgr->setAllLinked(cfg_uioptions_linkallalpha.getValueAsInt()); + alphaMgr->setAutoOpacify(cfg_uioptions_autoopacitylinked.getValueAsInt()); + alphaMgr->setGlobalAlpha(cfg_uioptions_linkedalpha.getValueAsInt()); + alphaMgr->setHoldTime(cfg_uioptions_autoopacitytime.getValueAsInt()); + alphaMgr->setFadeInTime(cfg_uioptions_autoopacityfadein.getValueAsInt()); + alphaMgr->setFadeOutTime(cfg_uioptions_autoopacityfadeout.getValueAsInt()); + alphaMgr->setExtendAutoOpacity(cfg_uioptions_extendautoopacity.getValueAsInt()); +#endif + } + alphaMgr->addLayout(this); +} + +void Layout::CreateXMLParameters(int master_handle) +{ + //LAYOUT_SCRIPTPARENT::CreateXMLParameters(master_handle); + int numParams = sizeof(params) / sizeof(params[0]); + hintNumberOfParams(xuihandle, numParams); + for (int i = 0;i < numParams;i++) + addParam(xuihandle, params[i], XUI_ATTRIBUTE_IMPLIED); +} + +Layout::~Layout() +{ + if (transparency_reenabled_at) killTimer(TIMER_TRANSPARENCY_AUTOON); + alphaMgr->removeLayout(this); + killTimer(TIMER_OFFSCREENCHECK); + if (lockedto) lockedto->removeLockedLayout(this); + WASABI_API_WNDMGR->wndTrackRemove(this); + if (reg) delete reg; + alllayouts.removeItem(this); +} + +int Layout::setXuiParam(int _xuihandle, int attrid, const wchar_t *paramname, const wchar_t *strvalue) +{ + if (xuihandle != _xuihandle) return LAYOUT_PARENT::setXuiParam(_xuihandle, attrid, paramname, strvalue); + switch (attrid) + { + case LAYOUT_SETDESKTOPALPHA: + setWantDesktopAlpha(WTOI(strvalue)); + break; + case LAYOUT_SETINDESKTOP: + setInDesktop(WTOI(strvalue)); + break; + case LAYOUT_SETALPHA: + setAlpha(WTOI(strvalue)); + break; + case LAYOUT_SETLINKWIDTH: + setLinkWidth(strvalue); + if (*strvalue && isPostOnInit() && isVisible()) onResize(); + break; + case LAYOUT_SETLINKHEIGHT: + setLinkHeight(strvalue); + if (*strvalue && isPostOnInit() && isVisible()) onResize(); + break; + case LAYOUT_SETOWNER: + owner = strvalue; + break; + case LAYOUT_NOPARENT: + setNoParent(WTOI(strvalue)); + break; + case LAYOUT_FORCEALPHA: + forcealpha = WTOI(strvalue); + break; + case LAYOUT_SETLOCKTO: + lockto = strvalue; + break; + case LAYOUT_SETOSFRAME: + osframe = WTOI(strvalue); + break; + case LAYOUT_SETALPHABACKGROUND: + setAlphaBackground(strvalue); + setWantDesktopAlpha(1); + setDrawBackground(1); + break; + case LAYOUT_SETNOACTIVATION: + wantactiv = WTOI(strvalue) ? 0 : 1; + break; + case LAYOUT_SETONTOP: + initontop = WTOI(strvalue); + if (isPostOnInit()) updateOnTop(); + break; + case LAYOUT_SNAPADJUSTLEFT: + snap_adjust_left = WTOI(strvalue); + script_vcpu_onSnapAdjustChanged(SCRIPT_CALL, getScriptObject()); +#ifdef USEAPPBAR + if (appbar_isDocked()) appbar_posChanged(); +#endif + break; + case LAYOUT_SNAPADJUSTTOP: + snap_adjust_top = WTOI(strvalue); + script_vcpu_onSnapAdjustChanged(SCRIPT_CALL, getScriptObject()); + #ifdef USEAPPBAR + if (appbar_isDocked()) appbar_posChanged(); +#endif + break; + case LAYOUT_SNAPADJUSTRIGHT: + snap_adjust_right = WTOI(strvalue); + script_vcpu_onSnapAdjustChanged(SCRIPT_CALL, getScriptObject()); + #ifdef USEAPPBAR + if (appbar_isDocked()) appbar_posChanged(); +#endif + break; + case LAYOUT_SNAPADJUSTBOTTOM: + snap_adjust_bottom = WTOI(strvalue); + script_vcpu_onSnapAdjustChanged(SCRIPT_CALL, getScriptObject()); + #ifdef USEAPPBAR + if (appbar_isDocked()) appbar_posChanged(); +#endif + break; + case LAYOUT_UNLINKED: + unlinked = WTOI(strvalue); + if (!unlinked && isPostOnInit() && isVisible()) onResize(); + break; + case LAYOUT_NODOCK: + setNoDock(WTOI(strvalue)); + break; + case LAYOUT_NOOFFSCREENCHECK: + setNoOffscreenCheck(WTOI(strvalue)); + break; + case LAYOUT_RESIZABLE: + resizable = WTOI(strvalue); + break; + case LAYOUT_SCALABLE: + scalable = WTOI(strvalue); + break; + default: + return 0; + } + return 1; +} + +void Layout::setLinkHeight(const wchar_t *layoutid) +{ + linkedheight = layoutid; +} + +void Layout::setLinkWidth(const wchar_t *layoutid) +{ + linkedwidth = layoutid; +} + +int Layout::onPostedMove() +{ + updateLockedLayouts(); + int r = LAYOUT_PARENT::onPostedMove(); + Container *c = getParentContainer(); + if (isVisible() && c && c->isMainContainer()) + { +#ifdef WASABI_ON_MAIN_MOVE + WASABI_ON_MAIN_MOVE(gethWnd()); +#endif + + } + return r; +} + +void Layout::cancelCapture() +{ + if (getCapture()) + endCapture(); + captured = 0; +} + +int Layout::isOffscreen(ifc_window *w) +{ + if (!w->isVisible()) return 0; + if (nooffscreencheck) return 0; +#ifdef USEAPPBAR + if (appbar_isDocked()) return 0; +#endif + if (lockedto) return 0; + RECT wr; + w->getWindowRect(&wr); + windowTracker->snapAdjustWindowRect(w, &wr); + RECT r; + + int isontop = 0; + if (w->getGuiObject()) + { + isontop = WTOI(w->getGuiObject()->guiobject_getXmlParam(L"ontop")); +#ifndef EXPERIMENTAL_INDEPENDENT_AOT + if (WTOI(w->getGuiObject()->guiobject_getXmlParam(L"noparent")) == 0) + isontop = 0; +#endif + + } + if (!isontop) + { +#ifdef WASABI_COMPILE_CONFIG + extern _bool cfg_options_alwaysontop; + isontop |= cfg_options_alwaysontop.getValueAsInt(); +#endif + } + Wasabi::Std::getViewport(&r, NULL, &wr, NULL, isontop); + if (wr.right < r.left + 10 || + wr.bottom < r.top + 10 || + wr.left > r.right - 10 || + wr.top > r.bottom - 10) + { + return 1; + } //////TO CONTINUE + return 0; +} + +void Layout::offscreenCheck() +{ + int disabled = 0; +#ifdef WASABI_CHECK_OFFSCREENCHECK_DISABLE + WASABI_CHECK_OFFSCREENCHECK_DISABLE(disabled); +#endif + if (disabled) return ; + if (!isVisible()) return ; + if (moving || scaling || resizing) return ; + if (isOffscreen(this)) + { + windowTracker->startCooperativeMove(this); + for (int i = 0;i < windowTracker->getNumDocked();i++) + { + ifc_window *w = windowTracker->enumDocked(i); + Layout *l = static_cast<Layout*>(w->getInterface(layoutGuid)); + if (l != NULL) + { + if (l->getParentContainer() && l->getParentContainer()->isMainContainer()) + { + if (!isOffscreen(l)) + { + windowTracker->endCooperativeMove(); + return ; + } + } + } + } + windowTracker->endCooperativeMove(); + RECT wr; + getWindowRect(&wr); + RECT nr = windowTracker->findOpenRect(wr); + move(nr.left, nr.top); + } +} + +/** + * This one only prevents UI resizings from layers! + */ +int Layout::getResizable () +{ + return this->resizable; +} + +/** + * This one only prevents UI scalings from layers! + */ +int Layout::getScalable () +{ + return this->scalable; +} + +void Layout::setTransparencyOverride(int v) +{ + transparencyoverride = v; + if (v != -1) setTransparency(v); else updateTransparency(); +} + +#ifndef PI +#define PI 3.1415926536 +#endif + +void Layout::timerCallback(int id) +{ + if (id == TIMER_TRANSPARENCY_AUTOON) + { + if (!isTransparencySafe(1)) + { + transparency_reenabled_at = 0; + return ; + } + int n = Wasabi::Std::getTickCount() - transparency_reenabled_at; + if (n < 1000) return ; + else + { + killTimer(TIMER_TRANSPARENCY_AUTOON); + transparency_autooff = 0; + updateTransparency(); + transparency_reenabled_at = 0; + } + return ; + } + else if (id == TIMER_OFFSCREENCHECK) + { + offscreenCheck(); + return ; + } + else if (id == TIMER_SETTINGCHANGED) + { + killTimer(TIMER_SETTINGCHANGED); +#ifdef _WIN32 + HWND parent; + webserver = INVALIDOSWINDOWHANDLE; + listview = INVALIDOSWINDOWHANDLE; + getExplorerWindows(&parent, &listview, &webserver); + if (!webserver) // active desktop now off, reposition this window zorder otherwise it will be behind the icons +#ifdef WIN32 + SetWindowPos(gethWnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE); +#else + bringToFront(); +#endif +#endif + } + else if (id == TIMER_SAVE_ALL_POSITIONS) + { + killTimer(TIMER_SAVE_ALL_POSITIONS); + saveAllPositions(); + // TODO: benski> not 100% sure we want to call into the script on the timer (maybe do it in endMove) + //script_vcpu_onEndMove(SCRIPT_CALL, getScriptObject()); + return; + } + else if (id == TIMER_SAVE_POSITION) + { + killTimer(TIMER_SAVE_POSITION); + savePosition(); + // TODO: benski> not 100% sure we want to call into the script on the timer (maybe do it in endMove) + //script_vcpu_onEndMove(SCRIPT_CALL, getScriptObject()); + return; + } + else LAYOUT_PARENT::timerCallback(id); +} + +void Layout::onMouseEnterLayout() +{ + script_vcpu_onMouseEnterLayout(SCRIPT_CALL, getScriptObject()); +} + +void Layout::onMouseLeaveLayout() +{ + script_vcpu_onMouseLeaveLayout(SCRIPT_CALL, getScriptObject()); +} + +void Layout::beginMove() +{ + moving = 1; +} + +void Layout::beginScale() +{ + scaling = 1; +} + +void Layout::beginResize() +{ + resizing = 1; +} + +void Layout::endMove() +{ + if (m_endmovesize) + { + m_endmovesize = 0; + RECT r; + guiresizable_getRootWnd()->getWindowRect(&r); + r.right = r.left + m_w; + r.bottom = r.top + m_h; + guiresizable_getRootWnd()->resizeToRect(&r); + } + moving = 0; + // TODO: benski> do this on a resetable timer so it doesn't go so slowly + if (WASABI_API_WNDMGR->wndTrackWasCooperative()) + setTimer(TIMER_SAVE_ALL_POSITIONS, 1000); +// saveAllPositions(); + else + setTimer(TIMER_SAVE_POSITION, 1000); + //savePosition(); + // TODO: benski> not 100% sure we want to call into the script on the timer (maybe do it in endMove) + script_vcpu_onEndMove(SCRIPT_CALL, getScriptObject()); +} + +void Layout::endScale() +{ + scaling = 0; + savePosition(); + fixPosition(); +} + +void Layout::endResize() +{ + resizing = 0; + RECT r; + getClientRect(&r); + RECT wr; + getWindowRect(&wr); + script_vcpu_onUserResize(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_INT(wr.left), MAKE_SCRIPT_INT(wr.top), MAKE_SCRIPT_INT(r.right - r.left), MAKE_SCRIPT_INT(r.bottom - r.top)); + savePosition(); +} + +void Layout::onMove() +{ + script_vcpu_onMove(SCRIPT_CALL, getScriptObject()); +} + +void Layout::setAutoOpacify(int a) +{ + if (autoopacify == a) return ; + autoopacify = a != -1 ? a : autoopacify; + if (getParentContainer() && !getParentContainer()->isTranscient()) + { + StringW tmp; + tmp.printf(L"Skin:%s/Container:%s/Layout:%s/autoopacify", WASABI_API_SKIN->getSkinName(), getParentContainer()->getDescriptor(), getGuiObject()->guiobject_getId()); + IntArray::write(tmp, autoopacify); + } + updateTransparency(); +} + +void Layout::controlMenu() +{ + PopupMenu pop; + int x = 1; +#ifdef WASABI_CHECK_CAN_EXIT + WASABI_CHECK_CAN_EXIT(x) +#endif + if (getParentContainer() && getParentContainer()->isMainContainer()) + { + if (x) + { + pop.addCommand(StringPrintfW(L"Exit %s", WASABI_API_APP->main_getAppName()), ACTION_CLOSE); + pop.addSeparator(); + } + } + else + { + if (!getParentContainer() || getParentContainer()->canClose()) + { + pop.addCommand(L"Close window", ACTION_CLOSE_WINDOW); + pop.addSeparator(); + } + } + PopupMenu *scalemenu = new PopupMenu(); + scalemenu->addCommand(L"50%", ACTION_SCALE_50); + scalemenu->addCommand(L"75%", ACTION_SCALE_75, FALSE, FALSE); + scalemenu->addCommand(L"100%", ACTION_SCALE_100); + scalemenu->addCommand(L"125%", ACTION_SCALE_125); + scalemenu->addCommand(L"150%", ACTION_SCALE_150); + scalemenu->addCommand(L"200%", ACTION_SCALE_200); + scalemenu->addCommand(L"400%", ACTION_SCALE_400, FALSE, FALSE); + pop.addSubMenu(scalemenu, L"Scale"); + + PopupMenu *opaqmenu = new PopupMenu(); + opaqmenu->addCommand(L"Auto-fade", ACTION_AUTOOPACIFY, getAutoOpacify(), FALSE); + opaqmenu->addSeparator(); + opaqmenu->addCommand(L"100%", ACTION_ALPHA_100, FALSE, FALSE); + opaqmenu->addCommand(L"90%", ACTION_ALPHA_90, FALSE, FALSE); + opaqmenu->addCommand(L"80%", ACTION_ALPHA_80, FALSE, FALSE); + opaqmenu->addCommand(L"70%", ACTION_ALPHA_70, FALSE, FALSE); + opaqmenu->addCommand(L"60%", ACTION_ALPHA_60, FALSE, FALSE); + opaqmenu->addCommand(L"50%", ACTION_ALPHA_50, FALSE, FALSE); + opaqmenu->addCommand(L"40%", ACTION_ALPHA_40, FALSE, FALSE); + opaqmenu->addCommand(L"30%", ACTION_ALPHA_30, FALSE, FALSE); + opaqmenu->addCommand(L"20%", ACTION_ALPHA_20, FALSE, FALSE); + opaqmenu->addCommand(L"10%", ACTION_ALPHA_10, FALSE, FALSE); + + pop.addSubMenu(opaqmenu, L"Opacity", !isTransparencySafe()); + +#ifdef EXPERIMENTAL_INDEPENDENT_AOT + pop.addCommand(L"Always on top", ACTION_AOT, getAlwaysOnTop()); +#endif + + int r = pop.popAtMouse(); + if (r < 0) return ; + onActionNotify(r, 0); +} + +void Layout::fixPosition() +{ + RECT r; + getWindowRect(&r); + RECT orig_r = r; + + RECT vr; + RegionI reg; + + int i = 0; + while (Wasabi::Std::enumViewports(i, &vr)) + { + reg.addRect(&vr); + i++; + } + + RECT full; + reg.getBox(&full); + + + int dif = r.bottom - full.bottom; + if (dif > 0) r.top -= dif; + dif = r.right - full.right; + if (dif > 0) r.left -= dif; + dif = full.top - r.top; + if (dif > 0) r.top += dif; + dif = full.left - r.left; + if (dif > 0) r.left += dif; + + if (orig_r.left != r.left || orig_r.top != r.top) + resize(r.left, r.top, NOCHANGE, NOCHANGE); +} + +void Layout::saveAllPositions() +{ + // The positions are saved from the lastest to the first one + // The 'Player' windows and the 'Main' windows are using the same prefix + // In saving in decreasing order we are sure the lastest saved is the one for the Player + + for (int i = 0;i < SkinParser::script_getNumContainers();i++) + { + Container *c = SkinParser::script_enumContainer(i); + for (int j = c->getNumLayouts() - 1;j >= 0 ;--j) + { + Layout *l = c->enumLayout(j); + l->savePosition(); + } + } +} + +int Layout::forceTransparencyFlag() +{ + return alphaMgr->needForcedTransparencyFlag(this); +} + +void Layout::savePosition() +{ +#ifdef WASABI_COMPILE_CONFIG + if (!getParentContainer() || getParentContainer()->isTranscient()) + return ; + + if (!Wasabi::Std::Wnd::isValidWnd(getOsWindowHandle())) + return ; + + + StringW prefix = MakePrefix(); + StringPrintfW tmp( L"%s/odim", prefix.v() ); + + SkinBitmap *baseTexture = getBaseTexture(); + + if ( baseTexture ) + { + IntArray::write( tmp, baseTexture->getWidth(), baseTexture->getHeight() ); + } + else + { + IntArray::write( tmp, -2, -2 ); + } + + RECT r, rs; + getClientRect(&r); // unscaled + //DebugStringW( L"\nLayout::savePosition() - x = %d, y = %d, w = %d, h = %d \n", r.left, r.top, r.right - r.left, r.bottom - r.top ); + + if (r.left == 0 && r.top == 0 && r.right == 0 && r.bottom == 0) + return ; + + getWindowRect(&rs); // screen scaled (for x/y) + tmp.printf(L"%s/rect", prefix.v()); + IntArray::write(tmp, rs.left, rs.top, r.right - r.left, r.bottom - r.top); + //DebugStringW( L"Layout::savePosition() rect - x = %d, y = %d, w = %d, h = %d \n", rs.left, rs.top, r.right - r.left, r.bottom - r.top ); + + getRestoredRect(&rs); + tmp.printf(L"%s/restoredrect", prefix.v()); + IntArray::write(tmp, rs.left, rs.top, rs.right - rs.left, rs.bottom - rs.top); + + //DebugStringW( L"Layout::savePosition() restoredrect - x = %d, y = %d, w = %d, h = %d \n", rs.left, rs.top, rs.right - rs.left, rs.bottom - rs.top ); + + tmp.printf(L"%s/maximized", prefix.v()); + // DebugString("isMaximized = %d\n", isMaximized()); + WASABI_API_CONFIG->setIntPrivate(tmp, isMaximized()); + + tmp.printf(L"%s/r", prefix.v()); + WASABI_API_CONFIG->setStringPrivate(tmp, StringPrintfW(getRenderRatio())); + + tmp.printf(L"%s/sm", prefix.v()); + TextInfoCanvas textInfoCanvas(this); + WASABI_API_CONFIG->setStringPrivate(tmp, StringPrintfW(textInfoCanvas.getSystemFontScale())); + + tmp.printf(L"%s/sl", prefix.v()); + WASABI_API_CONFIG->setStringPrivate(tmp, StringPrintfW(scalelocked)); + + tmp.printf(L"%s/autoopacify", prefix.v()); + IntArray::write(tmp, autoopacify); + +#ifdef USEAPPBAR + saveAppBarPosition(); +#endif + +#endif +} +#ifdef USEAPPBAR +void Layout::saveAppBarPosition() +{ + if (m_allowsavedock) + { + StringW prefix = MakePrefix(); + StringW wtmp = StringPrintfW(L"%s/appbar", prefix.v()); + WASABI_API_CONFIG->setIntPrivate(wtmp, appbar_getSide()); + wtmp.printf(L"%s/appbarontop", prefix.v()); + WASABI_API_CONFIG->setIntPrivate(wtmp, appbar_wantAlwaysOnTop()); + wtmp.printf(L"%s/appbarhidden", prefix.v()); + WASABI_API_CONFIG->setIntPrivate(wtmp, appbar_isHiding()); + wtmp.printf(L"%s/appbarisautohide", prefix.v()); + WASABI_API_CONFIG->setIntPrivate(wtmp, appbar_isAutoHiding()); + wtmp.printf(L"%s/appbarwantautohide", prefix.v()); + WASABI_API_CONFIG->setIntPrivate(wtmp, appbar_wantAutoHide()); + } +} +#endif +void Layout::lockScale(int locked) +{ + scalelocked = locked; + StringW tmp; + StringW prefix = MakePrefix(); + tmp.printf(L"%s/sl", prefix.v()); + WASABI_API_CONFIG->setStringPrivate(tmp, StringPrintfW(scalelocked)); +} + +void Layout::resize(int x, int y, int w, int h, int wantcb) +{ + if (inresize) return ; + inresize = 1; + LAYOUT_PARENT::resize(x, y, w, h, wantcb); + if (!lockedto) + getGuiObject()->guiobject_setGuiPosition(&x, &y, &w, &h, NULL, NULL, NULL, NULL); + inresize = 0; +} + +void Layout::move(int x, int y) +{ + //DebugStringW( L"Layout::move( x = %d, y = %d )\n", x, y ); + + LAYOUT_PARENT::move(x, y); + getGuiObject()->guiobject_setGuiPosition(&x, &y, NULL, NULL, NULL, NULL, NULL, NULL); +} + +#define DC_CHECKLASTRESIZE 0x109 +#ifdef USEAPPBAR +#define DC_LOADSAVEDDOCK 0x10A +#endif +#define DC_INVALIDATE 0x10B + +int Layout::onResize() +{ + LAYOUT_PARENT::onResize(); + if (!abortSaving()) savePosition(); + RECT r; + getClientRect(&r); + if (!linkedwidth.isempty()) + { + if (!inlinkwidth) + { + inlinkwidth = 1; + RECT cr; + Layout *l = getParentContainer() ? getParentContainer()->getLayout(linkedwidth) : NULL; + if (l) + { + int _unlinked = l->isUnlinked(); + _unlinked |= isUnlinked(); + if (!_unlinked) + { + l->getClientRect(&cr); + POINT pt; + l->getPosition(&pt); + l->resize(pt.x, pt.y, r.right - r.left, cr.bottom - cr.top); + } + } + inlinkwidth = 0; + } + } + if (!linkedheight.isempty()) + { + if (!inlinkheight) + { + inlinkheight = 1; + RECT cr; + Layout *l = getParentContainer() ? getParentContainer()->getLayout(linkedheight) : NULL; + if (l) + { + int _unlinked = l->isUnlinked(); + _unlinked |= isUnlinked(); + if (!_unlinked) + { + l->getClientRect(&cr); + POINT pt; + l->getPosition(&pt); + l->resize(pt.x, pt.y, cr.right - cr.left, r.bottom - r.top); + } + } + } + inlinkheight = 0; + } + updateLockedLayouts(); + + postDeferredCallback(DC_CHECKLASTRESIZE); + + return 1; +} + +int Layout::onDeferredCallback(intptr_t p1, intptr_t p2) +{ + /* if (p1 == DC_CHECKLASTRESIZE) { + RECT vr; + RECT r; + RECT wr; + Std::getViewport(&vr, NULL, NULL, gethWnd(), 1); + if (renderRatioActive()) + divRatio(&vr); + getClientRect(&r); + r.bottom -= snap_adjust_bottom; + r.top += snap_adjust_top; + r.right -= snap_adjust_right; + r.left += snap_adjust_left; + getWindowRect(&wr); + int n = 0; + if (r.right-r.left > vr.right-vr.left) { r.right = r.left + vr.right-vr.left; n++; } + if (r.bottom-r.top > vr.bottom-vr.top) { r.bottom = r.top + vr.bottom-vr.top; n++; } + if (n) resize(wr.left, wr.top, r.right-r.left+snap_adjust_left+snap_adjust_right, r.bottom-r.top+snap_adjust_top+snap_adjust_bottom); + } else */ +#ifdef USEAPPBAR + if (p1 == DC_LOADSAVEDDOCK) + {} +#endif + + if (p1 == DC_INVALIDATE) + { + invalidate(); + } + return LAYOUT_PARENT::onDeferredCallback(p1, p2); + // return 1; +} + +void Layout::updateLockedLayouts() +{ + for (int i = 0;i < getNumLockedLayouts();i++) + { + Layout *l = enumLockedLayout(i); + + if (l->getRenderRatio() != getRenderRatio()) + l->setRenderRatio(getRenderRatio()); + + int x, y, w, h; + l->getGuiObject()->guiobject_getGuiPosition(&x, &y, &w, &h, NULL, NULL, NULL, NULL); + RECT r; + l->getClientRect(&r); + if (w == AUTOWH) w = r.right - r.left; + if (h == AUTOWH) h = r.bottom - r.top; + POINT pt; + l->getPosition(&pt); + if (x == AUTOWH) x = pt.x; else clientToScreen(&x, NULL); + if (y == AUTOWH) y = pt.y; else clientToScreen(NULL, &y); + RECT cr; + l->getWindowRect(&cr); + if (cr.left != x || cr.top != y || cr.right != cr.left + w || cr.bottom != cr.top + h) + l->Group::resize(x, y, w, h); + } +} + +int Layout::isClickThrough() +{ + return 0; +} +#ifdef _WIN32 +LRESULT Layout::wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + +#ifdef ON_CUSTOM_ALTF4 + if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN) + if (wParam == VK_F4) + if (GetAsyncKeyState(VK_MENU)&0x8000) ON_CUSTOM_ALTF4; +#endif + + if (uMsg == WM_KILLFOCUS || uMsg == WM_SETFOCUS) + { + alphaMgr->hoverCheck(this); + } + + if (forwardMsgWnd != INVALIDOSWINDOWHANDLE) + { + switch (uMsg) + { + case WM_MOUSEWHEEL: + return (SendMessageW(forwardMsgWnd, uMsg, wParam, 0x31337)); // 0x31337 avoid main window callback + //case WM_DESTROY: //FG> commented out, makes wa quit when layout is destroyed + case WM_CLOSE: + return (SendMessageW(forwardMsgWnd, uMsg, wParam, lParam)); + + case WM_SETTINGCHANGE: + { + if (!indesktop) break; + setTimer(TIMER_SETTINGCHANGED, 1000); + } + break; //BU think this should be here eh + +#ifdef WIN32 + case 0x0319: + { // hehe --BU + if (lParam & 0x20000) + FireAction(L"NEXT", NULL, 0, 0, NULL, 0, NULL, FALSE); + else + FireAction(L"PREV", NULL, 0, 0, NULL, 0, NULL, FALSE); + } + break; +#endif + /* + WIP: This won't work anymore. What should we do about it? -- mig + + childNotify(NULL, CHILD_NOTIFY_LEFTPUSH, ACTION_NEXT); + break; + */ + } + } + return LAYOUT_PARENT::wndProc(hWnd, uMsg, wParam, lParam); +} +#else +OSStatus Layout::eventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + return LAYOUT_PARENT::eventHandler(inHandlerCallRef, inEvent, inUserData); +} +#warning port me +#endif + +/*int Layout::onRightButtonDown(int x, int y) { + LAYOUT_PARENT::onRightButtonDown(x, y); +// Main::appContextMenu(this, TRUE, isTransparencySafe()); + return 1; +}*/ + +ifc_window *Layout::getCustomOwner() +{ + if (noparent) return NULL; + if (owner.isempty()) return NULL; + return SkinParser::getLayout(owner); +} + +void Layout::addLockedLayout(Layout *l) +{ + locked.addItem(l); + updateLockedLayouts(); +} + +void Layout::removeLockedLayout(Layout *l) +{ + locked.removeItem(l); +} + +int Layout::getNumLockedLayouts() +{ + return locked.getNumItems(); +} + +Layout *Layout::enumLockedLayout(int n) +{ + return locked.enumItem(n); +} + +int Layout::isLocked() +{ + return (!lockto.isempty() + #ifdef USEAPPBAR + || cfg_options_appbarondrag == 0 && appbar_isDocked() +#endif + ); +} + +void Layout::lockTo(Layout *t) +{ + if (t == NULL) return ; + if (lockedto) lockedto->removeLockedLayout(this); + lockedto = t; + t->addLockedLayout(this); +} + +Layout *Layout::getLockedTo() +{ + return lockedto; +} + +int Layout::reinit(OSMODULEHANDLE inst, OSWINDOWHANDLE parent, int nochild) +{ + StringW osname = getOSWndName(); + ASSERTPR(!indesktop, "in desktop reinit failed"); + if (noparent) + parent = NULL; + int r = LAYOUT_PARENT::reinit(inst, parent, nochild); + setOSWndName(osname); + return r; +} + +int Layout::init(OSMODULEHANDLE inst, OSWINDOWHANDLE parent, int nochild) +{ + if (noparent) parent = NULL; + if (!indesktop) return LAYOUT_PARENT::init(inst, parent, nochild); + +#ifdef _WIN32 + webserver = INVALIDOSWINDOWHANDLE; + listview = INVALIDOSWINDOWHANDLE; + + getExplorerWindows(&parent, &listview, &webserver); + + if (!parent) + { + indesktop = 0; + return LAYOUT_PARENT::init(inst, parent, nochild); + } +#endif + nochild = 0; + +#ifdef _WIN32 + // if active desktop is off, that's all we can do, we'll be on top of the icons + // if active desktop is on, but listview is not, we'll be on top of active desktop + if (!webserver || !listview) return LAYOUT_PARENT::init(inst, parent, nochild); +#endif + +#ifdef WIN32 + // find who we're gonna sit on top of + HWND behind = listview; + if (GetWindow(listview, GW_HWNDPREV)) + behind = GetWindow(listview, GW_HWNDPREV); +#else + DebugString( "portme -- Layout::init\n" ); +#endif + + int r = LAYOUT_PARENT::init(inst, parent, nochild); +#ifdef WIN32 + SetWindowPos(gethWnd(), behind, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE); +#endif + + return r; +} + +#ifdef WIN32 +void Layout::getExplorerWindows(OSWINDOWHANDLE *parent, OSWINDOWHANDLE *listview, OSWINDOWHANDLE *webserver) +{ + *parent = NULL; + *listview = NULL; + *webserver = NULL; + + char classname[256] = ""; + HWND w; + + // find explorer window. todo: litestep support ? + *parent = FindWindowA(NULL, "Program Manager"); + if (!*parent) return ; + + // find its first child for parenting + *parent = GetWindow(*parent, GW_CHILD); + if (!*parent) return ; + + // find the children + w = GetWindow(*parent, GW_CHILD); + + while (w) + { + GetClassNameA(w, classname, 255); + if (!*webserver && STRCASEEQL("Internet Explorer_Server", classname)) + *webserver = w; + if (!*listview && STRCASEEQL("SysListView32", classname)) + *listview = w; + w = GetWindow(w, GW_HWNDNEXT); + } +} +#endif + +int Layout::onInit() +{ + LAYOUT_PARENT::onInit(); + + Container *c = getParentContainer(); + if (c != NULL) + { + const wchar_t *s = c->getName(); + if (s != NULL) + { + setOSWndName(s); + } + } + + loadSavedState(); + +#ifdef WA3COMPATIBILITY + setIcon(WASABI_API_APP->main_getIcon(TRUE), TRUE); + setIcon(WASABI_API_APP->main_getIcon(FALSE), FALSE); +#endif + + WASABI_API_WNDMGR->wndTrackAdd(this); + + if (wantDesktopAlpha() && isDesktopAlphaSafe()) + desktopAlpha_autoTurnOn(); + + if (getBaseTexture()) + { + //RECT r = {0, 0, getBaseTexture()->getWidth(), getBaseTexture()->getHeight()}; + delete reg; +#ifdef _WIN32 + reg = new RegionI(getBaseTexture(), NULL, 0, 0, 0, 0, 0, 0, getDesktopAlpha() ? 1 : 255); + setRegion(reg); +#else +#warning port me +#endif + } + + SystemObject::onCreateLayout(this); + + if (!lockto.isempty()) lockTo(SkinParser::getLayout(lockto)); + + updateOnTop(); + + setNoOffscreenCheck( -1); + + return 1; +} + +void Layout::updateOnTop() +{ + #ifdef USEAPPBAR + if (!appbar_isDocked()) +#endif + { +#ifdef EXPERIMENTAL_INDEPENDENT_AOT + setAlwaysOnTop(initontop); +#else + if (noparent) + { + int disable = 0; +#ifdef WASABI_GET_TEMPDISABLE_AOT + WASABI_GET_TEMPDISABLE_AOT(disable); +#endif +#ifdef _WIN32 + if (initontop && !disable) SetWindowPos(getOsWindowHandle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE); + else SetWindowPos(getOsWindowHandle(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE); +#else +#warning port me +#endif + } +#endif + + } +} + +void Layout::loadSavedState() +{ +#ifdef WASABI_COMPILE_CONFIG + StringW tmp; +#endif + wchar_t t[64] = L""; + + int ow = -1; + int oh = -1; + int ra = -1; + +#ifdef WASABI_COMPILE_CONFIG + if (getParentContainer() && !getParentContainer()->isTranscient()) + { + StringW prefix = MakePrefix(); + tmp.printf(L"%s/odim", prefix.v()); + IntArray::read(tmp, &ow, &oh); + + tmp.printf(L"%s/alpha", prefix.v()); + IntArray::read(tmp, &ra); + + tmp.printf(L"%s/autoopacify", prefix.v()); + IntArray::read(tmp, &autoopacify); + + } +#endif + + int from_scratch = 0; + if (Std::keyModifier(STDKEY_SHIFT) && Std::keyModifier(STDKEY_ALT) && Std::keyModifier(STDKEY_CONTROL)) from_scratch = 1; +#ifdef WASABI_COMPILE_CONFIG + if (getParentContainer() && !getParentContainer()->isTranscient()) + { + StringW prefix = MakePrefix(); + tmp.printf(L"%s/sl", prefix.v()); + WASABI_API_CONFIG->getStringPrivate(tmp, t, 63, L"0"); + lockScale(WTOI(t)); + } +#endif + + *t = 0; +#ifdef WASABI_COMPILE_CONFIG + if (getParentContainer() && !getParentContainer()->isTranscient()) + { + StringW prefix = MakePrefix(); + tmp.printf(L"%s/sm", prefix.v()); + } + + WASABI_API_CONFIG->getStringPrivate(tmp, t, 63, L"1."); + //double sm = (float)WTOF(t); +#else + //double sm = 1.0; +#endif + /*if (ABS(sm - Canvas::getSystemFontScale()) > 0.001) + from_scratch = 1;*/ + + if (Group::getBaseTexture() && alphabackground.getBitmap() != NULL) + { + if (Group::getBaseTexture()->getWidth() != alphabackground.getWidth() || Group::getBaseTexture()->getHeight() != alphabackground.getHeight()) + { + ASSERTPR(0, StringPrintf("layout %S should have same size for background and alphabackground", getGuiObject()->guiobject_getParentLayout()->getGuiObject()->guiobject_getId())); + } + } + + if ((ow != -2 && oh != -2) && (ow == -1 || oh == -1 || (getBaseTexture() && (ow != getBaseTexture()->getWidth() || oh != getBaseTexture()->getHeight())))) + from_scratch = 1; + + int w = 0, h = 0; + int findrect = 0; + + if (from_scratch || (getParentContainer() && getParentContainer()->isTranscient())) + { + if (getParentContainer()) + { + int _x = getParentContainer()->getDefaultPositionX(); + int _y = getParentContainer()->getDefaultPositionY(); + x = _x == -1 ? x : _x; + y = _y == -1 ? y : _y; + if (x == -1 && y == -1) findrect = 1; + } + else + { + int _x, _y; + getGuiObject()->guiobject_getGuiPosition(&_x, &_y, NULL, NULL, NULL, NULL, NULL, NULL); + if (_x != AUTOWH && _x != NOCHANGE) x = _x; + if (_y != AUTOWH && _y != NOCHANGE) y = _y; + } + getGuiObject()->guiobject_getGuiPosition(NULL, NULL, &w, &h, NULL, NULL, NULL, NULL); + if (w == AUTOWH || h == AUTOWH) + { + w = getPreferences(SUGGESTED_W); + h = getPreferences(SUGGESTED_H); + int _minx = getPreferences(MINIMUM_W); + int _maxx = getPreferences(MAXIMUM_W); + int _miny = getPreferences(MINIMUM_H); + int _maxy = getPreferences(MAXIMUM_H); + if (_minx != AUTOWH && _maxx != AUTOWH && _minx > _maxx) _minx = _maxx; + if (_miny != AUTOWH && _maxy != AUTOWH && _miny > _maxy) _miny = _maxy; + if (w == AUTOWH && _minx != AUTOWH) w = _minx; + if (h == AUTOWH && _miny != AUTOWH) h = _miny; + TextInfoCanvas textInfoCanvas(this); + double fontScale = textInfoCanvas.getSystemFontScale(); + if (w != AUTOWH && getGuiObject()->guiobject_getAutoSysMetricsW()) + w = (int)((float)w * fontScale); + if (h != AUTOWH && getGuiObject()->guiobject_getAutoSysMetricsH()) + h = (int)((float)h * fontScale); + } + } + else + { + if (getParentContainer()) + { + + if (getParentContainer()->isMainContainer()) //FG> could be a new component installed + SkinParser::noCenterSkin(); + +#ifdef WASABI_COMPILE_CONFIG + StringW prefix = MakePrefix(); + + tmp.printf(L"%s/rect", prefix.v()); + IntArray::read(tmp, &x, &y, &w, &h); + + RECT rr; + tmp.printf(L"%s/restoredrect", prefix.v()); + IntArray::read(tmp, (int*)&rr.left, (int*)&rr.top, (int*)&rr.right, (int*)&rr.bottom); + rr.right += rr.left; + rr.bottom += rr.top; + + tmp.printf(L"%s/maximized", prefix.v()); + if (WASABI_API_CONFIG->getIntPrivate(tmp, 0)) setRestoredRect(&rr); + +#endif + + } + } + + *t = 0; + double ratio = 1.0; + + if (!from_scratch) + { + if (getParentContainer()) + { +#ifdef WASABI_COMPILE_CONFIG + StringW prefix = MakePrefix(); + tmp.printf(L"%s/r", prefix.v()); + + WASABI_API_CONFIG->getStringPrivate(tmp, t, 63, L"1."); + ratio = WTOF(t); +#else + ratio = 1.0f; +#endif + + } + } + +#ifdef ON_TWEAK_RENDER_RATIO + if (!scalelocked) ON_TWEAK_RENDER_RATIO(ratio); +#endif + + if (w == 0 || h == 0 || from_scratch) + { + int _w = getPreferences(SUGGESTED_W); + w = _w == AUTOWH ? w : _w; + int _h = getPreferences(SUGGESTED_H); + h = _h == AUTOWH ? h : _h; + + TextInfoCanvas textInfoCanvas(this); + double fontScale = textInfoCanvas.getSystemFontScale(); + + if (getGuiObject()->guiobject_getAutoSysMetricsW()) + w = (int)((float)w * fontScale); + if (getGuiObject()->guiobject_getAutoSysMetricsH()) + h = (int)((float)h * fontScale); + if (w == 0 || h == 0) + { + w = getBaseTexture()->getWidth(); + h = getBaseTexture()->getHeight(); + } + RECT sr = {x, y, x + w, y + h}; + if (findrect) + sr = windowTracker->findOpenRect(Wasabi::Std::makeRect(0, 0, (int)((float)w * getRenderRatio()), (int)((float)h * getRenderRatio())), this); + sr.right = sr.left + w; + sr.bottom = sr.top + h; + BaseWnd::resize(&sr); + } + else + { + RECT cr; + getClientRect(&cr); + RECT r = {x, y, x + w, y + h}; + BaseWnd::resize(&r); + } + + setAlpha(from_scratch || ra == -1 ? alpha : ((ra < 254) ? ra : 255)); + + Layout *main = SkinParser::getMainLayout(); + if (main != this && main + #ifdef WASABI_COMPILE_CONFIG + && cfg_uioptions_linkallratio.getValueAsInt() +#endif + && !noparent) + { + setRenderRatio(main->getRenderRatio()); + } + else setRenderRatio(ratio); + + setAutoOpacify(autoopacify); + +#ifdef USEAPPBAR + postDeferredCallback(DC_LOADSAVEDDOCK); + + if (getParentContainer() && !getParentContainer()->isTranscient()) + { + StringW prefix = MakePrefix(); + StringW tmp = StringPrintfW(L"%s/appbar", prefix.v()); + int side = WASABI_API_CONFIG->getIntPrivate(tmp, APPBAR_NOTDOCKED); + tmp.printf(L"%s/appbarisautohide", prefix.v()); + int is_autohide = WASABI_API_CONFIG->getIntPrivate(tmp, 0); + tmp.printf(L"%s/appbarwantautohide", prefix.v()); + appbar_want_autohide = is_autohide || WASABI_API_CONFIG->getIntPrivate(tmp, 1); + tmp.printf(L"%s/appbarontop", prefix.v()); + appbar_want_alwaysontop = WASABI_API_CONFIG->getIntPrivate(tmp, 1); + tmp.printf(L"%s/appbarhidden",prefix.v()); + int curside = appbar_getSide(); + if (side != curside) + { + if (side == APPBAR_NOTDOCKED) + // starting up docked ?? + appbar_dock(side); + else + { + setNoParent(2); + BaseWnd::reinit(); + appbar_dock(side); + } + } + } + m_allowsavedock = 1; + +#endif +} + +void Layout::setBaseTexture(const wchar_t *b, int regis) +{ + LAYOUT_PARENT::setBaseTexture(b, 0); // 0, not regis! + if (!getDesktopAlpha() || ((wantDesktopAlpha()) && alphabackground.getBitmap() == NULL)) + { + if (regis) WASABI_API_WND->skin_unregisterBaseTextureWindow(this); + if (getBaseTexture()) + { + //RECT r = {0, 0, getBaseTexture()->getWidth(), getBaseTexture()->getHeight()}; + delete reg; +#ifdef _WIN32 + reg = new RegionI(getBaseTexture(), NULL, 0, 0, 0, 0, 0, 0, getDesktopAlpha() ? 1 : 255); + setRegion(reg); +#else +#warning port me +#endif + } + if (regis) + WASABI_API_WND->skin_registerBaseTextureWindow(this, getBackgroundStr()); + } +} + +void Layout::setWantDesktopAlpha(int want) +{ + if (want && !Wasabi::Std::Wnd::isDesktopAlphaAvailable()) + { + // WASABI_API_WNDMGR->messageBox("Desktop Alpha Blending is only available for Win2000/WinXP and above", "Sorry", MSGBOX_OK, NULL, NULL); + return ; + } + wantdesktopalpha = want; + if (wantdesktopalpha && isInited() && isDesktopAlphaSafe()) + desktopAlpha_autoTurnOn(); + else if (!wantdesktopalpha && getDesktopAlpha()) + desktopAlpha_autoTurnOff(); +} + +int Layout::wantDesktopAlpha() +{ + return wantdesktopalpha; +} + +int Layout::handleDesktopAlpha() +{ + return 1; +} + +void Layout::onGuiObjectSetVisible(GuiObject *o, int visible) +{ + if (disable_auto_alpha) return ; + if (!o || !o->guiobject_getRootWnd()) return ; + if (visible) + { + if (getDesktopAlpha()) + { + if (!o->guiobject_getRootWnd()->handleDesktopAlpha()) + { + desktopAlpha_autoTurnOff(); + } + } + if (!transparency_autooff) + { + if (!o->guiobject_getRootWnd()->handleTransparency()) + { + transparency_autoTurnOff(); + } + } + } + else + { // !visible + if (!getDesktopAlpha() && wantDesktopAlpha()) + { + if (isDesktopAlphaSafe()) + desktopAlpha_autoTurnOn(); + } + if (transparency_autooff) + { + if (isTransparencySafe(1)) + transparency_autoTurnOn(); + } + } +} + +void Layout::desktopAlpha_autoTurnOn() +{ + + setDesktopAlpha(1); + + WASABI_API_WND->skin_unregisterBaseTextureWindow(this); + + if (getBaseTexture()) + { + //RECT r = {0, 0, getBaseTexture()->getWidth(), getBaseTexture()->getHeight()}; + delete reg; +#ifdef _WIN32 + reg = new RegionI(getBaseTexture(), NULL, 0, 0, 0, 0, 0, 0, 1); + setRegion(reg); +#else +#warning port me +#endif + } + + WASABI_API_WND->skin_registerBaseTextureWindow(this, alphabackground.getBitmap() ? alphabackgroundstr.getValue() : getBackgroundStr()); + + invalidate(); +} + +void Layout::desktopAlpha_autoTurnOff() +{ +#ifdef WIN32 + SetWindowRedraw(gethWnd(), FALSE);//LockWindowUpdate(gethWnd()); + setDesktopAlpha(0); + + WASABI_API_WND->skin_unregisterBaseTextureWindow(this); + + if (getBaseTexture()) + { + //RECT r = {0, 0, getBaseTexture()->getWidth(), getBaseTexture()->getHeight()}; + delete reg; + reg = new RegionI(getBaseTexture(), NULL, 0, 0, 0, 0, 0, 0, 255); + setRegion(reg); + } + + WASABI_API_WND->skin_registerBaseTextureWindow(this, getBackgroundStr()); + SetWindowRedraw(gethWnd(), TRUE);//LockWindowUpdate(NULL); + + invalidate(); +#else + DebugString( "portme -- Layout::init\n" ); +#endif +} + +void Layout::transparency_autoTurnOn() +{ + transparency_reenabled_at = Wasabi::Std::getTickCount(); + setTimer(TIMER_TRANSPARENCY_AUTOON, 500); +} + +void Layout::transparency_autoTurnOff() +{ + transparency_autooff = 1; + killTimer(TIMER_TRANSPARENCY_AUTOON); + updateTransparency(); +} + +void Layout::onGlobalEnableDesktopAlpha(int enabled) +{ + foreach(alllayouts) + alllayouts.getfor()->globalEnableDesktopAlpha(enabled); + endfor +#ifdef ON_TOGGLE_DESKTOPALPHA + ON_TOGGLE_DESKTOPALPHA(enabled); +#endif +} + +void Layout::globalEnableDesktopAlpha(int enabled) +{ + if (enabled) + { + galphadisabled = 0; + setWantDesktopAlpha(wantdesktopalpha); + } + else + { + galphadisabled = 1; + if (getDesktopAlpha()) + desktopAlpha_autoTurnOff(); + } +} + +void Layout::setWantRedrawOnResize(int v) +{ + if (wantredrawonresize == v) return ; + wantredrawonresize = v; +} + +PtrList<Layout> Layout::alllayouts; + +int Layout::onPaint(Canvas *canvas) +{ + PaintCanvas paintcanvas; + if (canvas == NULL) + { + if (!paintcanvas.beginPaint(this)) return 0; + canvas = &paintcanvas; + } + + RECT r; + + if (!canvas->getClipBox(&r)) + getClientRect(&r); + + canvas->fillRect(&r, 0); + + LAYOUT_PARENT::onPaint(canvas); + + return 1; +} + +/*WndHolder *Layout::getHolder() { + return this; +}*/ + +SkinBitmap *Layout::getBaseTexture() +{ +#ifdef WASABI_COMPILE_CONFIG + // {9149C445-3C30-4e04-8433-5A518ED0FDDE} + const GUID uioptions_guid = + { 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } }; + int alphaenabled = _intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), L"Enable desktop alpha"); +#else + int alphaenabled = WASABI_WNDMGR_DESKTOPALPHA; +#endif + if (!alphabackground.getBitmap() || !getDesktopAlpha() || !alphaenabled) return LAYOUT_PARENT::getBaseTexture(); + return alphabackground.getBitmap(); +} + +int Layout::runAction(int actionid, const wchar_t *param) +{ + switch (actionid) + { + case ACTION_SWITCH: + if (getParentContainer()) + { + getParentContainer()->switchToLayout(param); + } + break; + case ACTION_TOGGLE: + SkinParser::toggleContainer(param); + break; +#ifdef WA3COMPATIBILITY + case ACTION_MENU: + Main::doMenu(param); + break; +#endif + case ACTION_ENDMODAL: + endModal(WTOI(param)); + break; + case ACTION_CLOSE: + onActionNotify(ACTION_CLOSE); + break; +#ifdef WA3COMPATIBILITY + default: + if (actionid != 0) + Main::doAction(actionid); + break; +#else + case ACTION_MINIMIZE: +#ifdef _WIN32 + ShowWindow(WASABI_API_WND->main_getRootWnd()->gethWnd(), SW_MINIMIZE); +#endif + break; +#endif + + } + return 0; +} + +int Layout::childNotify(ifc_window *child, int msg, intptr_t param1, intptr_t param2) +{ + if (msg == ACTION_ENFORCEMINMAX) + { + loadSavedState(); + return 0; + } + if (child != NULL) + { + int objId = child->getNotifyId(); + if (msg == ChildNotify::BUTTON_LEFTPUSH) + { + switch (objId) + { + case ACTION_SWITCH: + case ACTION_TOGGLE: + case ACTION_MENU: + runAction(objId, ((Wasabi::Button *)child)->getParam()); + break; + case ACTION_ENDMODAL: + { + StringPrintfW s(L"%d", (static_cast<ButtonWnd *>(child))->getModalRetCode()); + runAction(ACTION_ENDMODAL, s); + } + break; + case ACTION_CLOSE: + runAction(ACTION_CLOSE); + break; + /* + #ifdef WA3COMPATIBILITY + case ACTION_EJECT: + runAction(ACTION_EJECT, "0"); + break; + #endif + */ + default: + runAction(objId); + break; + } + return 0; + } + if (msg == ChildNotify::BUTTON_RIGHTPUSH) + { + //FUCKO child->abortTip(); + // POINT pt; + // Std::getMousePos(&pt); + // screenToClient(&pt); + // onRightButtonDown(pt.x, pt.y); +#pragma warning (disable: 4060) + switch (objId) + { + /* + #ifdef WA3COMPATIBILITY + case ACTION_EJECT: { + runAction(ACTION_EJECT, "1"); + } + break; + #endif + */ + } +#pragma warning (default: 4060) + return 0; + } + } + return LAYOUT_PARENT::childNotify(child, msg, param1, param2); +} + +int Layout::onActionNotify(int action, intptr_t param) +{ + switch (action) + { +#ifdef WA3COMPATIBILITY + case ACTION_SYSMENU: + Main::appContextMenu(this, TRUE, isDesktopAlphaSafe()); + break; + case ACTION_CONTROLMENU: + controlMenu(); + break; + case ACTION_WINDOWMENU: + Main::thingerContextMenu(this); + break; +#elif defined(WASABI_CUSTOM_CONTEXTMENUS) + case ACTION_SYSMENU: + extern void appContextMenu(ifc_window *w); + appContextMenu(this); + break; + case ACTION_CONTROLMENU: + extern void appControlMenu(ifc_window *w); + appControlMenu(this); + break; +#endif + case ACTION_SCALE_50: scaleTo(50); break; + case ACTION_SCALE_75: scaleTo(75); break; + case ACTION_SCALE_100: scaleTo(100); break; + case ACTION_SCALE_125: scaleTo(125); break; + case ACTION_SCALE_150: scaleTo(150); break; + case ACTION_SCALE_200: scaleTo(200); break; + case ACTION_SCALE_400: scaleTo(400); break; + case ACTION_ALPHA_10: setAlpha(25); break; + case ACTION_ALPHA_20: setAlpha(51); break; + case ACTION_ALPHA_30: setAlpha(76); break; + case ACTION_ALPHA_40: setAlpha(102); break; + case ACTION_ALPHA_50: setAlpha(127); break; + case ACTION_ALPHA_60: setAlpha(153); break; + case ACTION_ALPHA_70: setAlpha(178); break; + case ACTION_ALPHA_80: setAlpha(204); break; + case ACTION_ALPHA_90: setAlpha(229); break; + case ACTION_ALPHA_100: setAlpha(255); break; + case ACTION_AUTOOPACIFY: setAutoOpacify(!getAutoOpacify()); break; +#ifdef EXPERIMENTAL_INDEPENDENT_AOT + case ACTION_AOT: setAlwaysOnTop(!getAlwaysOnTop()); break; +#endif + case ACTION_CLOSE_WINDOW: + case ACTION_CLOSE: + if (getParentContainer() && getParentContainer()->isMainContainer()) + { + int x = 1; +#ifdef WASABI_CHECK_CAN_EXIT + WASABI_CHECK_CAN_EXIT(x) +#endif + if (x) + { + WASABI_API_APP->main_shutdown(); + } + } + else if (WASABI_API_WNDMGR->getModalWnd() != this) + { + if (!getParentContainer() || !getParentContainer()->isDynamic() || !getParentContainer()->canClose()) + if (getParentContainer()) getParentContainer()->setVisible(FALSE); else setVisible(FALSE); + else + skinEmbedder->destroyContainer(getParentContainer()); + } + else + { + endModal(MSGBOX_ABORTED); + } + break; + default: return 0; + } + return 1; +} + +void Layout::containerToggled(const wchar_t *id, int visible) +{ + #ifdef _WIN32 + sendNotifyToAllChildren(WM_WA_CONTAINER_TOGGLED, (intptr_t)id, visible); +#else +#warning port me +#endif +} + +void Layout::componentToggled(GUID *guid, int visible) +{ +#ifdef _WIN32 + sendNotifyToAllChildren(WM_WA_COMPONENT_TOGGLED, (intptr_t)guid, visible); +#else +#warning port me +#endif +} + +void Layout::setAlphaBackground(const wchar_t *b) +{ + alphabackgroundstr = b; + alphabackground.setBitmap(b); +#ifdef _WIN32 + RegionI r(alphabackground.getBitmap()); + setRegion(&r); +#else +#warning port me +#endif +} + +/*void Layout::setWindowRegion(api_region *reg) { + LAYOUT_PARENT::setWindowRegion(reg); + if (getDesktopAlpha()) { + SetWindowRgn(gethWnd(), NULL, FALSE); + return; + } + if (!isInited()) return; + api_region *_r = getRegion(); + if (getRenderRatio() != 1.0 && reg) { + api_region *clone = _r->clone(); + clone->scale(getRenderRatio()); + SetWindowRgn(gethWnd(), clone->makeWindowRegion(), TRUE); + _r->disposeClone(clone); + } else { + SetWindowRgn(gethWnd(), _r ? _r->makeWindowRegion() : NULL, TRUE); + } +}*/ + +void Layout::onSetDesktopAlpha(int a) +{ + invalidateWindowRegion(); +} + +void Layout::onShow(void) +{ + savePosition(); + if (!WASABI_API_MAKI->vcpu_getComplete()) SystemObject::onShowLayout(this); +} + +void Layout::onHide(void) +{ + savePosition(); + if (!WASABI_API_MAKI->vcpu_getComplete()) SystemObject::onHideLayout(this); +#ifndef WASABINOMAINAPI + api->hintGarbageCollect(); +#else + WASABI_API_SYSCB->syscb_issueCallback(SysCallback::GC, GarbageCollectCallback::GARBAGECOLLECT); +#endif + if (getParentContainer() && getParentContainer()->wantRefocusApp()) SkinParser::focusFirst(); +} + +#ifdef _WIN32 +LPARAM Layout::wndHolder_getParentParam(int i) +{ + switch (i) + { + case 0: return (LPARAM)gethWnd(); + case 1: return (LPARAM)static_cast<BaseWnd*>(this); + } + return 0; +} +#endif + +void Layout::onSetVisible( int show ) +{ + disable_auto_alpha = 1; + LAYOUT_PARENT::onSetVisible( show ); + + if ( show ) + onShow(); + else + onHide(); + + Container *p = getParentContainer(); + + if ( p ) + p->onChildSetLayoutVisible( this, show ); + + disable_auto_alpha = 0; + + if ( wantDesktopAlpha() && isDesktopAlphaSafe() ) + desktopAlpha_autoTurnOn(); +} + +void Layout::scaleTo(int s) +{ + beginScale(); + setRenderRatio((double)s / 100.0); + endScale(); +} + +void Layout::setRenderRatio(double s) +{ + if (isPostOnInit() + #ifdef WASABI_COMPILE_CONFIG + && cfg_uioptions_linkallratio.getValueAsInt() == 1 +#endif + && !broadcasting) + { + broadcasting = 1; + SkinParser::setAllLayoutsRatio(s); + broadcasting = 0; + return ; + } + if (getRenderRatio() == s) return ; + LAYOUT_PARENT::setRenderRatio(s); + if (reg) invalidateWindowRegion(); + invalidate(); + foreach(locked) + locked.getfor()->setRenderRatio(s); + endfor; + if (lockedto && lockedto->getRenderRatio() != getRenderRatio()) + lockedto->setRenderRatio(getRenderRatio()); + script_vcpu_onScale(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_DOUBLE(s)); + if (!abortSaving()) savePosition(); +} + +void Layout::setAlpha(int a) +{ + int old = alpha; + alpha = a; + updateTransparency(); +#ifdef WASABI_COMPILE_CONFIG + if (old != alpha && getParentContainer()) + { + StringPrintfW tmp(L"Skin:%s/Container:%s/Layout:%s/alpha", WASABI_API_SKIN->getSkinName(), getParentContainer()->getDescriptor(), getGuiObject()->guiobject_getId()); + IntArray::write(tmp, alpha); + } +#endif +} + +int Layout::getAlpha() +{ + return alpha; +} + +void Layout::setPaintingAlpha(int activealpha, int inactivealpha) +{ // from basewnd, called by gui object + LAYOUT_PARENT::setAlpha(activealpha, inactivealpha); + updateTransparency(); +} + +int Layout::getPaintingAlpha() +{ // from basewnd, called by gui object + return getAlpha(); +} + +int Layout::onActivate() +{ + LAYOUT_PARENT::onActivate(); + // activateChildren(1); + updateTransparency(); + return 1; +} + +int Layout::onKillFocus() +{ + alphaMgr->hoverCheck(this); + int r = LAYOUT_PARENT::onKillFocus(); + return r; +} + +int Layout::onGetFocus() +{ + alphaMgr->hoverCheck(this); + int r = LAYOUT_PARENT::onGetFocus(); + return r; +} + +int Layout::onDeactivate() +{ + LAYOUT_PARENT::onDeactivate(); + // activateChildren(0); + updateTransparency(); + return 1; +} + +void Layout::updateTransparency() +{ + alphaMgr->updateTransparency(this); +} + +/* +void Layout::activateChildren(int act) { + for (int i=0;i<gui_objects.getNumItems();i++) { + GuiObject *o = gui_objects.enumItem(i); + BaseWnd *b = NULL; + if (o) + b = o->getBaseWnd(); + else + ASSERT(0); + if (b) { + if (act) + b->onActivate(); + else + b->onDeactivate(); + } + } +}*/ + +void Layout::center() +{ + RECT r; + getNonClientRect(&r); + RECT vw; + Wasabi::Std::getViewport(&vw, NULL, NULL, gethWnd()); + int x = ((vw.right - vw.left) - (r.right - r.left)) / 2; + int y = ((vw.bottom - vw.top) - (r.bottom - r.top)) / 2; + move(x, y); +} + +void Layout::setParentContainer(Container *c) +{ + p_container = c; +} + +Container *Layout::getParentContainer() +{ + return p_container; +} + +int Layout::isLayout() +{ + return 1; +} + +void Layout::setInDesktop(int a) +{ + ASSERTPR(!isInited(), "cannot change indesktop after init"); + indesktop = a; +} + +int Layout::getInDesktop() +{ + return indesktop; +} + +int Layout::isDesktopAlphaSafe() +{ +#ifdef WASABI_COMPILE_CONFIG + if (galphadisabled) return 0; + // {9149C445-3C30-4e04-8433-5A518ED0FDDE} + const GUID uioptions_guid = + { 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } }; + if (!_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid), L"Enable desktop alpha")) return 0; +#else + if (!WASABI_WNDMGR_DESKTOPALPHA) return 0; +#endif + return LAYOUT_PARENT::isDesktopAlphaSafe(); +} + +void Layout::setStatusText(const wchar_t *txt, int overlay) +{ + foreach(statuscbs) + statuscbs.getfor()->onSetStatusText(txt, overlay); + endfor; +} + +void Layout::addAppCmds(AppCmds *commands) +{ + foreach(statuscbs) + statuscbs.getfor()->onAddAppCmds(commands); + endfor; +} + +void Layout::removeAppCmds(AppCmds *commands) +{ + foreach(statuscbs) + statuscbs.getfor()->onRemoveAppCmds(commands); + endfor; +} + +void Layout::pushCompleted(int max) +{ + foreach(statuscbs) + statuscbs.getfor()->pushCompleted(max); + endfor; +} +void Layout::incCompleted(int add) +{ + foreach(statuscbs) + statuscbs.getfor()->incCompleted(add); + endfor; +} +void Layout::setCompleted(int pos) +{ + foreach(statuscbs) + statuscbs.getfor()->setCompleted(pos); + endfor; +} +void Layout::popCompleted() +{ + foreach(statuscbs) + statuscbs.getfor()->popCompleted(); + endfor; +} + +void Layout::registerStatusCallback(GuiStatusCallback *lcb) +{ + statuscbs.addItem(lcb); + viewer_addViewItem(lcb->status_getDependencyPtr()); +} + +int Layout::viewer_onItemDeleted(api_dependent *item) +{ + for (int i = 0;i < statuscbs.getNumItems();i++) + if (statuscbs.enumItem(i)->status_getDependencyPtr() == item) + { + statuscbs.removeByPos(i--); + } + return 1; +} + +void Layout::snapAdjust(int left, int right, int top, int bottom) +{ + snap_adjust_left = left; + snap_adjust_top = top; + snap_adjust_right = right; + snap_adjust_bottom = bottom; + script_vcpu_onSnapAdjustChanged(SCRIPT_CALL, getScriptObject()); + #ifdef USEAPPBAR + if (appbar_isDocked()) appbar_posChanged(); +#endif + if (forceTransparencyFlag() || getAlpha() < 255) postDeferredCallback(DC_INVALIDATE); +} + +void Layout::getSnapAdjust(RECT *r) +{ + if (!r) return ; + r->left = snap_adjust_left; + r->top = snap_adjust_top; + r->right = snap_adjust_right; + r->bottom = snap_adjust_bottom; +} + +int Layout::abortSaving() +{ + GuiObject *o = getGuiObject(); + if (o->guiobject_movingToTarget()) return 1; + return 0; +} + +void Layout::setNoOffscreenCheck(int nocheck) +{ + killTimer(TIMER_OFFSCREENCHECK); + + if (nocheck != -1) nooffscreencheck = nocheck; + + setTimer(TIMER_OFFSCREENCHECK, 2500); +} + +#ifdef USEAPPBAR + +void Layout::onDock(int side) +{ + script_vcpu_onDock(SCRIPT_CALL, getScriptObject(), MAKE_SCRIPT_INT(side)); +} + +void Layout::onUnDock() +{ + script_vcpu_onUndock(SCRIPT_CALL, getScriptObject()); +} + +void Layout::appbar_onDock(int side) +{ + onDock(side); + savePosition(); +} + +void Layout::appbar_onUnDock() +{ + onUnDock(); + savePosition(); +} + +void Layout::appbar_onSlide() +{ + savePosition(); +} + +int Layout::getAppBarAutoHide() +{ + return appbar_want_autohide; +} + +void Layout::setAppBarAutoHide(int ah) +{ + appbar_want_autohide = ah; + if (appbar_isDocked()) appbar_updateAutoHide(); + savePosition(); +} + +int Layout::getAppBarAlwaysOnTop() +{ + return appbar_want_alwaysontop; +} + +void Layout::setAppBarAlwaysOnTop(int aot) +{ + appbar_want_alwaysontop = aot; + if (appbar_isDocked()) appbar_updateAlwaysOnTop(); + savePosition(); +} +#endif + + +// ------------------------------------------------------------------------ + +LayoutScriptController _layoutController; +LayoutScriptController *layoutController = &_layoutController; + +// -- Functions table ------------------------------------- +function_descriptor_struct LayoutScriptController::exportedFunction[] = { + {L"onDock", 1, (void*)Layout::script_vcpu_onDock }, + {L"onUndock", 0, (void*)Layout::script_vcpu_onUndock }, + {L"getScale", 0, (void*)Layout::script_vcpu_getScale }, + {L"setScale", 1, (void*)Layout::script_vcpu_setScale }, + {L"onScale", 1, (void*)Layout::script_vcpu_onScale }, + {L"setDesktopAlpha", 1, (void*)Layout::script_vcpu_setDesktopAlpha }, + {L"getDesktopAlpha", 0, (void*)Layout::script_vcpu_getDesktopAlpha }, + {L"isTransparencySafe", 0, (void*)Layout::script_vcpu_isTransparencySafe}, + {L"isLayoutAnimationSafe", 0, (void*)Layout::script_vcpu_isLayoutAnimationSafe}, + {L"getContainer", 0, (void*)Layout::script_vcpu_getContainer }, + {L"center", 0, (void*)Layout::script_vcpu_center}, + {L"onMove", 0, (void*)Layout::script_vcpu_onMove}, + {L"onEndMove", 0, (void*)Layout::script_vcpu_onEndMove}, + {L"snapAdjust", 4, (void*)Layout::script_vcpu_snapAdjust}, + {L"getSnapAdjustTop", 0, (void*)Layout::script_vcpu_getSnapAdjustTop}, + {L"getSnapAdjustLeft", 0, (void*)Layout::script_vcpu_getSnapAdjustLeft}, + {L"getSnapAdjustRight", 0, (void*)Layout::script_vcpu_getSnapAdjustRight}, + {L"getSnapAdjustBottom", 0, (void*)Layout::script_vcpu_getSnapAdjustBottom}, + {L"onUserResize", 4, (void*)Layout::script_vcpu_onUserResize}, + {L"setRedrawOnResize", 1, (void*)Layout::script_vcpu_setRedrawOnResize}, + {L"beforeRedock", 0, (void*)Layout::script_vcpu_beforeRedock}, + {L"redock", 0, (void*)Layout::script_vcpu_redock}, + {L"onMouseEnterLayout", 0, (void*)Layout::script_vcpu_onMouseEnterLayout}, + {L"onMouseLeaveLayout", 0, (void*)Layout::script_vcpu_onMouseLeaveLayout}, + {L"onSnapAdjustChanged", 0, (void*)Layout::script_vcpu_onSnapAdjustChanged}, + }; +// -------------------------------------------------------- + + +const wchar_t *LayoutScriptController::getClassName() +{ + return L"Layout"; +} + +const wchar_t *LayoutScriptController::getAncestorClassName() +{ + return L"Group"; +} + +int LayoutScriptController::getInstantiable() +{ + return 1; +} + +ScriptObject *LayoutScriptController::instantiate() +{ + Layout *l = new Layout; + return l->getScriptObject(); +} + +void LayoutScriptController::destroy(ScriptObject *o) +{ + Group *g = static_cast<Group *>(o->vcpu_getInterface(groupGuid)); + if (g && GroupMgr::hasGroup(g)) + { + GroupMgr::destroy(g); + return ; + } + ASSERTALWAYS("you cannot destroy a static layout"); +} + +void *LayoutScriptController::encapsulate(ScriptObject *o) +{ + return NULL; +} + +void LayoutScriptController::deencapsulate(void *o) +{} + +int LayoutScriptController::getNumFunctions() +{ + return sizeof(exportedFunction) / sizeof(function_descriptor_struct); +} + +const function_descriptor_struct *LayoutScriptController::getExportedFunctions() +{ + return exportedFunction; +} + +GUID LayoutScriptController::getClassGuid() +{ + return layoutGuid; +} + +// ------------------------------------------------------------------------- + +scriptVar Layout::script_vcpu_onDock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar side) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS1(o, layoutController, side); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT1(o, side); +} + +scriptVar Layout::script_vcpu_onUndock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS0(o, layoutController); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT0(o); +} + +scriptVar Layout::script_vcpu_getScale(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + double r = 0; + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) r = l->getRenderRatio(); + return MAKE_SCRIPT_DOUBLE(r); +} + +scriptVar Layout::script_vcpu_setScale(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar s) +{ + SCRIPT_FUNCTION_INIT + double a = GET_SCRIPT_DOUBLE(s); + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) l->setRenderRatio(a); + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_onScale(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar s) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS1(o, layoutController, s); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT1(o, s); +} + +scriptVar Layout::script_vcpu_setDesktopAlpha(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar s) +{ + SCRIPT_FUNCTION_INIT + bool a = GET_SCRIPT_BOOLEAN(s); + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) l->setWantDesktopAlpha(a); + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_getDesktopAlpha(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) return MAKE_SCRIPT_BOOLEAN(l->wantDesktopAlpha() && l->isDesktopAlphaSafe()); + RETURN_SCRIPT_ZERO; +} + +scriptVar Layout::script_vcpu_isTransparencySafe(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) return MAKE_SCRIPT_BOOLEAN(l->isTransparencySafe()); + RETURN_SCRIPT_ZERO; +} + +scriptVar Layout::script_vcpu_isLayoutAnimationSafe(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) return MAKE_SCRIPT_BOOLEAN(!l->forceTransparencyFlag() && (l->getAlphaMgr()->getAlpha(l) == 255)); + RETURN_SCRIPT_ZERO; +} + +scriptVar Layout::script_vcpu_getContainer(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) + { + Container *c = l->getParentContainer(); + return MAKE_SCRIPT_OBJECT(c ? c->getScriptObject() : NULL); + } + return MAKE_SCRIPT_OBJECT(NULL); +} + +scriptVar Layout::script_vcpu_center(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) l->center(); + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_setRedrawOnResize(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar v) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) l->setWantRedrawOnResize(GET_SCRIPT_INT(v)); + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_beforeRedock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) windowTracker->beforeRedock(l, &l->redock); + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_redock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) windowTracker->afterRedock(l, &l->redock); + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_onEndMove(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS0(o, layoutController); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT0(o); +} + +scriptVar Layout::script_vcpu_onMouseEnterLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS0(o, layoutController); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT0(o); +} + +scriptVar Layout::script_vcpu_onMouseLeaveLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS0(o, layoutController); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT0(o); +} + +scriptVar Layout::script_vcpu_onSnapAdjustChanged(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS0(o, layoutController); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT0(o); +} + +scriptVar Layout::script_vcpu_onUserResize(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar x, scriptVar y, scriptVar w, scriptVar h) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS4(o, layoutController, x, y, w, h); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT4(o, x, y, w, h); +} + +scriptVar Layout::script_vcpu_onMove(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT; + PROCESS_HOOKS0(o, layoutController); + SCRIPT_FUNCTION_CHECKABORTEVENT; + SCRIPT_EXEC_EVENT0(o); +} + +scriptVar Layout::script_vcpu_snapAdjust(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar left, scriptVar top, scriptVar right, scriptVar bottom) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) l->snapAdjust(GET_SCRIPT_INT(left), GET_SCRIPT_INT(top), GET_SCRIPT_INT(right), GET_SCRIPT_INT(bottom)); + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_getSnapAdjustLeft(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) + { + RECT r; + l->getSnapAdjust(&r); + return MAKE_SCRIPT_INT(r.left); + } + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_getSnapAdjustTop(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) + { + RECT r; + l->getSnapAdjust(&r); + return MAKE_SCRIPT_INT(r.top); + } + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_getSnapAdjustRight(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) + { + RECT r; + l->getSnapAdjust(&r); + return MAKE_SCRIPT_INT(r.right); + } + RETURN_SCRIPT_VOID; +} + +scriptVar Layout::script_vcpu_getSnapAdjustBottom(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) +{ + SCRIPT_FUNCTION_INIT + Layout *l = static_cast<Layout *>(o->vcpu_getInterface(layoutGuid)); + if (l) + { + RECT r; + l->getSnapAdjust(&r); + return MAKE_SCRIPT_INT(r.bottom); + } + RETURN_SCRIPT_VOID; +} + +int Layout::broadcasting = 0; + +StringW Layout::MakePrefix() +{ + return StringPrintfW(L"Skin:%s/Container:%s/Layout:%s", WASABI_API_SKIN->getSkinName(), getParentContainer()->getDescriptor(), getGuiObject()->guiobject_getId()); +}
\ No newline at end of file diff --git a/Src/Wasabi/api/wndmgr/layout.h b/Src/Wasabi/api/wndmgr/layout.h new file mode 100644 index 00000000..20a90504 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/layout.h @@ -0,0 +1,465 @@ +#ifndef __LAYOUT_H +#define __LAYOUT_H + +class Layout; +class Group; +class Container; +class Layer; + +#include <bfc/tlist.h> +#include <bfc/depend.h> +#include <tataki/bitmap/bitmap.h> +#include <api/wnd/wndclass/buttwnd.h> +#include <tataki/region/region.h> +#include <api/wndmgr/container.h> +#include <api/skin/group.h> +#include <api/skin/widgets/layer.h> +#include <api/wndmgr/guistatuscb.h> +#include <api/script/script.h> +#include <api/script/scriptobj.h> +#ifdef WASABI_WIDGETS_GUIOBJECT +#include <api/script/objects/guiobj.h> +#endif +#include <api/wnd/accessible.h> +#include <api/wndmgr/alphamgr.h> +#include <api/wnd/resizable.h> + +class XmlObject; +class Layout; + +extern AlphaMgr *alphaMgr; + +class LayoutScriptController : public GroupScriptController { + public: + + virtual const wchar_t *getClassName(); + virtual const wchar_t *getAncestorClassName(); + virtual ScriptObjectController *getAncestorController() { return groupController; } + virtual int getNumFunctions(); + virtual const function_descriptor_struct *getExportedFunctions(); + virtual GUID getClassGuid(); + virtual ScriptObject *instantiate(); + virtual int getInstantiable(); + virtual void destroy(ScriptObject *o); + virtual void *encapsulate(ScriptObject *o); + virtual void deencapsulate(void *o); + + private: + + static function_descriptor_struct exportedFunction[]; + +}; + +extern LayoutScriptController *layoutController; + +#ifndef _NOSTUDIO + +class AutoOpacityLinker; + +#define LAYOUT_PARENT Group +#define LAYOUT_SCRIPTPARENT Group + +class Layout : public LAYOUT_SCRIPTPARENT, public DependentViewerI, public GuiResizable +{ + +public: + Layout(); + virtual ~Layout(); + +#ifdef _WIN32 + virtual LRESULT wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +#else + virtual OSStatus eventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); +#endif + +// int onPaint(Canvas *canvas); + virtual int onInit(); + virtual int init(OSMODULEHANDLE inst, OSWINDOWHANDLE parent, int nochild); + virtual int reinit(OSMODULEHANDLE inst, OSWINDOWHANDLE parent, int nochild); + + virtual int childNotify(ifc_window *child, int msg, intptr_t param1=0, intptr_t param2=0); + virtual int onActionNotify(int action, intptr_t param=0); + + virtual void resize(int x, int y, int w, int h, int wantcb=1); + virtual void move(int x, int y); + +// virtual int onRightButtonDown(int x, int y); +// virtual int onLeftButtonDown(int x, int y); +// virtual int onMouseMove(int x, int y); +// virtual int onLeftButtonUp(int x, int y); + virtual int onResize(); + virtual int onPostedMove(); + virtual int onPaint(Canvas *canvas); + virtual void onSetDesktopAlpha(int a); + virtual int isLayout(); + virtual void setAlphaBackground(const wchar_t *txture); + virtual SkinBitmap *getBaseTexture(); + virtual void onGuiObjectSetVisible(GuiObject *o, int status); // called whenever a child shows/hide + virtual ifc_window *getCustomOwner(); + virtual void addLockedLayout(Layout *l); + virtual void removeLockedLayout(Layout *l); + virtual int getNumLockedLayouts(); + virtual Layout *enumLockedLayout(int n); + virtual int isLocked(); + virtual void lockTo(Layout *l); + virtual Layout *getLockedTo(); + void updateLockedLayouts(); + virtual int onGetFocus(); + virtual int onKillFocus(); + virtual void snapAdjust(int left, int right, int top, int bottom); + + virtual void onShow(void); + virtual void onHide(void); + + virtual void center(); + + virtual int wantDesktopAlpha(); + virtual void setWantDesktopAlpha(int want); + virtual int handleDesktopAlpha(); + + virtual int setXuiParam(int _xuihandle, int attribid, const wchar_t *paramname, const wchar_t *strvalue); + + void setWindowRegion(api_region *reg); + virtual int allowResize() { + return !isLocked() +#ifdef USEAPPBAR + && !appbar_isDocked() +#endif + ; + } + + // container/component callbacks to get notified that a container + // has been set visible/invisible + void containerToggled(const wchar_t *id,int visible); + void componentToggled(GUID *guid, int visible); + + void setParentContainer(Container *c); + virtual Container *getParentContainer(); + + virtual int isClickThrough(); + + void onSetVisible(int show); + virtual void cancelCapture(); + + virtual int onActivate(); + virtual int onDeactivate(); + + virtual int forceTransparencyFlag(); + + int x, y; + +#ifdef _WIN32 + void setForwardMsgWnd(HWND wnd) { forwardMsgWnd = wnd; } + + LPARAM wndHolder_getParentParam(int i=0); +#endif + + void scaleTo(int s); + virtual void setRenderRatio(double s); + + virtual void beginMove(); + virtual void beginScale(); + virtual void beginResize(); + virtual void endMove(); + virtual void endScale(); + virtual void endResize(); + + virtual void setEndMoveResize(int w, int h) { + m_w = w; + m_h = h; + m_endmovesize = 1; + }; + + virtual ifc_window *guiresizable_getRootWnd() { return (this); } + + + virtual void lockScale(int locked); + virtual int isScaleLocked() { return scalelocked; } + + virtual void onMove(); + + virtual int isDesktopAlphaSafe(); + + void addSubRegionLayer(Layer *l); + void removeSubRegionLayer(Layer *l); + + virtual void setInDesktop(int a); + virtual int getInDesktop(); + + virtual void setAlpha(int a); + virtual int getAlpha(); + virtual int getPaintingAlpha(); + virtual void timerCallback(int id); + + virtual void setLinkWidth(const wchar_t *layoutid); + virtual void setLinkHeight(const wchar_t *layoutid); + + virtual void setBaseTexture(const wchar_t *b, int regis=1); + virtual void setPaintingAlpha(int activealpha, int inactivealpha=-1); + + static void onGlobalEnableDesktopAlpha(int enabled); + + void savePosition(); +#ifdef USEAPPBAR + void saveAppBarPosition(); +#endif + virtual void setStatusText(const wchar_t *txt, int overlay=0); + virtual void addAppCmds(AppCmds *commands); + virtual void removeAppCmds(AppCmds *commands); + + void pushCompleted(int max=100); + void incCompleted(int add=1); + void setCompleted(int pos); + void popCompleted(); + + virtual void registerStatusCallback(GuiStatusCallback *lcb); + virtual int viewer_onItemDeleted(api_dependent *item); + virtual int wantActivation() { return wantactiv && LAYOUT_PARENT::wantActivation(); } + void loadSavedState(); + virtual void updateOnTop(); + + virtual int runAction(int actionid, const wchar_t *param=NULL); + + virtual void getSnapAdjust(RECT *r); + + virtual void updateTransparency(); + virtual int onDeferredCallback(intptr_t p1, intptr_t p2); + virtual int wantRedrawOnResize() { return wantredrawonresize; } + virtual void setWantRedrawOnResize(int v); + +#ifdef USEAPPBAR + virtual int appbar_wantAutoHide() { return getAppBarAutoHide(); } + virtual int appbar_wantAlwaysOnTop() { return getAppBarAlwaysOnTop(); } + + virtual int getAppBarAutoHide(); + virtual void setAppBarAutoHide(int ah); + + virtual int getAppBarAlwaysOnTop(); + virtual void setAppBarAlwaysOnTop(int aot); +#endif + + virtual void pushForceUnlink() { m_forceunlink++; } + virtual void popForceUnlink() { m_forceunlink--; } + + virtual int isUnlinked() { +#ifdef USEAPPBAR + return unlinked || appbar_isDocked() || m_forceunlink; +#else + return unlinked || m_forceunlink; +#endif + } + + void setAutoOpacify(int a); + int getAutoOpacify() { return autoopacify; } + + void offscreenCheck(); + int isOffscreen(ifc_window *w); + + int getResizable(); + int getScalable(); + + void setTransparencyOverride(int v); + int getTransparencyOverride() { return transparencyoverride; } + + enum { + LAYOUT_SETDESKTOPALPHA=0, + LAYOUT_SETINDESKTOP, + LAYOUT_SETALPHA, + LAYOUT_SETLINKWIDTH, + LAYOUT_SETLINKHEIGHT, + LAYOUT_SETOWNER, + LAYOUT_SETLOCKTO, + LAYOUT_SETOSFRAME, + LAYOUT_SETALPHABACKGROUND, + LAYOUT_SETNOACTIVATION, + LAYOUT_SETONTOP, + LAYOUT_SNAPADJUSTLEFT, + LAYOUT_SNAPADJUSTTOP, + LAYOUT_SNAPADJUSTRIGHT, + LAYOUT_SNAPADJUSTBOTTOM, + LAYOUT_UNLINKED, + LAYOUT_NOPARENT, + LAYOUT_FORCEALPHA, + LAYOUT_NODOCK, + LAYOUT_NOOFFSCREENCHECK, + LAYOUT_RESIZABLE, + LAYOUT_SCALABLE, + }; + + + void onMouseEnterLayout(); + void onMouseLeaveLayout(); + + int getNoParent() { return noparent; } + void setNoParent(int np) { noparent = np; } + int isAlphaForced() { return forcealpha; } + + AlphaMgr *getAlphaMgr() { return alphaMgr; } + + int getNoDock() { return nodock; } + void setNoDock(int nd) { nodock = nd; } + int isTransparencyForcedOff() { return transparency_autooff; } + + void controlMenu(); + + void setNoOffscreenCheck(int nocheck); + +#ifdef USEAPPBAR + void onDock(int side); + void onUnDock(); + + virtual void appbar_onDock(int side); + virtual void appbar_onUnDock(); + virtual void appbar_onSlide(); +#endif + +protected: + /*static */void CreateXMLParameters(int master_handle); +/* virtual int dragEnter(ifc_window *sourceWnd); + virtual int dragOver(int x, int y, ifc_window *sourceWnd); + virtual int dragDrop(ifc_window *sourceWnd, int x, int y); + virtual int acceptExternalDrops() { return 1; }*/ + virtual int wantClickWndAutoInvalidate() { return 0; } + + +private: + StringW MakePrefix(); + static XMLParamPair params[]; + void fixPosition(); + void saveAllPositions(); + void activateChildren(int act); +#ifdef _WIN32 + void getExplorerWindows(HWND *parent, HWND *listview, HWND *webserver); +#endif + void desktopAlpha_autoTurnOn(); + void desktopAlpha_autoTurnOff(); + void transparency_autoTurnOn(); + void transparency_autoTurnOff(); + void globalEnableDesktopAlpha(int enabled); + +#ifdef _WIN32 + HWND forwardMsgWnd; +#endif + int resizing; + int wantactiv; + int size_w,size_h; + int cX,cY; + int captured; + POINT mousepos; +#ifdef _WIN32 + HWND webserver; + HWND listview; +#endif + int alphagoingon; + int alphagoingoff; + int scalelocked; + int wantredrawonresize; + + int xuihandle; + + RegionI *reg; + //PtrList<Layer> *subregionlayers; + Container *p_container; + StringW alphabackgroundstr; + ifc_window *wndholders; + int abortSaving(); + int transparencyoverride; + + int default_x; + int default_y; + int moving; + int scaling; + int mover; + int indesktop; + int alpha; + StringW linkedheight, linkedwidth; + int inlinkwidth, inlinkheight; + AutoSkinBitmap alphabackground; + int wantdesktopalpha; + int galphadisabled; + static PtrList<Layout> alllayouts; + StringW owner; + PtrList<Layout> locked; + StringW lockto; + Layout *lockedto; + int inpostedmove; + int osframe; + PtrList<GuiStatusCallback> statuscbs; + int initontop; +// GarbageCollector gc; + PtrList<AppCmds> appcmds; + int inresize; + int unlinked; + + int snap_adjust_left; + int snap_adjust_top; + int snap_adjust_right; + int snap_adjust_bottom; + + int disable_auto_alpha; + int autoopacify; + int noparent; + int forcealpha; + redock_struct redock; + static int broadcasting; + int nodock; + uint32_t transparency_reenabled_at; + int transparency_autooff; + int nooffscreencheck; + int resizable; + int scalable; + + int m_w, m_h; + int m_endmovesize; + int m_allowsavedock; + int m_forceunlink; +#ifdef USEAPPBAR + int appbar_want_autohide; + int appbar_want_alwaysontop; +#endif + +// FG> +// -- SCRIPT ----------------------------------------------------- +public: + + static scriptVar script_vcpu_onDock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar side); + static scriptVar script_vcpu_onUndock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_getScale(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_setScale(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar s); + static scriptVar script_vcpu_onScale(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar s); + static scriptVar script_vcpu_setDesktopAlpha(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar s); + static scriptVar script_vcpu_getDesktopAlpha(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_isTransparencySafe(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_isLayoutAnimationSafe(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_getContainer(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_center(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_onMove(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_onEndMove(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_onUserResize(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar x, scriptVar y, scriptVar w, scriptVar h); + static scriptVar script_vcpu_snapAdjust(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar left, scriptVar top, scriptVar right, scriptVar bottom); + static scriptVar script_vcpu_setRedrawOnResize(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar v); + static scriptVar script_vcpu_beforeRedock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_redock(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_getSnapAdjustTop(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_getSnapAdjustLeft(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_getSnapAdjustRight(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_getSnapAdjustBottom(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_onMouseEnterLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_onMouseLeaveLayout(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + static scriptVar script_vcpu_onSnapAdjustChanged(SCRIPT_FUNCTION_PARAMS, ScriptObject *o); + +#else +class Layout : public LAYOUT_SCRIPTPARENT { + +public: + +#endif + +// INSERT_SCRIPT_OBJECT_CONTROL + + +}; + +// END SCRIPT + +#endif diff --git a/Src/Wasabi/api/wndmgr/msgbox.cpp b/Src/Wasabi/api/wndmgr/msgbox.cpp new file mode 100644 index 00000000..4a32cf66 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/msgbox.cpp @@ -0,0 +1,251 @@ +#include <precomp.h> +#include "msgbox.h" +#include <api/wndmgr/skinwnd.h> +#include <api/wnd/wndclass/guiobjwnd.h> +#include <api/script/scriptguid.h> +#include <api/script/objects/c_script/c_container.h> +#include <api/script/objects/c_script/c_text.h> +#include <api/script/objects/c_script/c_button.h> + +_btnstruct msgboxbtns[] = + { + { L"<<", MSGBOX_PREVIOUS }, + { L"OK", MSGBOX_OK }, + { L"Yes", MSGBOX_YES }, + { L"All", MSGBOX_ALL }, + { L"No", MSGBOX_NO }, + { L">>", MSGBOX_NEXT }, + { L"Cancel", MSGBOX_CANCEL }, + }; + +MsgBox::MsgBox(const wchar_t *_text, const wchar_t *_title, int _flags, const wchar_t *notanymore) +{ + text = _text; + title = _title; + flags = _flags; +#ifdef WIN32 +#ifdef _DEBUG + DebugStringW(L"msgbox: %s: %s", title, text.getValue()); +#endif +#endif + notanymore_id = notanymore; + sw = NULL; + if (flags == 0) flags = MSGBOX_OK; +} + +MsgBox::~MsgBox() +{ + foreach(buttons) + WASABI_API_SKIN->xui_delete(buttons.getfor()); + endfor +} + +int MsgBox::run() +{ + int _r = -1; + +#ifdef WASABI_COMPILE_CONFIG + if (!notanymore_id.isempty()) + { + StringPrintfW txt(L"msgbox_defaultvalue_%s", notanymore_id); + if ((GetKeyState(VK_SHIFT) & 0x8000)) + WASABI_API_CONFIG->setIntPublic(txt, -1); + _r = WASABI_API_CONFIG->getIntPublic(txt, -1); + } +#endif + + if (_r == -1) + { + sw = new SkinWnd(L"msgbox.custom.group", L"modal", FALSE, NULL, 1, 1); + if (!sw->getWindow()) return -1; + ifc_window *grp = sw->getWindow(); + ifc_window *l = grp->getDesktopParent(); + + GuiObject *_p = sw->findObject(L"msgbox.custom.group"); + //CUT: api_window *p = _p->guiobject_getRootWnd(); + + C_Container cont(sw->getContainer()); + cont.setName(title); + + createButtons(); + int min_w = reposButtons(); + + GuiObject *go_txt = sw->findObject(L"msgbox.text"); + if (go_txt != NULL) + { + GuiObject *to = go_txt->guiobject_findObject(L"wasabi.text"); + GuiObject *gto = sw->findObject(L"text"); + if (to != NULL && gto != NULL) + { + go_txt->guiobject_setXmlParam(L"text", text); + C_GuiObject t(*go_txt); + int _w = t.getAutoWidth(); + int _h = t.getAutoHeight(); + + to->guiobject_setXmlParam(L"w", StringPrintfW(_w)); + to->guiobject_setXmlParam(L"h", StringPrintfW(_h)); + to->guiobject_setXmlParam(L"relatw", L"0"); + to->guiobject_setXmlParam(L"relath", L"0"); + + int x, rx, w, rw; + int y, ry, h, rh; + int gtow, gtoh; + + go_txt->guiobject_getGuiPosition(&x, &y, &w, &h, &rx, &ry, &rw, &rh); + if (rw == 1) + _w += -w; + else + _w += x * 2; + if (rh == 1) + _h += -h; + else + _h += y * 2; + + gtow = _w; + gtoh = _h; + + GuiObject *grpo = grp->getGuiObject(); + ASSERT(grpo != NULL); + gto->guiobject_getGuiPosition(&x, &y, &w, &h, &rx, &ry, &rw, &rh); + if (rw == 1) + _w += -w; + else + _w += x * 2; + if (rh == 1) + _h += -h; + else + _h += y * 2; + + gto->guiobject_setXmlParam(L"w", StringPrintfW(gtow)); + gto->guiobject_setXmlParam(L"h", StringPrintfW(gtoh)); + + grpo->guiobject_setXmlParam(L"w", StringPrintfW(_w)); + grpo->guiobject_setXmlParam(L"h", StringPrintfW(_h)); + grpo->guiobject_setXmlParam(L"lockminmax", L"1"); + grpo->guiobject_setXmlParam(L"propagatesize", L"1"); + XmlObject *xl = static_cast<XmlObject *>(l->getInterface(xmlObjectGuid)); + xl->setXmlParam(L"minimum_h", StringPrintfW(L"%d", _h)); + xl->setXmlParam(L"minimum_w", StringPrintfW(L"%d", (_w < min_w) ? min_w : _w)); + } + } + + if (!notanymore_id.isempty()) + { + GuiObject *o = WASABI_API_SKIN->xui_new(L"Wasabi:CheckBox"); // that'll be deleted automatically when our parent group destroys + if (o != NULL) + { + ifc_window *w = o->guiobject_getRootWnd(); + C_GuiObject go(*o); + go.init(_p->guiobject_getScriptObject()); + o->guiobject_setXmlParam(L"text", L"Do not show this message anymore"); + o->guiobject_setXmlParam(L"y", L"-50"); + o->guiobject_setXmlParam(L"relaty", L"1"); + o->guiobject_setXmlParam(L"x", L"12"); + o->guiobject_setXmlParam(L"relatx", L"0"); + o->guiobject_setXmlParam(L"w", L"-24"); + o->guiobject_setXmlParam(L"relatw", L"1"); + min_w = MAX(w->getPreferences(SUGGESTED_W), min_w); + } + } + + sw->notifyMinMaxChanged(); + reposButtons(); + _r = sw->runModal(1); + } + +#ifdef WASABI_COMPILE_CONFIG + if (!notanymore_id.isempty() && _r != -1 && sw != NULL) + { + GuiObject *o = sw->findObject(L"checkbox.toggle"); + if (o != NULL) + { + C_Button b(*o); + if (b.getActivated()) + { + StringPrintfW txt(L"msgbox_defaultvalue_%s", notanymore_id); + WASABI_API_CONFIG->setIntPublic(txt, _r); + } + } + } +#endif + + if (sw) sw->destroy(); sw = NULL; + + return _r; +} + +void MsgBox::addButton(const wchar_t *text, int retcode) +{ + GuiObject *o = WASABI_API_SKIN->xui_new(L"Wasabi:Button"); // that wil NOT be deleted automatically when our parent group destroys because we did not init with guiobject + if (o != NULL) + { + o->guiobject_setXmlParam(L"action", L"endmodal"); + o->guiobject_setXmlParam(L"retcode", StringPrintfW(retcode)); + o->guiobject_setXmlParam(L"text", text); + buttons.addItem(o); + } +} + +void MsgBox::createButtons() +{ + GuiObject *_p = sw->findObject(L"msgbox.custom.group"); + if (!_p) return ; + + ASSERT(buttons.getNumItems() == 0); + buttons.deleteAll(); + + for (int i = 0;i < sizeof(msgboxbtns) / sizeof(_btnstruct);i++) + { + if (flags & msgboxbtns[i].id) + { + addButton(msgboxbtns[i].txt, msgboxbtns[i].id); + } + } + + ifc_window *p = _p->guiobject_getRootWnd(); + + foreach(buttons) + ifc_window *wnd = buttons.getfor()->guiobject_getRootWnd(); + if (wnd != NULL) + { + wnd->setStartHidden(1); + wnd->setParent(p); + wnd->init(p); + } + endfor; +} + +int MsgBox::reposButtons() +{ + RECT r; + GuiObject *_p = sw->findObject(L"msgbox.custom.group"); + ifc_window *p = _p->guiobject_getRootWnd(); + p->getClientRect(&r); + + int shift = 0; + + //CUT: int _w = 0; + //CUT: int _h = 0; + for (int i = buttons.getNumItems() - 1;i >= 0;i--) + { + ifc_window *wnd = buttons.enumItem(i)->guiobject_getRootWnd(); + if (wnd != NULL) + { + int _w = wnd->getPreferences(SUGGESTED_W); + int _h = wnd->getPreferences(SUGGESTED_H); + if (_w == AUTOWH) _w = -1; + int w = MAX(_w, 64); + wnd->resize(r.right - w - 16 - shift, r.bottom - 8 - _h, w, _h); + _w = MAX(w, _w); + _h = MAX(_h, _h); + shift += w + 4; + } + } + + foreach(buttons) + ifc_window *wnd = buttons.getfor()->guiobject_getRootWnd(); + if (wnd != NULL) + wnd->setVisible(1); + endfor; + return shift; +} diff --git a/Src/Wasabi/api/wndmgr/msgbox.h b/Src/Wasabi/api/wndmgr/msgbox.h new file mode 100644 index 00000000..41487835 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/msgbox.h @@ -0,0 +1,49 @@ +#ifndef __MESSAGEBOX_H +#define __MESSAGEBOX_H + +#include <bfc/string/bfcstring.h> +#include <bfc/string/StringW.h> +#include <bfc/ptrlist.h> + +#define MSGBOX_ABORTED 0 // NOT a flag, only a return code + +#define MSGBOX_OK 1 +#define MSGBOX_CANCEL 2 +#define MSGBOX_YES 4 +#define MSGBOX_NO 8 +#define MSGBOX_ALL 16 +#define MSGBOX_NEXT 32 +#define MSGBOX_PREVIOUS 64 + +class GuiObject; +class SkinWnd; + + +typedef struct { + wchar_t *txt; + int id; +} _btnstruct; + +class MsgBox { + public: + + MsgBox(const wchar_t *text, const wchar_t *title=L"Alert", int flags=MSGBOX_OK, const wchar_t *notanymore=NULL); + virtual ~MsgBox(); + virtual int run(); + + + private: + + void createButtons(); + int reposButtons(); + void addButton(const wchar_t *text, int retcode); + + StringW text, title; + int flags; + PtrList<GuiObject> buttons; + GuiObject *checkbox; + SkinWnd *sw; + StringW notanymore_id; +}; + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/wndmgr/resize.cpp b/Src/Wasabi/api/wndmgr/resize.cpp new file mode 100644 index 00000000..959ece91 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/resize.cpp @@ -0,0 +1,383 @@ +#include <precomp.h> +#ifdef WIN32 +#include <windows.h> +#endif + +#include <bfc/assert.h> +#include <api/wndmgr/resize.h> +#include <api/wnd/wndtrack.h> +#include <api/wnd/basewnd.h> +#include <api/wndmgr/layout.h> + +#define tag L"wa3_resizerclass" + +extern HINSTANCE hInstance; + + +//---------------------------------------------------------------------- +resizeClass::resizeClass(ifc_window *wnd, int minx, int miny, int maxx, int maxy, int sugx, int sugy) +{ + screenWidth = Wasabi::Std::getScreenWidth(); + screenHeight = Wasabi::Std::getScreenHeight(); + +#if defined (_WIN32) || defined(_WIN64) + WNDCLASSW wc; + if (!GetClassInfoW(hInstance, tag, &wc)) + { + MEMSET(&wc, 0, sizeof(wc)); + wc.lpfnWndProc = resizeWndProc; + wc.hInstance = hInstance; // hInstance of DLL + wc.lpszClassName = tag; // our window class name + wc.style = 0; + + int _r = RegisterClassW(&wc); + ASSERTPR(_r, "cannot create resizer wndclass"); + } + + hWnd = CreateWindowExW(0, tag, L"", 0, 0, 0, 1, 1, NULL, NULL, hInstance, NULL); + + ASSERT(hWnd); + + SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)this); + + if (minx > maxx && maxx != -1) minx = maxx; + if (miny > maxy && maxy != -1) miny = maxy; +#endif + + minWinWidth = minx; + minWinHeight = miny; + maxWinWidth = maxx; + maxWinHeight = maxy; + sugWinWidth = sugx; + sugWinHeight = sugy; + + if (wnd->getInterface(layoutGuid)) + { + static_cast<Layout *>(wnd)->getSnapAdjust(&snapAdjust); + if (minWinWidth != -1) minWinWidth -= snapAdjust.left + snapAdjust.right; + if (minWinHeight != -1) minWinHeight -= snapAdjust.bottom + snapAdjust.top; + if (maxWinWidth != -1) maxWinWidth -= snapAdjust.left + snapAdjust.right; + if (maxWinHeight != -1) maxWinHeight -= snapAdjust.bottom + snapAdjust.top; + if (sugWinWidth != -1) sugWinWidth -= snapAdjust.left + snapAdjust.right; + if (sugWinHeight != -1) sugWinHeight -= snapAdjust.bottom + snapAdjust.top; + } + + dc = NULL; +#ifdef WIN32 + oldB = NULL; + brush = NULL; + oldP = NULL; + pen = NULL; +#endif +} + + +//---------------------------------------------------------------------- +resizeClass::~resizeClass() +{ +#ifdef WIN32 + if (dc) + { + SelectObject(dc, oldB); + SelectObject(dc, oldP); + SetROP2(dc, mix); + DeleteObject(pen); + DeleteObject(brush); + ReleaseDC(NULL, dc); + } + + if (IsWindow(hWnd)) + DestroyWindow(hWnd); + //BU win98 sucks UnregisterClass(tag, Main::gethInstance()); +#else + if (dc) + { + XFreeGC(Linux::getDisplay(), dc->gc); + FREE(dc); + } +#endif +} + +//---------------------------------------------------------------------- +BOOL CALLBACK invalidateChildren(HWND hwnd, LPARAM lParam) +{ + InvalidateRect(hwnd, NULL, FALSE); + return TRUE; +} + +//---------------------------------------------------------------------- +BOOL CALLBACK invalidateAll(HWND hwnd, LPARAM lParam) +{ + EnumChildWindows(hwnd, invalidateChildren, 0); + InvalidateRect(hwnd, NULL, FALSE); + return TRUE; +} + +//---------------------------------------------------------------------- +int resizeClass::resizeWindow(ifc_window *wnd, int way) +{ + + // paintHookStart(); + + wnd->getWindowRect(&originalRect); + + snapAdjust.left = 0; + snapAdjust.top = 0; + snapAdjust.right = 0; + snapAdjust.bottom = 0; + + if (wnd->getInterface(layoutGuid)) + { + static_cast<Layout *>(wnd)->getSnapAdjust(&snapAdjust); + if (wnd->getRenderRatio() != 1.0) + { + double rr = wnd->getRenderRatio(); + snapAdjust.left = (int)((double)(snapAdjust.left) * rr); + snapAdjust.top = (int)((double)(snapAdjust.top) * rr); + snapAdjust.right = (int)((double)(snapAdjust.right) * rr); + snapAdjust.bottom = (int)((double)(snapAdjust.bottom) * rr); + } + originalRect.left += snapAdjust.left; + originalRect.top += snapAdjust.top; + originalRect.right -= snapAdjust.right; + originalRect.bottom -= snapAdjust.bottom; + } + + curRect = originalRect; + resizeWay = way; + resizedWindow = wnd->gethWnd(); + resizedWindowR = wnd; + + POINT pt; + Wasabi::Std::getMousePos(&pt); + cX = pt.x; + cY = pt.y; + +#ifdef WIN32 + SetCapture(hWnd); +#endif + SetTimer(hWnd, 1, 100, NULL); // this timer will make sure that we never get interlock + + drawFrame(); + + MSG msg; + cancelit = 1; + while (GetCapture() == hWnd && GetMessage( &msg, hWnd, 0, 0 )) + { + TranslateMessage( &msg ); +#ifdef LINUX + if ( msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE ) + wndProc( msg.hwnd, msg.message, msg.wParam, msg.lParam ); + else +#endif + DispatchMessage( &msg ); + } + + drawFrame(); + + // paintHookStop(); + + if (GetCapture() == hWnd) ReleaseCapture(); + KillTimer(hWnd, 1); + + if (!cancelit) + { + curRect.left -= snapAdjust.left; + curRect.top -= snapAdjust.top; + curRect.right += snapAdjust.right; + curRect.bottom += snapAdjust.bottom; + } + else + { + curRect = originalRect; + // evil, but less evil than InvalidateRect(NULL, NULL, FALSE); + EnumWindows(invalidateAll, 0); + } + + return !cancelit; +} + + +//---------------------------------------------------------------------- +RECT resizeClass::getRect(void) +{ + return curRect; +} + +//#define nifty + +//---------------------------------------------------------------------- +void resizeClass::drawFrame(void) +{ + RECT outRect; + +#ifdef WIN32 + if (!dc) + { + dc = GetDC(NULL); + brush = CreateSolidBrush(0xFFFFFF); + pen = CreatePen(PS_SOLID, 0, 0xFFFFFF); + oldB = (HBRUSH)SelectObject(dc, brush); + oldP = (HPEN)SelectObject(dc, pen); + mix = SetROP2(dc, R2_XORPEN); + } + + outRect = curRect; + +#ifndef nifty + + DrawFocusRect(dc, &outRect); + +#else + + RECT inRect; + + inRect = outRect; + inRect.left += 10; + inRect.right -= 10; + inRect.top += 24; + inRect.bottom -= 10; + + MoveToEx(dc, inRect.left, inRect.top, NULL); + LineTo(dc, inRect.right, inRect.top); + LineTo(dc, inRect.right, inRect.bottom); + LineTo(dc, inRect.left, inRect.bottom); + LineTo(dc, inRect.left, inRect.top); + MoveToEx(dc, outRect.left, 0, NULL); + LineTo(dc, outRect.left, screenHeight); + MoveToEx(dc, outRect.right, 0, NULL); + LineTo(dc, outRect.right, screenHeight); + MoveToEx(dc, 0, outRect.top, NULL); + LineTo(dc, screenWidth, outRect.top); + MoveToEx(dc, 0, outRect.bottom, NULL); + LineTo(dc, screenWidth, outRect.bottom); + +#endif +#endif//WIN32 +#ifdef LINUX + outRect = curRect; + + if ( ! dc ) + { + dc = (HDC)MALLOC( sizeof( hdc_typ ) ); + XGCValues gcv; + gcv.function = GXxor; + gcv.subwindow_mode = IncludeInferiors; + gcv.foreground = 0xffffff; + gcv.line_style = LineOnOffDash; + gcv.dashes = 1; + dc->gc = XCreateGC( Linux::getDisplay(), Linux::RootWin(), GCFunction | GCForeground | GCSubwindowMode, &gcv ); + } + + XDrawRectangle( Linux::getDisplay(), Linux::RootWin(), dc->gc, + outRect.left, outRect.top, outRect.right - outRect.left, + outRect.bottom - outRect.top ); +#endif + //PORTME +} + +LRESULT resizeClass::wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_LBUTTONUP: + cancelit = 0; + ReleaseCapture(); + return 0; + + case WM_MOUSEMOVE: + { + POINT pt; + int iX, iY; + Wasabi::Std::getMousePos(&pt); + iX = pt.x - cX; + iY = pt.y - cY; + drawFrame(); + + if (resizeWay & TOP) + curRect.top = originalRect.top + iY; + if (resizeWay & BOTTOM) + curRect.bottom = originalRect.bottom + iY; + if (resizeWay & LEFT) + curRect.left = originalRect.left + iX; + if (resizeWay & RIGHT) + curRect.right = originalRect.right + iX; + + if (abs((curRect.right - curRect.left) - sugWinWidth) < 10) + if (resizeWay & RIGHT) + curRect.right = curRect.left + sugWinWidth; + else if (resizeWay & LEFT) + curRect.left = curRect.right - sugWinWidth; + + if (abs((curRect.bottom - curRect.top) - sugWinHeight) < 10) + if (resizeWay & BOTTOM) + curRect.bottom = curRect.top + sugWinHeight; + else if (resizeWay & TOP) + curRect.top = curRect.bottom - sugWinHeight; + + curRect.left -= snapAdjust.left; + curRect.top -= snapAdjust.top; + curRect.right += snapAdjust.right; + curRect.bottom += snapAdjust.bottom; + + windowTracker->autoDock(resizedWindowR, &curRect, resizeWay); + + curRect.left += snapAdjust.left; + curRect.top += snapAdjust.top; + curRect.right -= snapAdjust.right; + curRect.bottom -= snapAdjust.bottom; + + if ((curRect.right - curRect.left) < minWinWidth) + if (resizeWay & RIGHT) + curRect.right = curRect.left + minWinWidth; + else if (resizeWay & LEFT) + curRect.left = curRect.right - minWinWidth; + + if ((curRect.bottom - curRect.top) < minWinHeight) + if (resizeWay & BOTTOM) + curRect.bottom = curRect.top + minWinHeight; + else if (resizeWay & TOP) + curRect.top = curRect.bottom - minWinHeight; + + if (maxWinWidth != -1 && (curRect.right - curRect.left) > maxWinWidth) + if (resizeWay & RIGHT) + curRect.right = curRect.left + maxWinWidth; + else if (resizeWay & LEFT) + curRect.left = curRect.right - maxWinWidth; + + if (maxWinHeight != -1 && (curRect.bottom - curRect.top) > maxWinHeight) + if (resizeWay & BOTTOM) + curRect.bottom = curRect.top + maxWinHeight; + else if (resizeWay & TOP) + curRect.top = curRect.bottom - maxWinHeight; + + drawFrame(); + } + return 0; + } +#ifdef WIN32 + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +#else + return 0; +#endif +} + +// Window Procedure +// +LRESULT CALLBACK resizeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ +#ifdef WIN32 + resizeClass *gThis = (resizeClass *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); + if (!gThis) + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + else + return gThis->wndProc(hwnd, uMsg, wParam, lParam); +#else + return 0; +#endif +} + +void resizeClass::setResizeCursor(int action) +{} + + diff --git a/Src/Wasabi/api/wndmgr/resize.h b/Src/Wasabi/api/wndmgr/resize.h new file mode 100644 index 00000000..2d67e14c --- /dev/null +++ b/Src/Wasabi/api/wndmgr/resize.h @@ -0,0 +1,48 @@ +#ifndef __RESIZE_H +#define __RESIZE_H +#ifdef _WIN32 +LRESULT CALLBACK resizeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif + +class resizeClass +{ +#ifdef _WIN32 + friend LRESULT CALLBACK resizeWndProc(HWND wnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // heh, i really need this one ;) +#endif +private: + void drawFrame(void); + void setResizeCursor(int action); + int orientation(int a, int action); + OSWINDOWHANDLE hWnd; + OSWINDOWHANDLE resizedWindow; + ifc_window *resizedWindowR; + int resizeWay; + RECT curRect; + RECT originalRect; + int cX, cY; + int minWinWidth, minWinHeight; + int maxWinWidth, maxWinHeight; + int sugWinWidth, sugWinHeight; + int screenHeight, screenWidth; + bool cancelit; + RECT snapAdjust; + +#ifdef WIN32 + HBRUSH oldB, brush; + HPEN oldP, pen; +#endif + HDC dc; + int mix; + +public: + resizeClass(ifc_window *wnd, int minx, int miny, int maxx, int maxy, int sugx, int sugy); + ~resizeClass(); + int resizeWindow(ifc_window *wnd, int way); +#ifdef _WIN32 + LRESULT wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif + RECT getRect(void); +}; + +#endif + diff --git a/Src/Wasabi/api/wndmgr/skinembed.cpp b/Src/Wasabi/api/wndmgr/skinembed.cpp new file mode 100644 index 00000000..079bc688 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/skinembed.cpp @@ -0,0 +1,733 @@ +#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; diff --git a/Src/Wasabi/api/wndmgr/skinembed.h b/Src/Wasabi/api/wndmgr/skinembed.h new file mode 100644 index 00000000..e33630ab --- /dev/null +++ b/Src/Wasabi/api/wndmgr/skinembed.h @@ -0,0 +1,76 @@ +#ifndef __SKIN_EMBEDDER_H +#define __SKIN_EMBEDDER_H + +#include <bfc/nsguid.h> +#include <bfc/string/bfcstring.h> +#include <bfc/string/StringW.h> +#include <bfc/ptrlist.h> +#include <bfc/depend.h> +#include <api/timer/timerclient.h> + +#define CB_DESTROYCONTAINER 0x887 + +class ifc_window; +class WindowHolder; +class Container; +class Layout; + +class SkinEmbedEntry { + public: + SkinEmbedEntry(api_dependent *d, ifc_window *w, GUID g, const wchar_t *gid, const wchar_t *prefered_container, int container_flag, Container *c, WindowHolder *wh) : groupid(gid), guid(g), dep(d), wnd(w), required(container_flag), layout(prefered_container), container(c), wndholder(wh) { } + virtual ~SkinEmbedEntry() { } + + StringW groupid; + GUID guid; + api_dependent *dep; + ifc_window *wnd; + int required; + StringW layout; + Container *container; + WindowHolder *wndholder; +}; + +class SkinEmbedder : public DependentViewerI, public TimerClientDI { + public: + + SkinEmbedder(); + virtual ~SkinEmbedder(); + + int toggle(GUID g, const wchar_t *prefered_container=NULL, int container_flag=0, RECT *r=NULL, int transcient=0); + int toggle(const wchar_t *groupid, const wchar_t *prefered_container=NULL, int container_flag=0, RECT *r=NULL, int transcient=0); + ifc_window *create(GUID g, const wchar_t *prefered_container=NULL, int container_flag=0, RECT *r=NULL, int transcient=0, int starthidden=0, int *isnew=NULL); + ifc_window *create(const wchar_t *groupid, const wchar_t *prefered_container=NULL, int container_flag=0, RECT *r=NULL, int transcient=0, int starthidden=0, int *isnew=NULL); + void destroy(ifc_window *w, RECT *r=NULL); + int getNumItems(GUID g); + int getNumItems(const wchar_t *groupid); + ifc_window *enumItem(GUID g, int n); + ifc_window *enumItem(const wchar_t *groupid, int n); + WindowHolder *getSuitableWindowHolder(GUID g, const wchar_t *group_id, Container *cont, Layout *lay, int visible, int dynamic, int empty, int has_self, int autoavail); + void registerWindowHolder(WindowHolder *w); + void unregisterWindowHolder(WindowHolder *w); + void destroyContainer(Container *o); + virtual int timerclient_onDeferredCallback(intptr_t param1, intptr_t param2); + virtual void timerclient_timerCallback(int id); +#ifdef WASABI_COMPILE_CONFIG + void restoreSavedState(); + void saveState(); +#endif + void attachToSkin(ifc_window *w, int side, int size); + + virtual int viewer_onItemDeleted(api_dependent *item); + static void cancelDestroyContainer(Container *c); + + private: + ifc_window *create(GUID g, const wchar_t *groupid, const wchar_t *prefered_container=NULL, int container_flag=0, RECT *r=NULL, int transcient=0, int starthidden=0, int *isnew=NULL); + + PtrList<WindowHolder> wndholders; + PtrList<SkinEmbedEntry> inserted; + PtrList<SkinEmbedEntry> allofthem; + static PtrList<SkinEmbedEntry> in_deferred_callback; + static PtrList<Container> cancel_deferred_destroy; + static PtrList<Container> deferred_destroy; +}; + +extern SkinEmbedder *skinEmbedder; + +#endif diff --git a/Src/Wasabi/api/wndmgr/skinwnd.cpp b/Src/Wasabi/api/wndmgr/skinwnd.cpp new file mode 100644 index 00000000..5ac895a0 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/skinwnd.cpp @@ -0,0 +1,99 @@ +#include <precomp.h> +#include "skinwnd.h" +#include <api/wnd/api_window.h> +#include <api/wnd/wndclass/guiobjwnd.h> +#include <api/script/scriptguid.h> +#include <api/script/objects/c_script/c_group.h> +#include <api/script/objects/c_script/c_layout.h> +#include <api/script/objects/c_script/c_container.h> +#include <api/wnd/wndclass/wndholder.h> + +SkinWnd::SkinWnd(const wchar_t *group_id, const wchar_t *prefered_container, int container_flag, RECT *animated_rect_source, int transcient, int starthidden) +{ + isnew = 0; + wnd = WASABI_API_WNDMGR->skinwnd_createByGroupId(group_id, prefered_container, container_flag, animated_rect_source, transcient, starthidden, &isnew); + notifyMinMaxChanged(); +} + +SkinWnd::SkinWnd(GUID svc_or_group_guid, const wchar_t *prefered_container, int container_flag, RECT *animated_rect_source, int transcient, int starthidden) +{ + isnew = 0; + wnd = WASABI_API_WNDMGR->skinwnd_createByGuid(svc_or_group_guid, prefered_container, container_flag, animated_rect_source, transcient, starthidden, &isnew); + notifyMinMaxChanged(); +} + +SkinWnd::~SkinWnd() +{} + +void SkinWnd::destroy(RECT *animated_rect_dest) +{ + if (wnd == NULL) return ; + if (!isnew) + { + ifc_window *w = wnd->findWindowByInterface(windowHolderGuid); + WindowHolder *wh = static_cast<WindowHolder*>(w->getInterface(windowHolderGuid)); + if (wh != NULL) + { + wh->onRemoveWindow(); + return ; + } + } + WASABI_API_WNDMGR->skinwnd_destroy(wnd, animated_rect_dest); +} + +int SkinWnd::runModal(int center) +{ + if (wnd == NULL) return 0; + ifc_window *w = wnd->getDesktopParent(); + if (center) + { + C_Layout l(getLayout()); + l.center(); + } + w->setVisible(1); + return w->runModal(); +} + +void SkinWnd::endModal(int retcode) +{ + if (wnd == NULL) return ; + wnd->endModal(retcode); +} + +GuiObject *SkinWnd::findObject(const wchar_t *object_id) +{ + if (wnd == NULL) return NULL; + GuiObject *obj = NULL; + obj = static_cast<GuiObject *>(wnd->getInterface(guiObjectGuid)); + return obj->guiobject_findObject(object_id); +} + +ScriptObject *SkinWnd::getContainer() +{ + if (wnd == NULL) return NULL; + ifc_window *dw = wnd->getDesktopParent(); + if (!dw) return NULL; + ScriptObject *o = static_cast<ScriptObject *>(dw->getInterface(scriptObjectGuid)); + if (o != NULL) + { + return C_Layout(o).getContainer(); + } + return NULL; +} + +ScriptObject *SkinWnd::getLayout() +{ + if (wnd == NULL) return NULL; + ifc_window *dw = wnd->getDesktopParent(); + if (!dw) return NULL; + ScriptObject *o = static_cast<ScriptObject *>(dw->getInterface(scriptObjectGuid)); + return o; +} + +void SkinWnd::notifyMinMaxChanged() +{ + if (wnd != NULL) + { + wnd->signalMinMaxEnforcerChanged(); + } +} diff --git a/Src/Wasabi/api/wndmgr/skinwnd.h b/Src/Wasabi/api/wndmgr/skinwnd.h new file mode 100644 index 00000000..e372fb56 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/skinwnd.h @@ -0,0 +1,42 @@ +#ifndef __SKINWND_H +#define __SKINWND_H + +#include <bfc/common.h> +#include "api.h" +#include <api/script/scriptobj.h> + +#define WASABISTDCONTAINER_RESIZABLE_STATUS "resizable_status" +#define WASABISTDCONTAINER_RESIZABLE_NOSTATUS "resizable_nostatus" +#define WASABISTDCONTAINER_STATIC "static" +#define WASABISTDCONTAINER_MODAL "modal" + +#define SKINWND_ATTACH_LEFT 1 +#define SKINWND_ATTACH_TOP 2 +#define SKINWND_ATTACH_RIGHT 3 +#define SKINWND_ATTACH_BOTTOM 4 + +class ifc_window; +class GuiObject; + +class SkinWnd +{ + public: + SkinWnd(GUID svc_or_group_guid, const wchar_t *prefered_container=NULL, int container_flag=0, RECT *animated_rect_source=NULL, int transcient=0, int starthidden=0); + SkinWnd(const wchar_t *group_id, const wchar_t *prefered_container=NULL, int container_flag=0, RECT *animated_rect_source=NULL, int transcient=0, int starthidden=0); + virtual ~SkinWnd(); + void destroy(RECT *animated_rect_dest=NULL); + ifc_window *getWindow() { return wnd; } + ScriptObject *getContainer(); + ScriptObject *getLayout(); + int runModal(int center=0); + void endModal(int retcode); + GuiObject *findObject(const wchar_t *object_id); + void notifyMinMaxChanged(); + int isNewContainer() { return isnew; } + + private: + ifc_window *wnd; + int isnew; +}; + +#endif diff --git a/Src/Wasabi/api/wndmgr/snappnt.cpp b/Src/Wasabi/api/wndmgr/snappnt.cpp new file mode 100644 index 00000000..93ad3df9 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/snappnt.cpp @@ -0,0 +1,181 @@ +#include <precomp.h> +#include "snappnt.h" +#include <api/wndmgr/layout.h> +#include <api/wnd/wndtrack.h> +#include <api/config/items/cfgitem.h> + +SnapPoint::SnapPoint(Layout *l, Container *c) +{ + points.addItem(this); + setParentLayout(l); + setParentContainer(c); +} + +SnapPoint::~SnapPoint() +{ + points.removeItem(this); +} + +void SnapPoint::removeAll() +{ + points.deleteAllSafe(); +} + +int SnapPoint::setXmlParam(const wchar_t *paramname, const wchar_t *strvalue) +{ + if (!WCSICMP(paramname, L"id")) id = strvalue; + else if (!WCSICMP(paramname, L"x")) x = WTOI(strvalue); + else if (!WCSICMP(paramname, L"y")) y = WTOI(strvalue); + else if (!WCSICMP(paramname, L"relatx")) relatx = WTOI(strvalue); + else if (!WCSICMP(paramname, L"relaty")) relaty = WTOI(strvalue); + else return 0; + return 1; +} + +void SnapPoint::setParentLayout(Layout *l) +{ + playout = l; +} + +void SnapPoint::setParentContainer(Container *c) +{ + pcontainer = c; +} + +Container *SnapPoint::getParentContainer() +{ + return pcontainer; +} + +Layout *SnapPoint::getParentLayout() +{ + return playout; +} + +const wchar_t *SnapPoint::getId() +{ + return id; +} + +int SnapPoint::getX() +{ + if (getParentLayout()) + return (int)((double)x * getParentLayout()->getRenderRatio()); + return x; +} + +int SnapPoint::getY() +{ + if (getParentLayout()) + return (int)((double)y * getParentLayout()->getRenderRatio()); + return y; +} + +PtrList<SnapPoint> SnapPoint::points; + +int SnapPoint::match(ifc_window *master, RECT *z, ifc_window *slave, int flag, int *donex, int *doney, int w, int h) +{ + SnapPoint *pmast; + SnapPoint *pslav; + + for (int i = 0;i < points.getNumItems();i++) + if (points.enumItem(i)->getParentLayout() == master) + { + pmast = points.enumItem(i); + for (int j = 0;j < points.getNumItems();j++) + if (points.enumItem(j)->getParentLayout() == slave) + { + pslav = points.enumItem(j); + int r = do_match(pmast, pslav, z, flag, donex, doney, w, h); + if (r) + return 1; + } + } + return 0; +} + +int SnapPoint::do_match(SnapPoint *pmast, SnapPoint *pslav, RECT *z, int mask, int *donex, int *doney, int w, int h) +{ + //#if 0//BU> lone needs to make this work again + //fg> maybe it would have been a good idea to tell me about it... especially since it *works fine* + + ASSERT(pmast); + ASSERT(pslav); + int f = 0; + + if (((mask & KEEPSIZE) == 0) && !z) + { + ASSERTPR(0, "match resize with no rect"); + } + + if (!z) + { // just testing if docked + + if (!WCSICMP(pmast->getId(), pslav->getId())) + { + BaseWnd *wm = pmast->getParentLayout(); + BaseWnd *ws = pslav->getParentLayout(); + if (ws && ws) + { + RECT pmr, psr; + wm->getWindowRect(&pmr); + ws->getWindowRect(&psr); + pmr.left += pmast->relatx ? pmast->getX() : (pmr.right - pmr.left + pmast->getX()); + pmr.top += pmast->relaty ? pmast->getY() : (pmr.bottom - pmr.top + pmast->getY()); + psr.left += pmast->relatx ? pslav->getX() : (psr.right - psr.left + pslav->getX()); + psr.top += pmast->relaty ? pslav->getY() : (psr.bottom - psr.top + pslav->getY()); + if (pmr.left == psr.left && pmr.top == psr.top) + { + if (donex) *donex = 1; + if (doney) *doney = 1; + return 1; + } + } + } + } + else + { + + ASSERT(donex); + ASSERT(doney); + + if (!WCSICMP(pmast->getId(), pslav->getId())) + { + //CUT: BaseWnd *wm = pmast->getParentLayout(); + BaseWnd *ws = pslav->getParentLayout(); + if (ws && ws) + { + RECT pmr, psr, osr, omr; + pmr = omr = *z; + ws->getWindowRect(&psr); + osr = psr; + pmr.left += pmast->relatx ? pmast->getX() : (pmr.right - pmr.left + pmast->getX()); + pmr.top += pmast->relaty ? pmast->getY() : (pmr.bottom - pmr.top + pmast->getY()); + psr.left += pmast->relatx ? pslav->getX() : (psr.right - psr.left + pslav->getX()); + psr.top += pmast->relaty ? pslav->getY() : (psr.bottom - psr.top + pslav->getY()); + if (pmr.left > psr.left - 10 && pmr.left < psr.left + 10 && (mask & LEFT) && ! *donex) + { + *donex = 1; + z->left = omr.left - (pmr.left - psr.left); + if (mask & KEEPSIZE) + z->right = z->left + w; + f++; + } + if (pmr.top > psr.top - 10 && pmr.top < psr.top + 10 && (mask & TOP) && ! *doney) + { + z->top = omr.top - (pmr.top - psr.top); + *doney = 1; + if (mask & KEEPSIZE) + z->bottom = z->top + h; + f++; + } + } + } + + return f > 0; + } + return 0; +} + + + diff --git a/Src/Wasabi/api/wndmgr/snappnt.h b/Src/Wasabi/api/wndmgr/snappnt.h new file mode 100644 index 00000000..997e8fd7 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/snappnt.h @@ -0,0 +1,49 @@ +#ifndef __SNAPPOINT_H +#define __SNAPPOINT_H + +#include <bfc/ptrlist.h> +#include <bfc/string/StringW.h> +#include <api/skin/xmlobject.h> + +#define SNAPPOINT_XMLPARENT XmlObjectI + +class Container; +class Layout; +class SnapPoint; +class ifc_window; + +class SnapPoint : public SNAPPOINT_XMLPARENT { + +public: + SnapPoint(Layout *l, Container *c); + virtual ~SnapPoint(); + + virtual int setXmlParam(const wchar_t *name, const wchar_t *strvalue); + + virtual void setParentContainer(Container *c); + virtual void setParentLayout(Layout *l); + virtual Container *getParentContainer(); + virtual Layout *getParentLayout(); + virtual const wchar_t *getId(); + + virtual int getX(); + virtual int getY(); + + static int match(ifc_window *master, RECT *z, ifc_window *slave, int flag, int *donex, int *doney, int w, int h); + static void removeAll(); + +private: + int x; + int y; + int relatx; + int relaty; + StringW id; + + Container *pcontainer; + Layout *playout; + + static PtrList<SnapPoint> points; + static int do_match(SnapPoint *pmast, SnapPoint *pslav, RECT *z, int mask, int *donex, int *doney, int w, int h); +}; + +#endif
\ No newline at end of file diff --git a/Src/Wasabi/api/wndmgr/wndmgrapi.cpp b/Src/Wasabi/api/wndmgr/wndmgrapi.cpp new file mode 100644 index 00000000..7d77a792 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/wndmgrapi.cpp @@ -0,0 +1,279 @@ +#include <precomp.h> +#include "wndmgrapi.h" +#include <api/wndmgr/autopopup.h> +#include <api/wndmgr/skinembed.h> +#include <api/wndmgr/animate.h> +#include <api/wnd/wndtrack.h> +#include <api/skin/skinparse.h> +#include <api/wndmgr/msgbox.h> +#include <api/util/varmgr.h> + +wndmgr_api *wndManagerApi = NULL; + +WndMgrApi::WndMgrApi() +{ + skinEmbedder = new SkinEmbedder(); + windowTracker = new WindowTracker(); +} + +WndMgrApi::~WndMgrApi() +{ + delete skinEmbedder; + skinEmbedder = NULL; + delete windowTracker; + windowTracker = NULL; +} + +void WndMgrApi::wndTrackAdd(ifc_window *wnd) +{ + if (wnd == NULL) + { + DebugString("wndTrackAdd, illegal param : wnd == NULL\n"); + return ; + } + windowTracker->addWindow(wnd); +} + +void WndMgrApi::wndTrackRemove(ifc_window *wnd) +{ + if (wnd == NULL) + { + DebugString("wndTrackAdd, illegal param : wnd == NULL\n"); + return ; + } + windowTracker->removeWindow(wnd); +} + +bool WndMgrApi::wndTrackDock(ifc_window *wnd, RECT *r, int mask) +{ + return windowTracker->autoDock(wnd, r, mask); +} + +bool WndMgrApi::wndTrackDock2(ifc_window *wnd, RECT *r, RECT *orig_r, int mask) +{ + return windowTracker->autoDock(wnd, r, orig_r, mask); +} + +void WndMgrApi::wndTrackStartCooperative(ifc_window *wnd) +{ + windowTracker->startCooperativeMove(wnd); +} + +void WndMgrApi::wndTrackEndCooperative(void) +{ + windowTracker->endCooperativeMove(); +} + +int WndMgrApi::wndTrackWasCooperative(void) +{ + return windowTracker->wasCooperativeMove(); +} + +void WndMgrApi::wndTrackInvalidateAll() +{ + windowTracker->invalidateAllWindows(); +} + +int WndMgrApi::skinwnd_toggleByGuid(GUID g, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient) +{ + return skinEmbedder->toggle(g, prefered_container, container_flag, sourceanimrect, transcient); +} + +int WndMgrApi::skinwnd_toggleByGroupId(const wchar_t *groupid, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient) +{ + return skinEmbedder->toggle(groupid, prefered_container, container_flag, sourceanimrect, transcient); +} + +ifc_window *WndMgrApi::skinwnd_createByGuid(GUID g, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient, int starthidden, int *isnew) +{ + return skinEmbedder->create(g, prefered_container, container_flag, sourceanimrect, transcient, starthidden, isnew); +} + +ifc_window *WndMgrApi::skinwnd_createByGroupId(const wchar_t *groupid, const wchar_t *prefered_container, int container_flag, RECT *sourceanimrect, int transcient, int starthidden, int *isnew) +{ + return skinEmbedder->create(groupid, prefered_container, container_flag, sourceanimrect, transcient, starthidden, isnew); +} + +void WndMgrApi::skinwnd_destroy(ifc_window *w, RECT *destanimrect) +{ + skinEmbedder->destroy(w, destanimrect); +} + +int WndMgrApi::skinwnd_getNumByGuid(GUID g) +{ + return skinEmbedder->getNumItems(g); +} + +ifc_window *WndMgrApi::skinwnd_enumByGuid(GUID g, int n) +{ + return skinEmbedder->enumItem(g, n); +} + +int WndMgrApi::skinwnd_getNumByGroupId(const wchar_t *groupid) +{ + return skinEmbedder->getNumItems(groupid); +} + +ifc_window *WndMgrApi::skinwnd_enumByGroupId(const wchar_t *groupid, int n) +{ + return skinEmbedder->enumItem(groupid, n); +} + +void WndMgrApi::skinwnd_attachToSkin(ifc_window *w, int side, int size) +{ + skinEmbedder->attachToSkin(w, side, size); +} + +ScriptObject *WndMgrApi::skin_getContainer(const wchar_t *container_name) +{ + Container *c = SkinParser::getContainer(container_name); + if (c != NULL) return c->getScriptObject(); + return NULL; +} + +ScriptObject *WndMgrApi::skin_getLayout(ScriptObject *container, const wchar_t *layout_name) +{ + ASSERT(container != NULL); + Container *c = static_cast<Container *>(container->vcpu_getInterface(containerGuid)); + if (c != NULL) + { + Layout *l = c->getLayout(layout_name); + if (l != NULL) return l->getScriptObject(); + } + return NULL; +} + +void WndMgrApi::wndholder_register(WindowHolder *wh) +{ + skinEmbedder->registerWindowHolder(wh); +} + +void WndMgrApi::wndholder_unregister(WindowHolder *wh) +{ + skinEmbedder->unregisterWindowHolder(wh); +} + +int WndMgrApi::messageBox(const wchar_t *txt, const wchar_t *title, int flags, const wchar_t *not_anymore_identifier, ifc_window *parentwnd) +{ +#ifdef WASABI_WNDMGR_OSMSGBOX + #ifdef WIN32 + + int f = 0; + if (flags & MSGBOX_OK) f |= MB_OK; + if (flags & MSGBOX_CANCEL) f |= MB_OKCANCEL; + if (flags & MSGBOX_YES) f |= MB_YESNO; + if ((flags & MSGBOX_YES) && (flags & MSGBOX_CANCEL)) f |= MB_YESNOCANCEL; + + int r = MessageBoxW(parentwnd ? parentwnd->gethWnd() : NULL, txt, title, f); + + if (r == IDOK) r = MSGBOX_OK; + if (r == IDCANCEL) r = MSGBOX_CANCEL; + if (r == IDYES) r = MSGBOX_YES; + if (r == IDNO) r = MSGBOX_NO; + + return r; + +#else + // port me! +#endif +#else + MsgBox _mb(txt, title, flags, not_anymore_identifier); + return _mb.run(); +#endif +} + +void WndMgrApi::drawAnimatedRects(const RECT *r1, const RECT *r2) +{ + if (r1 == NULL) + { + DebugString("drawAnimatedRects, illegal param : r1 == NULL\n"); + return ; + } + if (r2 == NULL) + { + DebugString("drawAnimatedRects, illegal param : r2 == NULL\n"); + return ; + } + AnimatedRects::draw(r1, r2); +} + +int WndMgrApi::autopopup_registerGuid(GUID g, const wchar_t *desc, const wchar_t *prefered_container, int container_flag) +{ + return AutoPopup::registerGuid(SKINPARTID_NONE, g, desc, prefered_container, container_flag); +} + +int WndMgrApi::autopopup_registerGroupId(const wchar_t *groupid, const wchar_t *desc, const wchar_t *prefered_container, int container_flag) +{ + return AutoPopup::registerGroupId(SKINPARTID_NONE, groupid, desc, prefered_container, container_flag); +} + +void WndMgrApi::autopopup_unregister(int id) +{ + AutoPopup::unregister(id); +} + +int WndMgrApi::autopopup_getNumGuids() +{ + return AutoPopup::getNumGuids(); +} + +GUID WndMgrApi::autopopup_enumGuid(int n) +{ + return AutoPopup::enumGuid(n); +} + +int WndMgrApi::autopopup_getNumGroups() +{ + return AutoPopup::getNumGroups(); +} + +const wchar_t *WndMgrApi::autopopup_enumGroup(int n) +{ + return AutoPopup::enumGroup(n); +} + +const wchar_t *WndMgrApi::autopopup_enumGuidDescription(int n) +{ + return AutoPopup::enumGuidDescription(n); +} + +const wchar_t *WndMgrApi::autopopup_enumGroupDescription(int n) +{ + return AutoPopup::enumGroupDescription(n); +} + +const wchar_t *WndMgrApi::varmgr_translate(const wchar_t *str) +{ + StringW *s = PublicVarManager::translate_nocontext(str); + if (s) + { + ret.swap(s); + delete s; + return ret.getValueSafe(); + } + return str; +} + +Stack<ifc_window*> WndMgrApi::modal_wnd_stack; + +ifc_window *WndMgrApi::getModalWnd() +{ + if (!modal_wnd_stack.peek()) return NULL; + return modal_wnd_stack.top(); +} + +void WndMgrApi::pushModalWnd(ifc_window *wnd) +{ + modal_wnd_stack.push(wnd); +} + +void WndMgrApi::popModalWnd(ifc_window *wnd) +{ + if (getModalWnd() != wnd) return ; + modal_wnd_stack.pop(); +} + +Container *WndMgrApi::newDynamicContainer(const wchar_t *name, int transcient) +{ + return SkinParser::newDynamicContainer(name, transcient); +} diff --git a/Src/Wasabi/api/wndmgr/wndmgrapi.h b/Src/Wasabi/api/wndmgr/wndmgrapi.h new file mode 100644 index 00000000..88637d49 --- /dev/null +++ b/Src/Wasabi/api/wndmgr/wndmgrapi.h @@ -0,0 +1,59 @@ +#ifndef __APIWNDMGR_H +#define __APIWNDMGR_H + +#include <api/wndmgr/api_wndmgr.h> +#include <bfc/stack.h> +#include <bfc/string/StringW.h> + +class WndMgrApi : public wndmgr_apiI { + public: + WndMgrApi(); + virtual ~WndMgrApi(); + + virtual void wndTrackAdd(ifc_window *wnd); + virtual void wndTrackRemove(ifc_window *wnd); + virtual bool wndTrackDock(ifc_window *wnd, RECT *r, int mask); + virtual bool wndTrackDock2(ifc_window *wnd, RECT *r, RECT *orig_r, int mask); + virtual void wndTrackStartCooperative(ifc_window *wnd); + virtual void wndTrackEndCooperative(); + virtual int wndTrackWasCooperative(); + virtual void wndTrackInvalidateAll(); + virtual int skinwnd_toggleByGuid(GUID g, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0); + virtual int skinwnd_toggleByGroupId(const wchar_t *groupid, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0); + virtual ifc_window *skinwnd_createByGuid(GUID g, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0, int starthidden = 0, int *isnew=NULL); + virtual ifc_window *skinwnd_createByGroupId(const wchar_t *groupid, const wchar_t *prefered_container = NULL, int container_flag = 0, RECT *sourceanimrect = NULL, int transcient = 0, int starthidden = 0, int *isnew=NULL); + virtual void skinwnd_destroy(ifc_window *w, RECT *destanimrect = NULL); + virtual int skinwnd_getNumByGuid(GUID g); + virtual ifc_window *skinwnd_enumByGuid(GUID g, int n); + virtual int skinwnd_getNumByGroupId(const wchar_t *groupid); + virtual ifc_window *skinwnd_enumByGroupId(const wchar_t *groupid, int n); + virtual void skinwnd_attachToSkin(ifc_window *w, int side, int size); + virtual ScriptObject *skin_getContainer(const wchar_t *container_name); + virtual ScriptObject *skin_getLayout(ScriptObject *container, const wchar_t *layout_name); + virtual void wndholder_register(WindowHolder *wh); + virtual void wndholder_unregister(WindowHolder *wh); + virtual int messageBox(const wchar_t *txt, const wchar_t *title, int flags, const wchar_t *not_anymore_identifier, ifc_window *parenwnt); + virtual ifc_window *getModalWnd(); + virtual void pushModalWnd(ifc_window *w = MODALWND_NOWND); + virtual void popModalWnd(ifc_window *w = MODALWND_NOWND); + virtual void drawAnimatedRects(const RECT *r1, const RECT *r2); + virtual int autopopup_registerGuid(GUID g, const wchar_t *desc, const wchar_t *prefered_container = NULL, int container_flag = 0); + virtual int autopopup_registerGroupId(const wchar_t *groupid, const wchar_t *desc, const wchar_t *prefered_container = NULL, int container_flag = 0); + virtual void autopopup_unregister(int id); + virtual int autopopup_getNumGuids(); + virtual GUID autopopup_enumGuid(int n); + virtual int autopopup_getNumGroups(); + virtual const wchar_t *autopopup_enumGroup(int n); + virtual const wchar_t *varmgr_translate(const wchar_t *str); + virtual Container *newDynamicContainer(const wchar_t *name, int transcient); + virtual const wchar_t *autopopup_enumGuidDescription(int n); + virtual const wchar_t *autopopup_enumGroupDescription(int n); + + private: + + static Stack<ifc_window*> modal_wnd_stack; + StringW ret; +}; + + +#endif // __APIWNDMGR_H |