winamp/Src/Wasabi/api/wnd/virtualwnd.cpp
2024-09-24 14:54:57 +02:00

672 lines
12 KiB
C++

#include <precomp.h>
#include "virtualwnd.h"
#include <tataki/region/api_region.h>
#include <api/wnd/usermsg.h>
#include <api/wnd/accessible.h>
VirtualWnd::VirtualWnd()
{
virtualX = virtualY = virtualH = virtualW = 0;
bypassvirtual = 0;
focus = 0;
resizecount = 0;
lastratio = 1;
}
VirtualWnd::~VirtualWnd()
{}
int VirtualWnd::init(ifc_window *parWnd, int nochild)
{
if (!bypassvirtual)
setParent(parWnd);
return (VIRTUALWND_PARENT::init(parWnd, nochild));
}
int VirtualWnd::init(OSMODULEHANDLE moduleHandle, OSWINDOWHANDLE parent, int nochild)
{
if (!bypassvirtual)
{
ASSERTPR(getParent() != NULL, "Virtual window created without specifying BaseWnd parent");
if (getStartHidden())
this_visible = 0;
else
this_visible = 1;
onInit();
onPostOnInit();
if (isVisible())
onSetVisible(1);
return 1;
}
else
return VIRTUALWND_PARENT::init(moduleHandle, parent, nochild);
}
OSWINDOWHANDLE VirtualWnd::getOsWindowHandle()
{
// ASSERTPR(getParent() != NULL, "Virtual window used as base parent !");
if (!bypassvirtual)
{
if (!getParent())
return INVALIDOSWINDOWHANDLE;
return getParent()->getOsWindowHandle();
}
else
{
return VIRTUALWND_PARENT::getOsWindowHandle();
}
}
OSMODULEHANDLE VirtualWnd::getOsModuleHandle()
{
if (!bypassvirtual)
{
if (!getParent())
return INVALIDOSMODULEHANDLE;
return getParent()->getOsModuleHandle();
}
else
return VIRTUALWND_PARENT::getOsModuleHandle();
}
void VirtualWnd::resize(RECT *r, int wantcb)
{
if (!bypassvirtual)
{
resize(r->left, r->top, r->right - r->left, r->bottom - r->top, wantcb);
}
else
{
VIRTUALWND_PARENT::resize( r, wantcb );
//virtualX = rx;
//virtualY = ry;
//virtualW = rwidth;
//virtualH = rheight;
}
}
// fg> the resizecount > 1 is a hack, it should be 0 but i need more time to fix this thing, at least this way we don't lose the optim
void VirtualWnd::resize(int x, int y, int w, int h, int wantcb)
{
if (!bypassvirtual)
{
if (x == NOCHANGE)
x = virtualX;
if (y == NOCHANGE)
y = virtualY;
if (w == NOCHANGE)
w = virtualW;
if (h == NOCHANGE)
h = virtualH;
double thisratio = getRenderRatio();
if (resizecount > 1 && virtualX == x && virtualY == y && virtualW == w && virtualH == h && lastratio == thisratio)
return ;
lastratio = thisratio;
if (isVisible())
{
RECT r;
getNonClientRect(&r);
invalidateRect(&r);
}
virtualX = x;
virtualY = y;
virtualW = w;
virtualH = h;
if (isVisible())
{
RECT r;
getNonClientRect(&r);
invalidateRect(&r);
}
setRSize(x, y, w, h);
if (wantcb && isPostOnInit())
{
resizecount = MIN(resizecount + 1, 2);
onResize();
}
}
else
{
VIRTUALWND_PARENT::resize( x, y, w, h, wantcb );
//virtualX = rx;
//virtualY = ry;
//virtualW = rwidth;
//virtualH = rheight;
}
}
//CUTvoid VirtualWnd::resize(RECT *r) {
//CUT resize(r->left, r->top, r->right-r->left, r->bottom-r->top);
//CUT}
void VirtualWnd::move(int x, int y)
{
//DebugStringW( L"VirtualWnd::move( x = %d, y = %d )\n", x, y );
if (!bypassvirtual)
{
if (isVisible())
{
RECT r;
getNonClientRect(&r);
invalidateRect(&r);
}
virtualX = x;
virtualY = y;
if (isVisible())
{
RECT r;
getNonClientRect(&r);
invalidateRect(&r);
}
}
else
{
VIRTUALWND_PARENT::move( x, y );
//virtualX = x;
//virtualY = y;
}
}
void VirtualWnd::invalidate()
{
if (!bypassvirtual)
{
if (!getRootParent()) return ;
RECT r(clientRect());
getRootParent()->invalidateRectFrom(&r, this);
// VIRTUALWND_PARENT::invalidate();
}
else
VIRTUALWND_PARENT::invalidate();
}
void VirtualWnd::invalidateRect(RECT *r)
{
if (!bypassvirtual)
{
if (!getRootParent()) return ;
getRootParent()->invalidateRectFrom(r, this);
}
else
VIRTUALWND_PARENT::invalidateRect(r);
}
void VirtualWnd::invalidateRgn(api_region *reg)
{
if (!bypassvirtual)
{
if (!getRootParent()) return ;
getRootParent()->invalidateRgnFrom(reg, this);
}
else
VIRTUALWND_PARENT::invalidateRgn(reg);
}
void VirtualWnd::validate()
{
if (!bypassvirtual)
{
if (!getRootParent()) return ;
RECT r;
getClientRect(&r);
getRootParent()->validateRect(&r);
}
else
VIRTUALWND_PARENT::validate();
}
void VirtualWnd::validateRect(RECT *r)
{
if (!bypassvirtual)
{
if (!getRootParent())
return ;
getRootParent()->validateRect(r);
}
else
VIRTUALWND_PARENT::validateRect( r );
}
void VirtualWnd::validateRgn(api_region *reg)
{
if (!bypassvirtual)
{
if (!getRootParent()) return ;
getRootParent()->validateRgn(reg);
}
else
VIRTUALWND_PARENT::validateRgn(reg);
}
void VirtualWnd::getClientRect(RECT *rect)
{
if (!bypassvirtual)
{
// CT:getClientRect behaves differently here for virtual windows
// so we can use onPaint directly on the destination canvas
// without using another temporary canvas.
Wasabi::Std::setRect(rect, virtualX, virtualY, virtualX + virtualW, virtualY + virtualH);
// rect->left=0; rect->right=virtualW;
// rect->top=0; rect->bottom=virtualH;
}
else
VIRTUALWND_PARENT::getClientRect(rect);
}
void VirtualWnd::getNonClientRect(RECT *rect)
{
VirtualWnd::getClientRect(rect);
}
void VirtualWnd::getWindowRect(RECT *rect)
{
if (!bypassvirtual)
{
RECT a;
getRootParent()->getWindowRect(&a);
int x = virtualX, y = virtualY, w = virtualW, h = virtualH;
if (renderRatioActive())
{
multRatio(&x, &y);
multRatio(&w, &h);
}
rect->left = a.left + x; rect->right = rect->left + w;
rect->top = a.top + y; rect->bottom = rect->top + h;
}
else
VIRTUALWND_PARENT::getWindowRect(rect);
}
int VirtualWnd::beginCapture()
{
if (!bypassvirtual)
{
disable_tooltip_til_recapture = 0;
getRootParent()->setVirtualChildCapture(this);
return 1;
}
else
return VIRTUALWND_PARENT::beginCapture();
}
int VirtualWnd::endCapture()
{
if (!bypassvirtual)
{
if (getRootParent() == NULL) return 0;
getRootParent()->setVirtualChildCapture(NULL);
return 1;
}
else
return VIRTUALWND_PARENT::endCapture();
}
int VirtualWnd::getCapture()
{
if (!bypassvirtual)
{
if (getRootParent() == NULL) return 0;
return getRootParent()->getVirtualChildCapture() == this;
}
else
return VIRTUALWND_PARENT::getCapture();
}
void VirtualWnd::setVirtualChildCapture(BaseWnd *child)
{
if (!bypassvirtual)
{
getParent()->setVirtualChildCapture(child);
}
else
VIRTUALWND_PARENT::setVirtualChildCapture(child);
}
// eek
void VirtualWnd::repaint()
{
if (!bypassvirtual)
{
if (!getParent()) return ;
getParent()->repaint();
}
else
VIRTUALWND_PARENT::repaint();
}
/*int VirtualWnd::focusNextSibbling(int dochild) {
return 1;
}
int VirtualWnd::focusNextVirtualChild(BaseWnd *child) {
return 1;
}*/
int VirtualWnd::cascadeRepaint(int pack)
{
if (!bypassvirtual)
{
if (getRootParent())
{
RECT r;
VirtualWnd::getNonClientRect(&r);
getRootParent()->cascadeRepaintRectFrom(&r, this, pack);
}
return 1;
}
else
return VIRTUALWND_PARENT::cascadeRepaint(pack);
}
int VirtualWnd::cascadeRepaintRect(RECT *r, int pack)
{
if (!bypassvirtual)
{
if (getRootParent())
{
getRootParent()->cascadeRepaintRectFrom(r, this, pack);
}
return 1;
}
else
return VIRTUALWND_PARENT::cascadeRepaintRect(r, pack);
}
int VirtualWnd::cascadeRepaintRgn(api_region *r, int pack)
{
if (!bypassvirtual)
{
if (getRootParent())
{
getRootParent()->cascadeRepaintRgnFrom(r, this, pack);
}
return 1;
}
else
return VIRTUALWND_PARENT::cascadeRepaintRgn(r, pack);
}
/*api_window *VirtualWnd::getWindowBehindMyself(int x, int y) {
RECT r;
if (!bypassvirtual) {
if (!getParent()) return NULL;
int n = getParent()->getNumVirtuals();
api_window *c = NULL;
for (int i=n-1;i>=0;i++) {
c = getParent()->getVirtualChild(i);
if (c == this) break;
}
i--;
if (i < 0) return getParent();
for (;i>=0; i--) {
c = getParent()->getVirtualChild(i);
c->getNonClientRect(&r);
if (x>=r.left&&x<=r.right&&y>=r.top&&y<=r.bottom)
return c;
}
return getParent();
} else
return NULL;
}*/
ifc_window *VirtualWnd::rootWndFromPoint(POINT *pt)
{
if (!bypassvirtual)
{
if (!getParent()) return NULL;
return getParent()->rootWndFromPoint(pt);
}
else
return VIRTUALWND_PARENT::rootWndFromPoint(pt);
}
double VirtualWnd::getRenderRatio()
{
if (!bypassvirtual)
{
if (!getParent()) return 1.0;
return getParent()->getRenderRatio();
}
else
return VIRTUALWND_PARENT::getRenderRatio();
}
void VirtualWnd::bringToFront()
{
if (!bypassvirtual)
{
if (!getParent()) return ;
//getParent()->bringVirtualToFront(this); TODO: FIX!!!
}
else
VIRTUALWND_PARENT::bringToFront();
}
void VirtualWnd::bringToBack()
{
if (!bypassvirtual)
{
if (!getParent()) return ;
//getParent()->bringVirtualToBack(this); TODO: FIX!!!
}
else
VIRTUALWND_PARENT::bringToBack();
}
void VirtualWnd::bringAbove(BaseWnd *o)
{
if (!bypassvirtual)
{
if (!getParent()) return ;
getParent()->bringVirtualAbove(this, o);
} /* else
VIRTUALWND_PARENT::bringAbove();*/
}
void VirtualWnd::bringBelow(BaseWnd *o)
{
if (!bypassvirtual)
{
if (!getParent()) return ;
getParent()->bringVirtualBelow(this, o);
} /* else
VIRTUALWND_PARENT::bringBelow();*/
}
int VirtualWnd::reparent(ifc_window *newparent)
{
if (!bypassvirtual)
{
if (getParent())
getParent()->unregisterRootWndChild(this);
parentWnd = NULL;
newparent->registerRootWndChild(this);
onSetParent(newparent);
newparent->invalidate();
return 1;
}
else
{
return VIRTUALWND_PARENT::reparent(newparent);
}
}
int VirtualWnd::setVirtual(int i)
{
// ASSERT(!isInited()); // cut
if (isInited()) return 0;
bypassvirtual = !i;
return 1;
}
ifc_window *VirtualWnd::getRootParent()
{
if (!bypassvirtual)
{
if (!getParent()) return NULL;
ifc_window *t = this;
while (t->isVirtual())
{
if (!t->getParent()) return NULL;
t = t->getParent();
}
return t;
}
else
{
return VIRTUALWND_PARENT::getRootParent();
}
}
int VirtualWnd::gotFocus()
{
if (!bypassvirtual)
return focus;
else
return VIRTUALWND_PARENT::gotFocus();
}
int VirtualWnd::onGetFocus()
{
if (!bypassvirtual)
{
focus = 1;
getRootParent()->onSetRootFocus(this);
invalidate();
Accessible *a = getAccessibleObject();
if (a != NULL)
a->onGetFocus();
}
else
return VIRTUALWND_PARENT::onGetFocus();
return 1;
}
int VirtualWnd::onKillFocus()
{
if (!bypassvirtual)
{
focus = 0;
invalidate();
}
else
return VIRTUALWND_PARENT::onKillFocus();
return 1;
}
void VirtualWnd::setFocus()
{
ifc_window *f = this;
if (!f->wantFocus() && f->getParent())
{
while (f)
{
ifc_window *rp = f->getRootParent();
if (rp == f) rp = f->getParent();
f = rp;
if (f && (!f->getParent() || f->wantFocus() || f == WASABI_API_WND->main_getRootWnd()))
{
f->setFocus();
break;
}
}
}
else
{
if (!bypassvirtual)
{
if (getParent())
{
getParent()->setVirtualChildFocus(this);
}
}
else
VIRTUALWND_PARENT::setFocus();
}
}
void VirtualWnd::setVirtualChildFocus(ifc_window *child)
{
if (!bypassvirtual)
{
getParent()->setVirtualChildFocus(child);
}
else
VIRTUALWND_PARENT::setVirtualChildFocus(child);
}
int VirtualWnd::onActivate()
{
if (bypassvirtual)
return VIRTUALWND_PARENT::onActivate();
return 1;
}
int VirtualWnd::onDeactivate()
{
if (bypassvirtual)
return VIRTUALWND_PARENT::onDeactivate();
return 1;
}
void VirtualWnd::setAllowDeactivation(int allow)
{
ifc_window *w = getDesktopParent();
if (w != NULL && w != this)
w->setAllowDeactivation(allow);
else VIRTUALWND_PARENT::setAllowDeactivation(allow);
}
int VirtualWnd::allowDeactivation()
{
ifc_window *w = getDesktopParent();
if (w != NULL && w != this)
return w->allowDeactivation();
return VIRTUALWND_PARENT::allowDeactivation();
}
/* todo: setCursor
+ real childs going invisible should deferedInvalidate their rect on their parent window if it has a virtualCanvas
*/
// No need for screenToClient/clientToScreen overrides since the virtual's origin is the same as it's parent