#include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include // for HDROP #endif #include #define DESKTOPALPHA #define REFRESH_RATE 25 #define DRAWTIMERID 125 #include #include #include #include #include #include #include #include #include #include #include #include namespace Agave { #include "../Agave/Config/api_config.h" } //#define TIP_TIMER_ID 1601 #define TIP_DESTROYTIMER_ID 1602 #define TIP_AWAY_ID 1603 #define TIP_AWAY_DELAY 100 #define TIP_TIMER_THRESHOLD 350 #define TIP_LENGTH 3000 #define VCHILD_TIMER_ID_MIN 2000 #define VCHILD_TIMER_ID_MAX 2100 #define BUFFEREDMSG_TIMER_ID 1604 #define DEFERREDCB_INVALIDATE 0x201 // move to .h #define DEFERREDCB_FOCUSFIRST 0x202 // move to .h #define DC_KILLGHOST 0x204 #ifdef _WIN32 #define WM_DEFER_CALLBACK (WM_USER+0x333) #endif class DragSet : public PtrList, public NamedW {}; //CUT? static void register_wndClass(HINSTANCE); //CUT? #define ROOTSTRING "RootWnd" //CUT? #define BASEWNDCLASSNAME "BaseWindow_" ROOTSTRING #ifndef WM_MOUSEWHEEL #define WM_MOUSEWHEEL 0x20A #endif static ifc_window *stickyWnd; static RECT sticky; static UINT WINAMP_WM_DIRECT_MOUSE_WHEEL = WM_NULL; /*api_window *api_window::rootwndFromPoint(POINT &point, int level) { api_window *wnd; wnd = WASABI_API_WND->rootWndFromPoint(&point); return api_window::rootwndFromRootWnd(wnd, level, &point); } api_window *api_window::rootwndFromRootWnd(api_window *wnd, int level, POINT *point) { for (;;) { if (wnd == NULL || level < 0) return NULL; if (point) { RECT r; wnd->getWindowRect(&r); if (!PtInRect(&r, *point)) return NULL; // PORT ME } if (level == 0) return wnd; wnd = wnd->getRootWndParent(); level--; } // should never get here }*/ static BOOL DisabledWindow_OnMouseClick(HWND hwnd) { DWORD windowStyle = (DWORD)GetWindowLongPtrW(hwnd, GWL_STYLE); if (WS_DISABLED != ((WS_CHILD | WS_DISABLED) & windowStyle)) return FALSE; HWND hActive = GetActiveWindow(); HWND hPopup = GetWindow(hwnd, GW_ENABLEDPOPUP); BOOL beepOk = (hPopup == hActive || hwnd == GetWindow(hActive, GW_OWNER)); if (!beepOk && NULL == hPopup) { for (HWND hWalker = hwnd; ;) { hWalker = GetWindow(hWalker, GW_OWNER); if (NULL == hWalker || (0 != (WS_CHILD & GetWindowLongPtrW(hWalker, GWL_STYLE)))) break; if (hActive == GetWindow(hWalker, GW_ENABLEDPOPUP)) { beepOk = TRUE; break; } } } if (beepOk) { static const GUID accessibilityConfigGroupGUID = { 0xe2e7f4a, 0x7c51, 0x478f, { 0x87, 0x74, 0xab, 0xbc, 0xf6, 0xd5, 0xa8, 0x57 } }; #define GetBoolConfig(__group, __itemName, __default)\ ((NULL != (__group)) && NULL != (item = group->GetItem(__itemName)) ? item->GetBool() : (__default)) waServiceFactory *serviceFactory = WASABI_API_SVC->service_getServiceByGuid(Agave::AgaveConfigGUID); Agave::api_config *config = (NULL != serviceFactory) ? (Agave::api_config *)serviceFactory->getInterface() : NULL; Agave::ifc_configgroup *group = (NULL != config) ? config->GetGroup(accessibilityConfigGroupGUID) : NULL; Agave::ifc_configitem *item; if (GetBoolConfig(group, L"modalflash", true)) { FLASHWINFO flashInfo; flashInfo.cbSize = sizeof(FLASHWINFO); flashInfo.hwnd = hActive; flashInfo.dwFlags = FLASHW_CAPTION; flashInfo.uCount = 2; flashInfo.dwTimeout = 100; FlashWindowEx(&flashInfo); } if (GetBoolConfig(group, L"modalbeep", false)) MessageBeep(MB_OK); if (NULL != config) serviceFactory->releaseInterface(config); } else { for (HWND hWalker = hwnd; NULL == hPopup;) { hWalker = GetWindow(hWalker, GW_OWNER); if (NULL == hWalker || (0 != (WS_CHILD & GetWindowLongPtrW(hWalker, GWL_STYLE)))) break; hPopup = GetWindow(hWalker, GW_ENABLEDPOPUP); } SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE); if (NULL != hPopup && hPopup != hwnd) { BringWindowToTop(hPopup); SetActiveWindow(hPopup); } } return TRUE; } int WndWatcher::viewer_onItemDeleted(ifc_dependent *item) { if (item == dep) { dep = NULL; watcher->wndwatcher_onDeleteWindow(watched); watched = NULL; } return 1; } BaseWnd::BaseWnd() { uiwaslocked = 0; m_takenOver = 0; rootfocus = NULL; rootfocuswatcher.setWatcher(this); alwaysontop = 0; customdefaultcursor = NULL; preventcancelcapture = 0; ratiolinked = 1; deleting = 0; hinstance = NULL; hwnd = NULL; parentWnd = NULL; dragging = 0; prevtarg = NULL; inputCaptured = 0; btexture = NULL; postoninit = 0; inited = 0; skipnextfocus = 0; ncb = FALSE; accessible = NULL; tooltip = NULL; tip_done = FALSE; tipshowtimer = FALSE; tipawaytimer = FALSE; tipdestroytimer = FALSE; start_hidden = 0; notifyWindow = NULL; lastClick[0] = 0; lastClick[1] = 0; lastClickP[0].x = 0; lastClickP[0].y = 0; lastClickP[1].x = 0; lastClickP[1].y = 0; destroying = FALSE; curVirtualChildCaptured = NULL; curVirtualChildFocus = NULL; virtualCanvas = NULL; virtualCanvasH = virtualCanvasW = 0; deferedInvalidRgn = NULL; hasfocus = 0; focus_on_click = 1; lastnullregion = 0; ratio = 1; lastratio = 1; rwidth = rheight = 0; skin_id = -1; wndalpha = 255; activealpha = 255; inactivealpha = 255; w2k_alpha = 0; //FUCKO scalecanvas = NULL; clickthrough = 0; mustquit = 0; returnvalue = 0; notifyid = 0; cloaked = 0; disable_tooltip_til_recapture = 0; subtractorrgn = NULL; composedrgn = NULL; wndregioninvalid = 1; regionop = REGIONOP_NONE; rectrgn = 1; need_flush_cascaderepaint = 0; deferedCascadeRepaintRgn = NULL; this_visible = 0; this_enabled = 1; renderbasetexture = 0; oldCapture = NULL; my_guiobject = NULL; want_autoresize_after_init = 0; resizecount = 0; suggested_w = 320; suggested_h = 200; maximum_w = maximum_h = AUTOWH; minimum_w = minimum_h = AUTOWH; rx = 0; ry = 0; rwidth = 0; rheight = 0; allow_deactivate = 1; minimized = 0; inonresize = 0; #ifndef WA3COMPATIBILITY m_target = NULL; #endif nodoubleclick = noleftclick = norightclick = nomousemove = nocontextmnu = 0; focusEventsEnabled = 1; maximized = 0; MEMSET(&restore_rect, 0, sizeof(RECT)); ghostbust = 0; lastActiveWnd = NULL; } BaseWnd::~BaseWnd() { //ASSERT(virtualChildren.getNumItems() == 0); childtabs.deleteAll(); if (WASABI_API_WND && WASABI_API_WND->getModalWnd() == this) WASABI_API_WND->popModalWnd(this); destroying = TRUE; curVirtualChildFocus = NULL; #ifdef _WIN32 if (inputCaptured && GetCapture() == getOsWindowHandle()) ReleaseCapture(); #else #warning port me #endif for (int i = 0;i < ghosthwnd.getNumItems();i++) Wasabi::Std::Wnd::destroyWnd(ghosthwnd.enumItem(i)); if (hwnd != NULL && !m_takenOver) { #ifdef URLDROPS if (acceptExternalDrops()) Wasabi::Std::Wnd::revokeDragNDrop(hwnd /*, &m_target*/); #else #ifndef WA3COMPATIBILITY if (m_target != NULL) { Wasabi::Std::Wnd::revokeDragNDrop(hwnd); } #endif #endif int popact = !wantActivation(); if (popact) WASABI_API_WND->appdeactivation_push_disallow(this); Wasabi::Std::Wnd::destroyWnd(hwnd); if (popact) WASABI_API_WND->appdeactivation_pop_disallow(this); } deleteFrameBuffer(virtualCanvas); virtualCanvas = NULL; delete scalecanvas; scalecanvas = NULL; resetDragSet(); notifyParent(ChildNotify::DELETED); if (tipdestroytimer) killTimer(TIP_DESTROYTIMER_ID); if (tipshowtimer) { // TODO: on the mac, use CreateMouseTrackingRegion TRACKMOUSEEVENT tracker; tracker.cbSize=sizeof(tracker); tracker.dwFlags = TME_HOVER|TME_CANCEL; tracker.hwndTrack = this->getOsWindowHandle(); tracker.dwHoverTime = TIP_TIMER_THRESHOLD; TrackMouseEvent(&tracker); } if (tipawaytimer) killTimer(TIP_AWAY_ID); destroyTip(); delete tooltip; if (uiwaslocked) killTimer(BUFFEREDMSG_TIMER_ID); if (deferedInvalidRgn) delete deferedInvalidRgn; delete composedrgn; delete subtractorrgn; delete deferedCascadeRepaintRgn; if (parentWnd != NULL) parentWnd->unregisterRootWndChild(this); if (!m_takenOver && WASABI_API_WND) WASABI_API_WND->unregisterRootWnd(this); hwnd = NULL; } int BaseWnd::init(ifc_window *parWnd, int nochild) { if (parWnd == NULL) return 0; OSWINDOWHANDLE phwnd = parWnd->getOsWindowHandle(); ASSERT(phwnd != NULL); parentWnd = parWnd; // set default parent wnd int ret = init(parWnd->getOsModuleHandle(), phwnd, nochild); if (!ret) parentWnd = NULL; // abort return ret; } int BaseWnd::init(OSMODULEHANDLE moduleHandle, OSWINDOWHANDLE parent, int nochild) { RECT r; int w, h; ASSERTPR(getOsWindowHandle() == NULL, "don't you double init you gaybag"); hinstance = moduleHandle; #ifdef _WIN32 ASSERT(hinstance != NULL); #endif //CUT register_wndClass(hinstance); if (parent != NULL) { Wasabi::Std::Wnd::getClientRect(parent, &r); } else { Wasabi::Std::setRect(&r, 0, 0, getPreferences(SUGGESTED_W), getPreferences(SUGGESTED_H)); } w = (r.right - r.left); h = (r.bottom - r.top); rwidth = w; rheight = h; rx = r.left; ry = r.top; int popact = !wantActivation(); if (popact) WASABI_API_WND->appdeactivation_push_disallow(this); //CUThwnd = createWindow(r.left, r.top, w, h, nochild, parent, hinstance); hwnd = Wasabi::Std::Wnd::createWnd(&r, nochild, acceptExternalDrops(), parent, hinstance, static_cast(this)); #ifdef __APPLE__ #warning remove me Wasabi::Std::Wnd::showWnd(hwnd); #endif if (popact) WASABI_API_WND->appdeactivation_pop_disallow(this); //ASSERT(hwnd != NULL); // lets fail nicely, this could happen for some win32 reason, we don't want to fail the whole app for it, so lets just fail the wnd if (hwnd == NULL) return 0; if (wantActivation()) bringToFront(); //CUT nreal++; //FUCKO #ifdef _WIN32 // PORT ME #ifdef URLDROPS if (acceptExternalDrops()) RegisterDragDrop(hwnd, &m_target); #else #ifndef WA3COMPATIBILITY if (!m_target && WASABI_API_WND != NULL) m_target = WASABI_API_WND->getDefaultDropTarget(); if (m_target != NULL) { RegisterDragDrop(hwnd, (IDropTarget *)m_target); } #endif #endif #endif this_visible = 0; onInit(); this_visible = !start_hidden; onPostOnInit(); return 1; } #ifndef WA3COMPATIBILITY void BaseWnd::setDropTarget(void *dt) { #ifdef _WIN32 if (isVirtual()) return ; if (isInited() && m_target != NULL) { Wasabi::Std::Wnd::revokeDragNDrop(getOsWindowHandle()); m_target = NULL; } m_target = dt; if (m_target != NULL && isInited()) { RegisterDragDrop(gethWnd(), (IDropTarget *)m_target); } #else #warning port me #endif } void *BaseWnd::getDropTarget() { return m_target; } #endif int BaseWnd::onInit() { const wchar_t *s = getName(); if (s != NULL) setOSWndName(s); inited = 1; if (getParent()) getParent()->registerRootWndChild(this); if (WASABI_API_WND != NULL) WASABI_API_WND->registerRootWnd(this); #ifdef _WIN32 if (!Wasabi::Std::Wnd::isDesktopAlphaAvailable()) w2k_alpha = 0; //FUCKO if (w2k_alpha) { setLayeredWindow(1); } if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL) WINAMP_WM_DIRECT_MOUSE_WHEEL = RegisterWindowMessageW(L"WINAMP_WM_DIRECT_MOUSE_WHEEL"); #endif return 0; } int BaseWnd::onPostOnInit() { postoninit = 1; // from now on, isInited() returns 1; if (want_autoresize_after_init) onResize(); else invalidateWindowRegion(); if (isVisible()) onSetVisible(1); if (getTabOrder() == -1) setAutoTabOrder(); ifc_window *dp = getDesktopParent(); if ((dp == NULL || dp == this) && WASABI_API_TIMER != NULL) postDeferredCallback(DEFERREDCB_FOCUSFIRST, 0, 500); return 0; } void BaseWnd::setLayeredWindow(int i) { if (!Wasabi::Std::Wnd::isValidWnd(getOsWindowHandle())) return ; if (!isInited()) return ; Wasabi::Std::Wnd::setLayeredWnd(getOsWindowHandle(), i); #if 0//CUT if (i) { SetWindowLong(getOsWindowHandle(), GWL_EXSTYLE, GetWindowLong(getOsWindowHandle(), GWL_EXSTYLE) & ~WS_EX_LAYERED); SetWindowLong(getOsWindowHandle(), GWL_EXSTYLE, GetWindowLong(getOsWindowHandle(), GWL_EXSTYLE) | WS_EX_LAYERED); } else { SetWindowLong(getOsWindowHandle(), GWL_EXSTYLE, GetWindowLong(getOsWindowHandle(), GWL_EXSTYLE) & ~WS_EX_LAYERED); } #endif setTransparency(-1); } int BaseWnd::getCursorType(int x, int y) { if (!customdefaultcursor) return BASEWND_CURSOR_POINTER; return BASEWND_CURSOR_USERSET; } void BaseWnd::onSetName() { if (isInited() && !isVirtual()) Wasabi::Std::Wnd::setWndName(getOsWindowHandle(), getNameSafe()); notifyParent(ChildNotify::NAMECHANGED); if (accessible) accessible->onSetName(getName()); } OSWINDOWHANDLE BaseWnd::getOsWindowHandle() { OSWINDOWHANDLE handle; if ( isVirtual() ) handle = getParent()->getOsWindowHandle(); else handle = hwnd; return handle; } OSMODULEHANDLE BaseWnd::getOsModuleHandle() { return hinstance; } void BaseWnd::onTip() { tipshowtimer = FALSE; tip_done = TRUE; POINT p; Wasabi::Std::getMousePos(&p); if (WASABI_API_WND->rootWndFromPoint(&p) == (ifc_window *)this) { createTip(); setTimer(TIP_DESTROYTIMER_ID, TIP_LENGTH); tipdestroytimer = TRUE; } setTimer(TIP_AWAY_ID, TIP_AWAY_DELAY); tipawaytimer = TRUE; } void BaseWnd::timerCallback(int id) { switch (id) { case BUFFEREDMSG_TIMER_ID: checkLockedUI(); break; // case TIP_TIMER_ID: //onTip(); //break; case TIP_DESTROYTIMER_ID: killTimer(TIP_DESTROYTIMER_ID); killTimer(TIP_AWAY_ID); tipawaytimer = FALSE; tipdestroytimer = FALSE; destroyTip(); break; case TIP_AWAY_ID: onTipMouseMove(); break; } } int BaseWnd::isInited() { return inited; } int BaseWnd::isDestroying() { return destroying; } int BaseWnd::wantSiblingInvalidations() { return FALSE; } void BaseWnd::setRSize(int x, int y, int w, int h) { rwidth = w; rheight = h; rx = x; ry = y; } void BaseWnd::resize(int x, int y, int w, int h, int wantcb) { inonresize = 1; if (x == AUTOWH) x = NOCHANGE; if (y == AUTOWH) y = NOCHANGE; if (w == AUTOWH) w = NOCHANGE; if (h == AUTOWH) h = NOCHANGE; if (getNumMinMaxEnforcers() > 0) { int min_w = getPreferences(MINIMUM_W); int min_h = getPreferences(MINIMUM_H); int max_w = getPreferences(MAXIMUM_W); int max_h = getPreferences(MAXIMUM_H); if (min_w != AUTOWH && w != NOCHANGE && w < min_w) w = min_w; if (max_w != AUTOWH && w != NOCHANGE && w > max_w) w = max_w; if (min_h != AUTOWH && h != NOCHANGE && h < min_h) h = min_h; if (max_h != AUTOWH && h != NOCHANGE && h > max_h) h = max_h; } int noresize = (w == NOCHANGE && h == NOCHANGE); int nomove = (x == NOCHANGE && y == NOCHANGE)/* || (x == rx && y == ry)*/; if (x == NOCHANGE) x = rx; if (y == NOCHANGE) y = ry; if (w == NOCHANGE) w = rwidth; if (h == NOCHANGE) h = rheight; #ifdef _DEBUG ASSERT(x < 0xFFF0); ASSERT(y < 0xFFF0); ASSERT(w < 0xFFF0); ASSERT(h < 0xFFF0); #endif double thisratio = getRenderRatio(); int different_ratio = (lastratio != thisratio); lastratio = thisratio; int noevent = (resizecount > 1 && w == rwidth && h == rheight); //ifc_window *dp = getDesktopParent(); if (different_ratio == 1 && noevent == 1) { if (Wasabi::Std::Wnd::getTopmostChild(getOsWindowHandle()) != INVALIDOSWINDOWHANDLE) noevent = 0; invalidateWindowRegion(); } RECT oldsize, newsize = Wasabi::Std::makeRect(x, y, w, h); if (hwnd != NULL) BaseWnd::getNonClientRect(&oldsize); else oldsize = newsize; setRSize(x, y, w, h); if (handleRatio() && renderRatioActive()) { multRatio(&w, &h); if (getParent() != NULL) { multRatio(&x, &y); } } if (!noevent) { if (wantcb && isPostOnInit()) { resizecount = MIN(5, ++resizecount); if (!isVirtual()) invalidateWindowRegion(); onResize(); if (ensureWindowRegionValid()) updateWindowRegion(); } } if (getOsWindowHandle() != NULL) { RECT oldsizescaled; getWindowRect(&oldsizescaled); RECT newsizescaled = {x, y, x + w, y + h}; if (MEMCMP(&newsizescaled, &oldsizescaled, sizeof(RECT))) { //CUT SetWindowPos(getOsWindowHandle(), NULL, x, y, w, h, //CUT SWP_NOZORDER | //CUT SWP_NOACTIVATE | //CUT (!wantRedrawOnResize() ? SWP_NOCOPYBITS: 0) | //CUT (ncb ? SWP_NOCOPYBITS : 0) | //CUT ( nomove ? SWP_NOMOVE : 0) | //CUT ( noresize ? SWP_NOSIZE : 0) | //CUT 0); Wasabi::Std::Wnd::setWndPos( getOsWindowHandle(), NULL, x, y, w, h, TRUE, TRUE, !wantRedrawOnResize() || ncb, nomove, noresize ); } //else //{ // DebugStringW(L"BaseWnd::resize optimized\n"); //} onAfterResize(); if (ncb) invalidate(); else { RECT r; if (hwnd != NULL) { if (newsize.left == oldsize.left && newsize.top == oldsize.top) { if (newsize.right > oldsize.right) { // growing in width r.left = oldsize.right; r.right = newsize.right; r.top = newsize.top; r.bottom = newsize.bottom; invalidateRect(&r); if (newsize.bottom > oldsize.bottom) { // growing in width & height r.left = oldsize.left; r.right = newsize.right; r.top = oldsize.bottom; r.bottom = newsize.bottom; invalidateRect(&r); } } else if (newsize.bottom > oldsize.bottom) { if (newsize.bottom > oldsize.bottom) { // growing in height r.left = oldsize.left; r.right = newsize.right; r.top = oldsize.bottom; r.bottom = newsize.bottom; invalidateRect(&r); } } } } } } inonresize = 0; } void BaseWnd::forcedOnResizeChain(ifc_window *w) { w->triggerEvent(TRIGGER_ONRESIZE); int n = w->getNumRootWndChildren(); for (int i = 0;i < n;i++) { forcedOnResizeChain(w->enumRootWndChildren(i)); } } int BaseWnd::forcedOnResize() { forcedOnResizeChain(this); return 1; } int BaseWnd::onResize() { if (!isVirtual() || (getRegionOp() != REGIONOP_NONE)) invalidateWindowRegion(); // you are not supposed to call onResize until after onInit has returned. If what you wanted was to generate // an onResize event to do some custom client coordinates recalculations (ie: to apply on your children) // then you don't need to do anything since onResize is going to be called after onInit() is done. If you still want to // trigger it because your code might be called by onInit and after onInit, use isPostOnInit() as a test. // if what you wanted was to signal a object that you just resized it, then you don't need to do anything beside // resize(...), it will generate the event on its own if the window is inited, and will defer to until after onInit // if it is not. // shortly put: do not call onResize before or inside onInit() // if you have any valid reason for doing that, i'd like to know about it so i can make it possible. -FG #ifdef _DEBUG if (!isPostOnInit()) { //__asm int 3; ASSERTPR(isPostOnInit(), "do not call onResize before or inside onInit()"); } #endif return FALSE; } void BaseWnd::resizeToClient(BaseWnd *wnd) { if (wnd != NULL) wnd->resize(&clientRect()); } int BaseWnd::onPostedMove() { /* if (w2k_alpha && Wasabi::Std::Wnd::isDesktopAlphaAvailable() && !cloaked) { RECT r; getWindowRect(&r); Wasabi::Std::Wnd::moveLayeredWnd(hwnd, r.left, r.top); }*/ return FALSE; } void BaseWnd::resize(RECT *r, int wantcb) { resize(r->left, r->top, r->right - r->left, r->bottom - r->top, wantcb); } void BaseWnd::move(int x, int y) { //DebugStringW( L"BaseWnd::move( x = %d, y = %d )\n", x, y ); setRSize(x, y, rwidth, rheight); Wasabi::Std::Wnd::setWndPos( getOsWindowHandle(), NULL, x, y, 0, 0, TRUE, TRUE, ncb, FALSE, TRUE ); //CUT if (!ncb) //CUT SetWindowPos(getOsWindowHandle(), NULL, x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_DEFERERASE); //CUT else //CUT SetWindowPos(getOsWindowHandle(), NULL, x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOCOPYBITS|SWP_NOACTIVATE|SWP_DEFERERASE); } #ifdef EXPERIMENTAL_INDEPENDENT_AOT BOOL CALLBACK EnumOwnedTopMostWindows(HWND hwnd, LPARAM lParam) { enumownedstruct *st = (enumownedstruct *)lParam; if (hwnd != st->hthis && GetWindow(hwnd, GW_OWNER) == st->owner) { ifc_window *w = (ifc_window*)GetWindowLong(hwnd, GWL_USERDATA); if (w != NULL && w->getAlwaysOnTop()) st->hlist->addItem(w); } return TRUE; } void BaseWnd::saveTopMosts() { HWND owner = GetWindow(getOsWindowHandle(), GW_OWNER); enumownedstruct st; ontoplist.removeAll(); if (owner != NULL) { st.owner = owner; st.hlist = &ontoplist; st.hthis = getOsWindowHandle(); EnumWindows(EnumOwnedTopMostWindows, (long)&st); } } void BaseWnd::restoreTopMosts() { HWND owner = GetWindow(getOsWindowHandle(), GW_OWNER); if (owner != NULL) { for (int i = 0;i < ontoplist.getNumItems();i++) { ontoplist.enumItem(i)->setAlwaysOnTop(1); } } } #endif void BaseWnd::bringToFront() { // when we set a window to the top of the zorder (not topmost), win32 finds the owner and removes any topmost flag its children may // have because it assumes we want this window over these, which we definitly don't. so we need to first go thru all the owner's children, // make a list of the ones with a topmost flag, set this window on top, and set the topmost flags back. yay ASSERT(!isVirtual()); #ifdef EXPERIMENTAL_INDEPENDENT_AOT saveTopMosts(); #endif //CUT SetWindowPos(getOsWindowHandle(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE|SWP_DEFERERASE|SWP_NOOWNERZORDER); Wasabi::Std::Wnd::bringToFront(getOsWindowHandle()); #ifdef EXPERIMENTAL_INDEPENDENT_AOT restoreTopMosts(); #endif } void BaseWnd::bringToBack() { ASSERT(!isVirtual()); #ifdef EXPERIMENTAL_INDEPENDENT_AOT saveTopMosts(); #endif //CUT SetWindowPos(getOsWindowHandle(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE|SWP_DEFERERASE|SWP_NOOWNERZORDER); Wasabi::Std::Wnd::sendToBack(getOsWindowHandle()); #ifdef EXPERIMENTAL_INDEPENDENT_AOT restoreTopMosts(); #endif } void BaseWnd::setVisible(int show) { int visible = isVisible(1); if (!!visible == !!show) return ; invalidate(); this_visible = !!show; /*if (!getParent() || getParent() == WASABI_API_WND->main_getRootWnd() && IsWindow(getOsWindowHandle())) { if (!show) { setLayeredWindow(0); if (setLayeredWindowAttributes) setLayeredWindowAttributes(hwnd, RGB(0,0,0), 255, LWA_ALPHA); } else { setLayeredWindow(w2k_alpha); } }*/ if (!getParent() || getParent() == WASABI_API_WND->main_getRootWnd() || getParent()->isVisible()) { onSetVisible(show); } } void BaseWnd::setCloaked(int cloak) { if (cloaked == cloak) return ; cloaked = cloak; if (isVirtual()) return ; if (cloaked) { //CUTif (IsWindowVisible(getOsWindowHandle())) //CUT ShowWindow(getOsWindowHandle(), SW_HIDE); if (Wasabi::Std::Wnd::isWndVisible(getOsWindowHandle())) Wasabi::Std::Wnd::hideWnd(getOsWindowHandle()); } else { if (isVisible(1)) //CUTShowWindow(getOsWindowHandle(), SW_NORMAL); Wasabi::Std::Wnd::showWnd(getOsWindowHandle()); } } void BaseWnd::onSetVisible(int show) { /* for debug purposes - don't delete please #include "../../../studio/container.h" #include "../../../studio/layout.h" if (!show && getGuiObject() && STRCASEEQLSAFE(getGuiObject()->guiobject_getId(), "normal")) { Layout *l = (Layout *)getInterface(layoutGuid); if (l) { if (l->getParentContainer() && STRCASEEQLSAFE(l->getParentContainer()->getId(), "main")) { DebugString("Hiding main player\n"); } } }*/ if (!isVirtual()) if (hwnd != NULL) if (!cloaked) { //CUT // SetWindowPos(getOsWindowHandle(),NULL,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_SHOWWINDOW); //CUT ShowWindow(getOsWindowHandle(), show ? SW_SHOWNA : SW_HIDE); if (show) Wasabi::Std::Wnd::showWnd(getOsWindowHandle(), TRUE); else Wasabi::Std::Wnd::hideWnd(getOsWindowHandle()); } /* if (!show) postDeferredCallback(0x7849); else {*/ foreach(rootwndchildren) ifc_window *w = rootwndchildren.getfor(); if (w && w->isVisible(1)) // check internal flag only w->onSetVisible(show); endfor; dependent_sendEvent(BaseWnd::depend_getClassGuid(), Event_SETVISIBLE, show); //} /* if (getDesktopParent() == this) { cascadeRepaint(0); }*/ /*#ifdef WIN32 // os-specific non virtual child wnd support if (!isVirtual()) { HWND w = GetWindow(getOsWindowHandle(), GW_CHILD); while (w != NULL) { api_window *rootwnd = (api_window*)GetWindowLong(w, GWL_USERDATA); if (rootwnd && rootwnd != this) if (rootwnd->isInited()) rootwnd->onSetVisible(show); w = GetWindow(w, GW_HWNDNEXT); } } #endif*/ if (!isVirtual()) { if (!show) { deferedInvalidate(); delete virtualCanvas; virtualCanvas = NULL; } } invalidateWindowRegion(); } void BaseWnd::setEnabled(int en) { int enabled = isEnabled(1); if (!!enabled == !!en) return ; invalidate(); this_enabled = !!en; if (!getParent() || getParent() == WASABI_API_WND->main_getRootWnd() || getParent()->isEnabled()) { onEnable(en); } } int BaseWnd::isEnabled(int within) { if (!isVirtual() && !getOsWindowHandle()) return 0; if (!this_enabled) return 0; if (within) return this_enabled; // whatever, local if (isVirtual()) // virtual, global if (getParent()) return getParent()->isEnabled(); else return 0; // non virtual, global //CUT if (GetWindowLong(getOsWindowHandle(), GWL_STYLE) & WS_POPUP) return this_enabled; if (Wasabi::Std::Wnd::isPopup(getOsWindowHandle())) return this_enabled; //CUT if (!Wasabi::Std::Wnd::isValidWnd(GetParent(gethWnd()))) return this_enabled; if (!Wasabi::Std::Wnd::isValidWnd(Wasabi::Std::Wnd::getParent(getOsWindowHandle()))) return this_enabled; if (getParent()) return getParent()->isEnabled(); // not a popup, check its parent or fail return this_enabled; } int BaseWnd::onEnable(int en) { if (!isVirtual()) { if (hwnd != NULL) //CUT EnableWindow(getOsWindowHandle(), en); Wasabi::Std::Wnd::setEnabled(getOsWindowHandle(), en); foreach(rootwndchildren) ifc_window *w = rootwndchildren.getfor(); if (w->isEnabled(1)) // check internal flag only w->onEnable(en); endfor; } return 1; } void BaseWnd::setFocus() { if (curVirtualChildFocus != NULL) { curVirtualChildFocus->onKillFocus(); curVirtualChildFocus = NULL; } onSetRootFocus(this); //CUT SetFocus(getOsWindowHandle()); Wasabi::Std::Wnd::setFocus(getOsWindowHandle()); } void BaseWnd::setFocusOnClick(int f) { focus_on_click = f; } api_region *BaseWnd::getDeferedInvalidRgn() { return deferedInvalidRgn; } void BaseWnd::deferedInvalidate() { if (!hasVirtualChildren() || !isVisible(1)) return ; RECT r = Wasabi::Std::makeRect(0, 0, 0, 0); getNonClientRect(&r); deferedInvalidateRect(&r); } void BaseWnd::deferedInvalidateRect(RECT *r) { if (!hasVirtualChildren()) return ; RegionI h(r); deferedInvalidateRgn(&h); } void BaseWnd::deferedInvalidateRgn(api_region *h) { if (!hasVirtualChildren()) return ; if (!deferedInvalidRgn) { deferedInvalidRgn = new RegionI(); } deferedInvalidRgn->addRegion(h); } void BaseWnd::deferedValidate() { if (!hasVirtualChildren() || !isVisible(1)) return ; RECT r = Wasabi::Std::makeRect(0,0,0,0); getNonClientRect(&r); deferedValidateRect(&r); } void BaseWnd::deferedValidateRect(RECT *r) { if (!hasVirtualChildren()) return ; RegionI h(r); deferedValidateRgn(&h); } void BaseWnd::deferedValidateRgn(api_region *h) { if (!hasVirtualChildren()) return ; if (!deferedInvalidRgn) return ; deferedInvalidRgn->subtractRgn(h); } int BaseWnd::hasVirtualChildren() { return 1; //virtualChildren.getNumItems() > 0; } void BaseWnd::invalidate() { invalidateFrom(this); } void BaseWnd::invalidateFrom(ifc_window *who) { if (hasVirtualChildren()) deferedInvalidate(); //CUT if (hwnd != NULL && isVisible(1)) InvalidateRect(getOsWindowHandle(), NULL, FALSE); if (hwnd != NULL && isVisible(1)) Wasabi::Std::Wnd::invalidateRect(getOsWindowHandle()); } void BaseWnd::invalidateRectFrom(RECT *r, ifc_window *who) { if (hasVirtualChildren()) deferedInvalidateRect(r); RegionI rg(r); invalidateRgnFrom(&rg, who); } void BaseWnd::invalidateRgn(api_region *r) { invalidateRgnFrom(r, this); } void BaseWnd::invalidateRect(RECT *r) { invalidateRectFrom(r, this); } void BaseWnd::invalidateRgnFrom(api_region *r, ifc_window *who) { if (parentWnd) parentWnd->onChildInvalidate(r, who); PaintCallbackInfoI pc(NULL, r); dependent_sendEvent(BaseWnd::depend_getClassGuid(), Event_ONINVALIDATE, 0, &pc); if (hwnd != NULL && isVisible(1)) { if (hasVirtualChildren()) { api_region *_r = r->clone(); int j = virtualChildren.searchItem(who); for (int i = 0;i < virtualChildren.getNumItems();i++) { ifc_window *w = virtualChildren[i]; if (w != who && w->wantSiblingInvalidations()) w->onSiblingInvalidateRgn(_r, who, j, i); } deferedInvalidateRgn(_r); physicalInvalidateRgn(_r); r->disposeClone(_r); } else { deferedInvalidateRgn(r); physicalInvalidateRgn(r); } } } void BaseWnd::physicalInvalidateRgn(api_region *r) { if (hwnd != NULL && isVisible(1)) { if (renderRatioActive()) { api_region *clone = r->clone(); clone->scale(getRenderRatio(), getRenderRatio(), TRUE); //CUT InvalidateRgn(getOsWindowHandle(), clone->getOSHandle(), FALSE); Wasabi::Std::Wnd::invalidateRegion(getOsWindowHandle(), clone->getOSHandle()); r->disposeClone(clone); } else //CUT InvalidateRgn(getOsWindowHandle(), r->getOSHandle(), FALSE); Wasabi::Std::Wnd::invalidateRegion(getOsWindowHandle(), r->getOSHandle()); } } void BaseWnd::validate() { //CUT if (hwnd != NULL) ValidateRect(getOsWindowHandle(), NULL); if (hwnd != NULL) Wasabi::Std::Wnd::validateRect(getOsWindowHandle()); } void BaseWnd::validateRect(RECT *r) { if (hwnd != NULL) { if (renderRatioActive()) { RECT r2 = *r; Wasabi::Std::scaleRect(&r2, getRenderRatio()); //CUT ValidateRect(getOsWindowHandle(), &r2); Wasabi::Std::Wnd::validateRect(getOsWindowHandle(), &r2); } else //CUT ValidateRect(getOsWindowHandle(), r); Wasabi::Std::Wnd::validateRect(getOsWindowHandle(), r); } } void BaseWnd::validateRgn(api_region *reg) { if (hwnd != NULL) { if (renderRatioActive()) { api_region *clone = reg->clone(); clone->scale(getRenderRatio(), getRenderRatio(), TRUE); //CUT ValidateRgn(getOsWindowHandle(), clone->getOSHandle()); Wasabi::Std::Wnd::validateRegion(getOsWindowHandle(), clone->getOSHandle()); reg->disposeClone(clone); } else //CUT ValidateRgn(getOsWindowHandle(), reg->getOSHandle()); Wasabi::Std::Wnd::validateRegion(getOsWindowHandle(), reg->getOSHandle()); } } void BaseWnd::repaint() { /* if (hasVirtualChildren()) { api_region *h = new api_region(); int s = GetUpdateRgn(getOsWindowHandle(), h->getHRGN(), FALSE); if (s != NULLREGION && s != ERROR) { virtualDrawRgn(h); } delete h; }*/ //CUTif (hwnd != NULL) UpdateWindow(getOsWindowHandle()); if (hwnd != NULL) Wasabi::Std::Wnd::update(getOsWindowHandle()); } void BaseWnd::getClientRect(RECT *rect) { /* rect->left = rx; rect->right = rx + rwidth; rect->top = ry; rect->bottom = ry + rheight;*/ //ASSERT(hwnd != NULL); if (!Wasabi::Std::Wnd::isValidWnd(hwnd)) { MEMSET(rect, 0, sizeof(RECT)); return ; } GetClientRect(getOsWindowHandle(), rect); ////Wasabi::Std::Wnd::getClientRect(getOsWindowHandle(), rect); rect->right = rect->left + rwidth; rect->bottom = rect->top + rheight; } RECT BaseWnd::clientRect() { RECT ret; getClientRect(&ret); return ret; } void BaseWnd::getNonClientRect(RECT *rect) { // ASSERT(hwnd != NULL); if (!hwnd) getClientRect(rect); else { Wasabi::Std::Wnd::getClientRect(getOsWindowHandle(), rect); if (getRenderRatio() != 1.0) { rect->right = rect->left + rwidth; rect->bottom = rect->left + rheight; } } /* rect->left = rx; rect->right = rx + rwidth; rect->top = ry; rect->bottom = ry + rheight;*/ } RECT BaseWnd::nonClientRect() { RECT ret; getNonClientRect(&ret); return ret; } void BaseWnd::getWindowRect(RECT *rect) { //CUT#ifdef WIN32 //CUT ASSERT(hwnd != NULL); //CUT GetWindowRect(getOsWindowHandle(), rect); //CUT#else //CUT#error port me //CUT#endif Wasabi::Std::Wnd::getWindowRect(getOsWindowHandle(), rect); } // get position relative to parent (same coordinate system for basewnd & virtualwnd) void BaseWnd::getPosition(POINT *pt) { pt->x = rx; pt->y = ry; } void *BaseWnd::dependent_getInterface(const GUID *classguid) { HANDLEGETINTERFACE(ifc_window); //CUT HANDLEGETINTERFACE(api_window); return NULL; } RECT BaseWnd::windowRect() { RECT ret; getWindowRect(&ret); return ret; } void BaseWnd::clientToScreen(int *x, int *y) { int _x = x ? *x : 0; int _y = y ? *y : 0; if (renderRatioActive()) { _x = (int)((double)_x * getRenderRatio()); _y = (int)((double)_y * getRenderRatio()); } Wasabi::Std::Wnd::clientToScreen(getOsWindowHandle(), &_x, &_y); if (x) *x = _x; if (y) *y = _y; } void BaseWnd::clientToScreen(RECT *r) { clientToScreen((int*)&r->left, (int*)&r->top); clientToScreen((int*)&r->right, (int*)&r->bottom); } void BaseWnd::clientToScreen(POINT *p) { clientToScreen((int *)&p->x, (int *)&p->y); } void BaseWnd::screenToClient(int *x, int *y) { //CUT POINT p; int _x = x ? *x : 0; int _y = y ? *y : 0; //CUT ScreenToClient(getOsWindowHandle(), &p); Wasabi::Std::Wnd::screenToClient(getOsWindowHandle(), &_x, &_y); if (renderRatioActive()) { _x = (int)((double)_x / getRenderRatio()); _y = (int)((double)_y / getRenderRatio()); } if (x) *x = _x; if (y) *y = _y; } void BaseWnd::screenToClient(RECT *r) { screenToClient((int*)&r->left, (int*)&r->top); screenToClient((int*)&r->right, (int*)&r->bottom); } void BaseWnd::screenToClient(POINT *p) { screenToClient((int *)&p->x, (int *)&p->y); } void BaseWnd::setParent(ifc_window *newparent) { ASSERTPR(newparent != NULL, "quit being a weeny"); ASSERTPR(parentWnd == NULL || newparent == parentWnd, "can't reset parent"); parentWnd = newparent; if (isInited()) { OSWINDOWHANDLE w1 = getOsWindowHandle(); OSWINDOWHANDLE w2 = newparent->getOsWindowHandle(); if (w1 != w2) //CUT SetParent(w1, w2); Wasabi::Std::Wnd::setParent(w1, w2); } } //FUCKO int BaseWnd::reparent(ifc_window *newparent) { #ifdef _WIN32 if (!isVirtual()) { if (isInited()) { ifc_window *old = getParent(); if (!old && newparent) { ::SetParent(getOsWindowHandle(), newparent->getOsWindowHandle()); SetWindowLong(getOsWindowHandle() , GWL_STYLE, GetWindowLong(getOsWindowHandle(), GWL_STYLE) & ~WS_POPUP); SetWindowLong(getOsWindowHandle() , GWL_STYLE, GetWindowLong(getOsWindowHandle(), GWL_STYLE) | WS_CHILD); } else if (old && !newparent) { SetWindowLong(getOsWindowHandle() , GWL_STYLE, GetWindowLong(getOsWindowHandle(), GWL_STYLE) & ~WS_CHILD); SetWindowLong(getOsWindowHandle() , GWL_STYLE, GetWindowLong(getOsWindowHandle(), GWL_STYLE) | WS_POPUP); ::SetParent(getOsWindowHandle(), NULL); } else { ::SetParent(getOsWindowHandle(), newparent ? newparent->getOsWindowHandle() : NULL); } } } parentWnd = newparent; onSetParent(newparent); #ifdef WASABI_ON_REPARENT WASABI_ON_REPARENT(getOsWindowHandle()); #endif #else #warning port me #endif return 1; } ifc_window *BaseWnd::getParent() { return parentWnd; } ifc_window *BaseWnd::getRootParent() { return this; } //PORTME ifc_window *BaseWnd::getDesktopParent() { #ifdef _WIN32 // NONPORTABLE HWND w = getOsWindowHandle(); HWND last = w; if (!w) return NULL; HWND p = w; wchar_t cn[256] = {0}; while (p && !(GetWindowLong(p, GWL_STYLE) & WS_POPUP)) { GetClassNameW(p, cn, 255); cn[255] = 0; if (!wcscmp(cn, BASEWNDCLASSNAME)) last = p; p = GetParent(p); } if (p) { GetClassNameW(p, cn, 255); cn[255] = 0; if (!wcscmp(cn, BASEWNDCLASSNAME)) return (ifc_window*)GetWindowLongPtrW(p, GWLP_USERDATA); else if (last != NULL) return (ifc_window*)GetWindowLongPtrW(last, GWLP_USERDATA); } #else #warning port me #endif return NULL; } int BaseWnd::notifyParent(int msg, int param1, int param2) { ifc_window *notifywnd = getNotifyWindow(); if (getParent() == NULL && notifywnd == NULL) return 0; if (notifywnd == NULL) notifywnd = getParent(); ASSERT(notifywnd != NULL); return notifywnd->childNotify(this, msg, param1, param2); } int BaseWnd::passNotifyUp(ifc_window *child, int msg, int param1, int param2) { // Same code as above to decide for whom we should notify. ifc_window *notifywnd = getNotifyWindow(); if (getParent() == NULL && notifywnd == NULL) return 0; if (notifywnd == NULL) notifywnd = getParent(); ASSERT(notifywnd != NULL); // And here we just change the api_window pointer. return notifywnd->childNotify(child, msg, param1, param2); } void BaseWnd::setNotifyId(int id) { notifyid = id; } int BaseWnd::getNotifyId() { return notifyid; } DragInterface *BaseWnd::getDragInterface() { return this; } ifc_window *BaseWnd::rootWndFromPoint(POINT *pt) { // pt is in client coordinates int x = (int)((double)pt->x / getRenderRatio()); int y = (int)((double)pt->y / getRenderRatio()); ifc_window *ret = findRootWndChild(x, y); if (ret == NULL) ret = this; return ret; } int BaseWnd::rootwnd_paintTree(ifc_canvas *canvas, api_region *r) { BaseCloneCanvas c(canvas); return paintTree(&c, r); } const wchar_t *BaseWnd::getRootWndName() { return getName(); } const wchar_t *BaseWnd::getId() { return NULL; } void BaseWnd::setSkinId(int id) { skin_id = id; } void BaseWnd::setPreferences(int what, int v) { switch (what) { case MAXIMUM_W: maximum_w = v; break; case MAXIMUM_H: maximum_h = v; break; case MINIMUM_W: minimum_w = v; break; case MINIMUM_H: minimum_h = v; break; case SUGGESTED_W: suggested_w = v; break; case SUGGESTED_H: suggested_h = v; break; } } int BaseWnd::getPreferences(int what) { if (getNumMinMaxEnforcers() > 0) { int min_x = minimum_w, min_y = minimum_h, max_x = maximum_w, max_y = maximum_h, sug_x = suggested_w, sug_y = suggested_h; for (int i = 0;i < getNumMinMaxEnforcers();i++) { int tmin_x = MINIMUM_W, tmin_y = MINIMUM_H, tmax_x = MAXIMUM_W, tmax_y = MAXIMUM_H, tsug_x = SUGGESTED_W, tsug_y = SUGGESTED_H; ifc_window *w = enumMinMaxEnforcer(i); if (w) { tmin_x = w->getPreferences(MINIMUM_W); tmin_y = w->getPreferences(MINIMUM_H); tmax_x = w->getPreferences(MAXIMUM_W); tmax_y = w->getPreferences(MAXIMUM_H); tsug_x = w->getPreferences(SUGGESTED_W); tsug_y = w->getPreferences(SUGGESTED_H); if (tmin_x == -1) tmin_x = AUTOWH; if (tmin_y == -1) tmin_y = AUTOWH; if (tmax_x == -1) tmax_x = AUTOWH; if (tmax_y == -1) tmax_y = AUTOWH; if (tsug_x == -1) tsug_x = AUTOWH; if (tsug_y == -1) tsug_y = AUTOWH; #ifndef DISABLE_SYSFONTSCALE TextInfoCanvas textInfoCanvas(this); double fontScale = textInfoCanvas.getSystemFontScale(); GuiObject *o = static_cast(getInterface(guiObjectGuid)); if (o != NULL) { if (o->guiobject_getAutoSysMetricsW()) { if (tmin_x != AUTOWH) tmin_x = (int)((float)tmin_x * fontScale); if (tmax_x != AUTOWH) tmax_x = (int)((float)tmax_x * fontScale); if (tsug_x != AUTOWH) tsug_x = (int)((float)tsug_x * fontScale); } if (o->guiobject_getAutoSysMetricsH()) { if (tmin_y != AUTOWH) tmin_y = (int)((float)tmin_y * fontScale); if (tmax_y != AUTOWH) tmax_y = (int)((float)tmax_y * fontScale); if (tsug_y != AUTOWH) tsug_y = (int)((float)tsug_y * fontScale); } } #endif RECT cor; w->getNonClientRect(&cor); RECT wr; getNonClientRect(&wr); int xdif = (wr.right - wr.left) - (cor.right - cor.left); int ydif = (wr.bottom - wr.top) - (cor.bottom - cor.top); if (tmin_x != AUTOWH) tmin_x += xdif; if (tmin_y != AUTOWH) tmin_y += ydif; if (tmax_x != AUTOWH) tmax_x += xdif; if (tmax_y != AUTOWH) tmax_y += ydif; if (tsug_x != AUTOWH) tsug_x += xdif; if (tsug_y != AUTOWH) tsug_y += ydif; } if (min_x != AUTOWH) min_x = (tmin_x != AUTOWH) ? MAX(min_x, tmin_x) : min_x; else min_x = tmin_x; if (max_x != AUTOWH) max_x = (tmax_x != AUTOWH) ? MAX(max_x, tmax_x) : max_x; else max_x = tmax_x; if (min_y != AUTOWH) min_y = (tmin_y != AUTOWH) ? MAX(min_y, tmin_y) : min_y; else min_y = tmin_y; if (max_y != AUTOWH) max_y = (tmax_y != AUTOWH) ? MAX(max_y, tmax_y) : max_y; else max_y = tmax_y; if (sug_x != AUTOWH) sug_x = (tsug_x != AUTOWH) ? MAX(sug_x, tsug_x) : sug_x; else sug_x = tsug_x; if (sug_y != AUTOWH) sug_y = (tsug_y != AUTOWH) ? MAX(sug_y, tsug_y) : sug_y; else sug_y = tsug_y; } if (min_x != AUTOWH && min_x == max_x) sug_x = min_x; if (min_y != AUTOWH && min_y == max_y) sug_y = min_y; switch (what) { case MINIMUM_W: return min_x; case MINIMUM_H: return min_y; case MAXIMUM_W: return max_x; case MAXIMUM_H: return max_y; case SUGGESTED_W: return sug_x; case SUGGESTED_H: return sug_y; } } switch (what) { case SUGGESTED_W: return suggested_w; case SUGGESTED_H: return suggested_h; case MAXIMUM_W: return maximum_w; case MAXIMUM_H: return maximum_h; case MINIMUM_W: return minimum_w; case MINIMUM_H: return minimum_h; } return AUTOWH; } void BaseWnd::setStartHidden(int wtf) { start_hidden = wtf; } //PORTME #ifdef _WIN32 #define EQUAL_CLSNAME(__name1, __name2)\ (CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),\ NORM_IGNORECASE, (__name1), -1, (__name2), -1)) static BOOL BaseWnd_IsFrameWindow(HWND hwnd) { WCHAR szClass[64] = {0}; if (NULL == hwnd || !GetClassNameW(hwnd, szClass, ARRAYSIZE(szClass))) return FALSE; return EQUAL_CLSNAME(szClass, L"Winamp v1.x") || EQUAL_CLSNAME(szClass, L"BaseWindow_RootWnd"); } LRESULT BaseWnd::wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (!isDestroying()) switch (uMsg) { case WM_DEFER_CALLBACK: timerclient_onDeferredCallback(wParam, lParam); break; case WM_SYSCOMMAND: { if ((wParam & 0xfff0) == SC_SCREENSAVE || (wParam & 0xfff0) == SC_MONITORPOWER) { ifc_window *main = WASABI_API_WND->main_getRootWnd(); if (main && main != this) return SendMessageW(main->gethWnd(), uMsg, wParam, lParam); } break; } //CUT case WM_CREATE: //CUT hwnd = hWnd; //CUT break; //CUT case WM_CLOSE: //CUT return 0; case WM_PAINT: { if (inonresize && !wantRedrawOnResize()) return 1; ASSERT(hwnd != NULL); if (!isVisible(1) || IsIconic(hWnd)) break; RECT r; if (GetUpdateRect(hWnd, &r, FALSE)) { if (virtualOnPaint()) { return 0; } } } break; case WM_PRINTCLIENT: { bool old_cloaked = (!!cloaked); cloaked = true; DCCanvas dc((HDC)wParam, this); paint(&dc, 0); cloaked = old_cloaked; if (lParam & PRF_CHILDREN) { RECT wnd_size; GetWindowRect(hwnd, &wnd_size); HWND child = GetWindow(hwnd, GW_CHILD); while (child != NULL) { if (GetWindowLongPtrW(child, GWL_STYLE) & WS_VISIBLE) { RECT child_size; GetWindowRect(child, &child_size); if (child_size.right && child_size.bottom) { BltCanvas bitmap(child_size.right, child_size.bottom, child);; SendMessageW(child, WM_PRINT, (WPARAM)bitmap.getHDC(), PRF_CHILDREN | PRF_CLIENT | PRF_NONCLIENT/*| PRF_OWNED*/); //bitmap->makeAlpha(255); //set alpha to 255 int w, h; bitmap.getDim(&w, &h, NULL); ARGB32 *m_pBits = (ARGB32 *)bitmap.getBits(); int nwords = w*h; for (; nwords > 0; nwords--, m_pBits++) { unsigned char *pixel = (unsigned char *)m_pBits; pixel[3] = 255; // alpha } POINT offset; offset.x = child_size.left - wnd_size.left; offset.y = child_size.top - wnd_size.top; //BLENDFUNCTION blendFn; //blendFn.BlendOp = AC_SRC_OVER; //blendFn.BlendFlags = 0; //blendFn.SourceConstantAlpha = 255; //blendFn.AlphaFormat = 0; //AlphaBlend((HDC)wParam, offset.x, offset.y, child_size.right-child_size.left, child_size.bottom-child_size.top, // bitmap->getHDC(), 0, 0, child_size.right-child_size.left, child_size.bottom-child_size.top, blendFn); StretchBlt((HDC)wParam, offset.x, offset.y, child_size.right-child_size.left, child_size.bottom-child_size.top, bitmap.getHDC(), 0, 0, child_size.right-child_size.left, child_size.bottom-child_size.top, SRCCOPY); } } child = GetWindow(child, GW_HWNDNEXT); } } } return 0; //CUT case WM_NCPAINT: return 0; //CUT case WM_SYNCPAINT: return 0; case WM_SETCURSOR: if (checkModal()) return TRUE; if (hWnd == (HWND)wParam) { DWORD windowStyle = (DWORD)GetWindowLongPtrW(hWnd, GWL_STYLE); switch(HIWORD(lParam)) { case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case 0x020B/*WM_XBUTTONDOWN*/: DisabledWindow_OnMouseClick(hWnd); break; } int ct = BASEWND_CURSOR_POINTER; int _x, _y; Wasabi::Std::getMousePos(&_x, &_y); screenToClient(&_x, &_y); OSCURSORHANDLE c = NULL; if (0 == (WS_DISABLED & windowStyle)) { if (!handleVirtualChildMsg(WM_SETCURSOR, _x, _y, &ct, &c)) { ct = getCursorType(_x, _y); } } wchar_t *wincursor = NULL; switch (ct) { case BASEWND_CURSOR_USERSET: if (c == NULL) c = getCustomCursor(_x, _y); if (c != NULL) { SetCursor(c); return TRUE; } else wincursor = IDC_ARROW; // Ensure to have at least a cursor break; case BASEWND_CURSOR_POINTER: wincursor = IDC_ARROW; break; case BASEWND_CURSOR_NORTHSOUTH: wincursor = IDC_SIZENS; break; case BASEWND_CURSOR_EASTWEST: wincursor = IDC_SIZEWE; break; case BASEWND_CURSOR_NORTHWEST_SOUTHEAST: wincursor = IDC_SIZENWSE; break; case BASEWND_CURSOR_NORTHEAST_SOUTHWEST: wincursor = IDC_SIZENESW; break; case BASEWND_CURSOR_4WAY: wincursor = IDC_SIZEALL; break; case BASEWND_CURSOR_EDIT: wincursor = IDC_IBEAM; break; default: wincursor = IDC_ARROW; break; } if (wincursor != NULL) { SetCursor(LoadCursor(NULL, wincursor)); return TRUE; } } return FALSE; case WM_TIMER: timerCallback((int)wParam); return 0; case WM_GETOBJECT: if (lParam == OBJID_CLIENT) { Accessible *acc = getAccessibleObject(); if (acc != NULL) { LRESULT lAcc = acc->getOSHandle((int)wParam); return lAcc; } } break; // Fall through to DefWindowProc case WM_SETFOCUS: if (!focusEventsEnabled) break; if (isInited()) { if (rootfocus != NULL && rootfocus != this) { if (rootfocus != curVirtualChildFocus) rootfocus->setFocus(); break; } else { if (wantFocus()) { onGetFocus(); break; } else { ifc_window *w = getTab(TAB_GETFIRST); if (w != NULL) { w->setFocus(); } } } } break; case WM_KILLFOCUS: { ifc_window *rp = getRootParent(); if (!WASABI_API_WND->rootwndIsValid(rp) || !Wasabi::Std::Wnd::isValidWnd(rp->getOsWindowHandle())) break; if (!focusEventsEnabled) break; #ifdef WASABI_COMPILE_WND if (WASABI_API_WND) WASABI_API_WND->forwardOnKillFocus(); // resets the keyboard active keys buffer #endif if (!WASABI_API_WND->rootwndIsValid(curVirtualChildFocus)) curVirtualChildFocus = NULL; if (curVirtualChildFocus) { curVirtualChildFocus->onKillFocus(); curVirtualChildFocus = NULL; } else if (hasfocus) onKillFocus(); break; } // dragging and dropping case WM_LBUTTONDOWN: { if (lParam == 0xdeadc0de) return 1; if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; WASABI_API_WND->popupexit_check(this); if (checkModal()) return 0; abortTip(); int xPos = (signed short)LOWORD(lParam); int yPos = (signed short)HIWORD(lParam); xPos = (int)((float)xPos / getRenderRatio()); yPos = (int)((float)yPos / getRenderRatio()); if (!getCapture() && hasVirtualChildren() && handleVirtualChildMsg(WM_LBUTTONDOWN, xPos, yPos)) return 0; if (isEnabled() && !dragging) { autoFocus(this); int r = 0; if (wantLeftClicks()) r = onLeftButtonDown(xPos, yPos); if (checkDoubleClick(uMsg, xPos, yPos) && wantDoubleClicks() && onLeftButtonDblClk(xPos, yPos)) return 0; return r; } } break; case WM_RBUTTONDOWN: { if (lParam == 0xdeadc0de) return 1; if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; WASABI_API_WND->popupexit_check(this); if (checkModal()) return 0; abortTip(); int xPos = (signed short)LOWORD(lParam); int yPos = (signed short)HIWORD(lParam); xPos = (int)((float)xPos / getRenderRatio()); yPos = (int)((float)yPos / getRenderRatio()); if (!getCapture() && hasVirtualChildren()) if (handleVirtualChildMsg(WM_RBUTTONDOWN, xPos, yPos)) return 0; if (isEnabled() && !dragging) { autoFocus(this); int r = 0; if (wantRightClicks()) r = onRightButtonDown(xPos, yPos); if (checkDoubleClick(uMsg, xPos, yPos) && wantDoubleClicks()) if (onRightButtonDblClk(xPos, yPos)) return 0; return r; } } break; case WM_MOUSEHOVER: if (checkModal()) return 0; if (!getCapture() && hasVirtualChildren()) if (handleVirtualChildMsg(WM_MOUSEHOVER, 0, 0)) return 0; break; case WM_MOUSEMOVE: { /* static int mm=0; DebugString("mousemove %d\n", mm++);*/ if (checkModal()) return 0; int xPos = (signed short)LOWORD(lParam); int yPos = (signed short)HIWORD(lParam); xPos = (int)((float)xPos / getRenderRatio()); yPos = (int)((float)yPos / getRenderRatio()); if (dragging) { POINT pt = {xPos, yPos}; clientToScreen(&pt); ifc_window *targ; int candrop = 0; // find the window the mouse is over targ = NULL; if (stickyWnd) { RECT wr; GetWindowRect(stickyWnd->getOsWindowHandle(), &wr); if (pt.x >= wr.left - sticky.left && pt.x <= wr.right + sticky.right && pt.y >= wr.top - sticky.top && pt.y <= wr.bottom + sticky.bottom) targ = stickyWnd; else stickyWnd = NULL; } if (targ == NULL && WASABI_API_WND) targ = WASABI_API_WND->rootWndFromPoint(&pt); // FG> not to self, check DI prevtargdi(prevtarg); DI targdi(targ); if (prevtarg != targ) { // window switch if (prevtarg != NULL) prevtargdi.dragLeave(this); if (targ != NULL) targdi.dragEnter(this); } if (targ != NULL) candrop = targdi.dragOver(pt.x, pt.y, this); if (targ == NULL || !candrop) SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_NO))); else SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_APPSTARTING))); prevtarg = targ; } else if (isEnabled()) { tipbeenchecked = FALSE; if (!getCapture() && hasVirtualChildren()) { if (handleVirtualChildMsg(WM_MOUSEMOVE, xPos, yPos)) return 0; } if (getCapture()) { if (wantMouseMoves()) if (onMouseMove(xPos, yPos)) return 0; } if (!tipbeenchecked) onTipMouseMove(); return 0; } } break; case WM_LBUTTONUP: { if (lParam == 0xdeadc0de) return 1; if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (checkModal()) return 0; int xPos = (signed short)LOWORD(lParam); int yPos = (signed short)HIWORD(lParam); xPos = (int)((float)xPos / getRenderRatio()); yPos = (int)((float)yPos / getRenderRatio()); abortTip(); if (!dragging && !getCapture() && hasVirtualChildren()) { if (handleVirtualChildMsg(WM_LBUTTONUP, xPos, yPos)) return 0; } if (dragging) { clientToScreen(&xPos, &yPos); int res = 0; if (prevtarg != NULL) { res = DI(prevtarg).dragDrop(this, xPos, yPos); } // inform source what happened dragComplete(res); resetDragSet(); prevtarg = NULL; stickyWnd = NULL; suggestedTitle = NULL; SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW))); Wasabi::Std::Wnd::releaseCapture(); dragging = 0; } else if (isEnabled()) { if (wantLeftClicks()) if (onLeftButtonUp(xPos, yPos)) return 0; } } break; case WM_RBUTTONUP: { if (lParam == 0xdeadc0de) return 1; if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (checkModal()) return 0; abortTip(); int xPos = (signed short)LOWORD(lParam); int yPos = (signed short)HIWORD(lParam); xPos = (int)((float)xPos / getRenderRatio()); yPos = (int)((float)yPos / getRenderRatio()); if (!getCapture() && hasVirtualChildren()) { if (handleVirtualChildMsg(WM_RBUTTONUP, xPos, yPos)) return 0; } if (isEnabled() && !dragging) { if (wantRightClicks()) if (onRightButtonUp(xPos, yPos)) return 0; } } break; case WM_CONTEXTMENU: { if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (checkModal()) return 0; ASSERT(hWnd != NULL); int xPos = (signed short)LOWORD(lParam); int yPos = (signed short)HIWORD(lParam); if (hWnd == getOsWindowHandle()) { if (wantContextMenus()) if (onContextMenu(xPos, yPos)) return 0; } else if (GetParent(hWnd) == getOsWindowHandle()) { if (wantContextMenus()) if (onChildContextMenu(xPos, yPos)) return 0; } } break; case WM_ERASEBKGND: return (onEraseBkgnd((HDC)wParam)); case WM_MOUSEWHEEL: { abortTip(); int l, a; l = (short)HIWORD(wParam) / 120; a = (short)HIWORD(wParam); if (!l) if (a > 0) l = 1; else if (a < 0)l = 0; a = l >= 0 ? l : -l; if (GetAsyncKeyState(VK_MBUTTON)&0x8000) { if (l >= 0) l = 0; // Fast Forward 5s else l = 1; // Rewind 5s } else { if (l >= 0) l = 2; // Volume up else l = 3; // Volume down } int r = 0; if (l & 1) r = onMouseWheelDown(!(BOOL)(l & 2), a); else r = onMouseWheelUp(!(BOOL)(l & 2), a); if (r == 0) { r = WASABI_API_WND->forwardOnMouseWheel(l, a); } // if it wasn't handled by this wnd, nor by the api, send it to the main wnd, unless we're it if (r == 0) { if (WASABI_API_WND->main_getRootWnd() != this) r = (int)SendMessageW(WASABI_API_WND->main_getRootWnd()->gethWnd(), uMsg, wParam, lParam); } return r; } case WM_WA_RELOAD: { if (wParam == 0) freeResources(); else reloadResources(); return 0; } case WM_WA_GETFBSIZE: { SIZE *s = (SIZE *)wParam; s->cx = rwidth; s->cy = rheight; return 0; } case WM_USER + 8976: // wheel in tip, delete tip abortTip(); return 0; case WM_CHAR: if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (WASABI_API_WND->interceptOnChar((TCHAR) wParam)) return 0; if (curVirtualChildFocus == NULL) { if (onChar(((TCHAR) wParam))) return 0; } else { if (curVirtualChildFocus->onChar(((TCHAR) wParam))) return 0; } if (WASABI_API_WND && WASABI_API_WND->forwardOnChar(this, (TCHAR) wParam, (int)lParam)) return 0; break; case WM_KEYDOWN: if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (WASABI_API_WND->interceptOnKeyDown((int) wParam)) return 0; if (curVirtualChildFocus == NULL) { if (onKeyDown((int) wParam)) return 0; } else { if (curVirtualChildFocus->onKeyDown((int)wParam)) return 0; } if (WASABI_API_WND && WASABI_API_WND->forwardOnKeyDown(this, (int) wParam, (int)lParam)) return 0; break; case WM_KEYUP: if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (WASABI_API_WND->interceptOnKeyUp((int) wParam)) return 0; if (curVirtualChildFocus == NULL) { if (onKeyUp((int) wParam)) return 0; } else { if (curVirtualChildFocus->onKeyUp((int)wParam)) return 0; } if (WASABI_API_WND && WASABI_API_WND->forwardOnKeyUp(this, (int) wParam, (int)lParam)) return 0; break; case WM_SYSKEYDOWN: if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (WASABI_API_WND->interceptOnSysKeyDown((int) wParam, (int)lParam)) return 0; if (curVirtualChildFocus == NULL) { if (onSysKeyDown((int) wParam, (int)lParam)) return 0; } else { if (curVirtualChildFocus->onSysKeyDown((int)wParam, (int)lParam)) return 0; } if (WASABI_API_WND && WASABI_API_WND->forwardOnSysKeyDown(this, (int) wParam, (int)lParam)) return 0; break; case WM_SYSKEYUP: if (bufferizeLockedUIMsg(uMsg, (int)wParam, (int)lParam)) return 0; if (WASABI_API_WND->interceptOnSysKeyUp((int) wParam, (int)lParam)) return 0; if (curVirtualChildFocus == NULL) { if (onSysKeyUp((int) wParam, (int)lParam)) return 0; } else { if (curVirtualChildFocus->onSysKeyUp((int)wParam, (int)lParam)) return 0; } if (WASABI_API_WND && WASABI_API_WND->forwardOnSysKeyUp(this, (int) wParam, (int)lParam)) return 0; break; case WM_MOUSEACTIVATE: { if (checkModal() || !wantActivation()) return MA_NOACTIVATE; //SetFocus(getOsWindowHandle()); return MA_ACTIVATE; } case WM_ACTIVATEAPP: if (wParam == FALSE) { if (WASABI_API_WND != NULL) { WASABI_API_WND->popupexit_signal(); WASABI_API_SYSCB->syscb_issueCallback(SysCallback::GC, GarbageCollectCallback::GARBAGECOLLECT); WASABI_API_WND->kbdReset(); if (ghosthwnd.getNumItems() > 0 && ghostbust) { ghostbust = 0; postDeferredCallback(DC_KILLGHOST); } return 0; } } break; case WM_ACTIVATE: switch(LOWORD(wParam)) { case WA_ACTIVE: case WA_CLICKACTIVE: if (WASABI_API_WND != NULL) WASABI_API_WND->popupexit_check(this); onActivate(); if (WA_CLICKACTIVE == LOWORD(wParam)) { POINT pt; DWORD pts = GetMessagePos(); POINTSTOPOINT(pt, pts); MapWindowPoints(HWND_DESKTOP, hwnd, &pt, 1); HWND hTarget = ChildWindowFromPointEx(hwnd, pt, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED | CWP_SKIPTRANSPARENT); if (hTarget && hTarget != hwnd) lastActiveWnd = hTarget; } if (lastActiveWnd != hwnd && NULL != lastActiveWnd && IsWindow(lastActiveWnd)) { SendMessageW(lastActiveWnd, uMsg, wParam, lParam); return 0; } break; default: onDeactivate(); lastActiveWnd = GetFocus(); if (NULL != lastActiveWnd && !IsChild(hwnd, lastActiveWnd)) lastActiveWnd = NULL; { #ifndef ARRAYSIZE #define ARRAYSIZE(x) (sizeof(x)/sizeof(*x)) #endif if (NULL != lastActiveWnd && !BaseWnd_IsFrameWindow(lastActiveWnd)) { while (lastActiveWnd) { if (BaseWnd_IsFrameWindow(GetWindow(lastActiveWnd, GW_OWNER))) break; lastActiveWnd = GetAncestor(lastActiveWnd, GA_PARENT); } } } if (lastActiveWnd != hwnd && NULL != lastActiveWnd) { SendMessageW(lastActiveWnd, uMsg, wParam, lParam); return 0; } break; } break; case WM_NCACTIVATE: if (allowDeactivation()) return TRUE; return FALSE; case WM_WINDOWPOSCHANGING: { if (!isVirtual() && Wasabi::Std::Wnd::isPopup(hwnd)) { WINDOWPOS *wp = (WINDOWPOS *)lParam; if (wp->x != rx || wp->y != ry) wp->flags |= SWP_NOMOVE; } } break; case WM_WINDOWPOSCHANGED: { WINDOWPOS *lpwp = (WINDOWPOS *)lParam; // points to size and position data if (lpwp->flags & SWP_HIDEWINDOW) { minimized = 1; onMinimize(); } else if (lpwp->flags & SWP_SHOWWINDOW) { minimized = 0; onRestore(); } if (!inonresize) { int w = rwidth; int h = rheight; multRatio(&w, &h); if (lpwp->cx != w || lpwp->cy != h) { DebugStringW(L"external onResize\n"); w = lpwp->cx; h = lpwp->cy; divRatio(&w, &h); setRSize(rx, ry, w, h); if (isPostOnInit()) onResize(); } } onPostedMove(); return 0; } case WM_DROPFILES: { if (checkModal()) break; WASABI_API_WND->pushModalWnd(); onExternalDropBegin(); HDROP h = (HDROP)wParam; POINT dp = {0}; DragQueryPoint(h, &dp); clientToScreen(&dp); // build a file list wchar_t buf[WA_MAX_PATH] = {0}; PtrList keep; SetCursor(LoadCursor(NULL, IDC_WAIT)); //CUT #if UTF8 //CUT // doesn't really need UTF8, the "buf" is never written to. //CUT // made to be NULL to enforce this concept. int nfiles = DragQueryFile(h, 0xffffffff, NULL, 0); //CUT #else //CUT int nfiles = DragQueryFile(h, 0xffffffff, buf, sizeof(buf)); //CUT #endif // convert them all to PlayItem *'s for (int i = 0; i < nfiles; i++) { DragQueryFileW(h, i, buf, WA_MAX_PATH); addDroppedFile(buf, &keep); // recursive } SetCursor(LoadCursor(NULL, IDC_ARROW)); dragging = 1; if (dragEnter(this)) { if (dragOver(dp.x, dp.y, this)) dragDrop(this, dp.x, dp.y); } else { dragLeave(this); #ifdef FORWARD_DRAGNDROP HWND w = WASABI_API_WND->main_getRootWnd()->gethWnd(); SendMessageW(w, WM_DROPFILES, wParam, lParam); #endif } dragging = 0; // remove data keep.deleteAll(); resetDragSet(); onExternalDropEnd(); WASABI_API_WND->popModalWnd(); } return 0; // dropfiles case WM_CAPTURECHANGED: /* static int cc=0; DebugString("capture changed! %d\n", cc++);*/ if (preventcancelcapture) return 0; inputCaptured = 0; if (curVirtualChildCaptured != NULL) { ifc_window *w = curVirtualChildCaptured; curVirtualChildCaptured = NULL; w->onCancelCapture(); } else { onCancelCapture(); } return 0; } //switch if (WINAMP_WM_DIRECT_MOUSE_WHEEL == uMsg && WM_NULL != WINAMP_WM_DIRECT_MOUSE_WHEEL) { wndProc(hWnd, WM_MOUSEWHEEL, wParam, lParam); return TRUE; } if (uMsg >= WM_USER) { int ret; if (onUserMessage(uMsg, (int)wParam, (int)lParam, &ret)) return ret; return 0; } return DefWindowProcW(hWnd, uMsg, wParam, lParam); } #endif int BaseWnd::onUserMessage(int msg, int w, int l, int *r) { return 0; } int BaseWnd::checkDoubleClick(int b, int x, int y) { #ifdef _WIN32 uint32_t now = Wasabi::Std::getTickCount(); switch (b) { case WM_LBUTTONDOWN: if (lastClick[0] > now - Wasabi::Std::getDoubleClickDelay()) { lastClick[0] = 0; if (ABS(lastClickP[0].x - x) > Wasabi::Std::getDoubleClickX() || ABS(lastClickP[0].y - y) > Wasabi::Std::getDoubleClickY()) return 0; return 1; } lastClick[0] = now; lastClickP[0].x = x; lastClickP[0].y = y; break; case WM_RBUTTONDOWN: if (lastClick[1] > now - Wasabi::Std::getDoubleClickDelay()) { lastClick[1] = 0; if (ABS(lastClickP[1].x - x) > Wasabi::Std::getDoubleClickX() || ABS(lastClickP[1].y - y) > Wasabi::Std::getDoubleClickY()) return 0; return 1; } lastClick[1] = now; lastClickP[1].x = x; lastClickP[1].y = y; break; } #else #warning port me #endif return 0; } int BaseWnd::onMouseWheelUp(int click, int lines) { return 0; } int BaseWnd::onMouseWheelDown(int click, int lines) { return 0; } int BaseWnd::onContextMenu(int x, int y) { return 0; } int BaseWnd::onChildContextMenu(int x, int y) { return 0; } int BaseWnd::onDeferredCallback(intptr_t param1, intptr_t param2) { switch (param1) { case DEFERREDCB_FLUSHPAINT: do_flushPaint(); break; case DEFERREDCB_INVALIDATE: if (isPostOnInit()) invalidate(); break; case DC_KILLGHOST: if (ghosthwnd.getNumItems() > 0) { preventcancelcapture = 1; for (int i = 0;i < ghosthwnd.getNumItems();i++) Wasabi::Std::Wnd::destroyWnd(ghosthwnd.enumItem(i)); ghosthwnd.freeAll(); preventcancelcapture = 0; } break; case DEFERREDCB_FOCUSFIRST: assignRootFocus(NULL); if (Wasabi::Std::Wnd::getFocus() == getOsWindowHandle()) { focusNext(); } break; case 0x7849 /*DEFERREDCB_ONHIDE*/: { foreach(rootwndchildren) ifc_window *w = rootwndchildren.getfor(); if (w->isVisible(1)) // check internal flag only w->onSetVisible(0); endfor; dependent_sendEvent(BaseWnd::depend_getClassGuid(), Event_SETVISIBLE, 0); break; } } return 0; } int BaseWnd::onPaint(Canvas *canvas) { #if 0 // example: PaintCanvas c; if (!c.beginPaint(this)) return 0; (do some painting) c will self -destruct on return #endif if (renderbasetexture) { PaintCanvas paintcanvas; if (canvas == NULL) { if (!paintcanvas.beginPaint(this)) return 0; canvas = &paintcanvas; } RECT r; getNonClientRect(&r); RenderBaseTexture(canvas, r); } return 0; } int BaseWnd::onPaint(Canvas *canvas, api_region *h) { if (!canvas) return onPaint(canvas); #ifdef _WIN32 int sdc = SaveDC(canvas->getHDC()); #elif defined(__APPLE__) CGContextSaveGState(canvas->getHDC()); #endif canvas->selectClipRgn(h); int rs = onPaint(canvas); #ifdef _WIN32 RestoreDC(canvas->getHDC(), sdc); #elif defined(__APPLE__) CGContextRestoreGState(canvas->getHDC()); #endif return rs; } int BaseWnd::getTransparency() { return wndalpha; } void BaseWnd::setTransparency(int amount) { //if (wndalpha == amount) return; if (amount == 254) amount = 255; if (amount == 1) amount = 0; if (amount != -1) wndalpha = amount; else amount = wndalpha; if (!Wasabi::Std::Wnd::isDesktopAlphaAvailable()) { wndalpha = 255; return ; } if (w2k_alpha) { invalidate(); return ; } #ifdef WIN32 if (!isInited() || isVirtual()) return ; if (!Wasabi::Std::Wnd::isValidWnd(getOsWindowHandle())) return ; if (amount < -1) amount = 0; else if (amount > 255) amount = 255; //CUT DWORD dwLong = GetWindowLong(hwnd, GWL_EXSTYLE); if (amount == 255 && !forceTransparencyFlag()) { Wasabi::Std::Wnd::setLayeredWnd(hwnd, FALSE); //CUT if (dwLong & WS_EX_LAYERED) //CUT SetWindowLong(hwnd, GWL_EXSTYLE, dwLong & ~WS_EX_LAYERED); has_alpha_flag = 0; } else { if (!Wasabi::Std::Wnd::isLayeredWnd(hwnd)) Wasabi::Std::Wnd::setLayeredWnd(hwnd, TRUE); //CUT if (!(dwLong & WS_EX_LAYERED)) //CUT SetWindowLong(hwnd, GWL_EXSTYLE, dwLong | WS_EX_LAYERED); Wasabi::Std::Wnd::setLayeredAlpha(hwnd, amount); //CUT setLayeredWindowAttributes(hwnd, RGB(0,0,0), amount, LWA_ALPHA); has_alpha_flag = 1; } #endif } int BaseWnd::forceTransparencyFlag() { return 0; } int BaseWnd::beginCapture() { if (!getCapture()) { disable_tooltip_til_recapture = 0; curVirtualChildCaptured = NULL; /* oldCapture = */Wasabi::Std::Wnd::setCapture(getOsWindowHandle()); /* if (oldCapture) { DebugString("Stolen capture detected, this may be ok, but try to avoid it if possible. Saving old capture\n"); }*/ inputCaptured = 1; } return 1; } int BaseWnd::endCapture() { preventcancelcapture = 1; if (Wasabi::Std::Wnd::getCapture() == getOsWindowHandle()) Wasabi::Std::Wnd::releaseCapture(); /* if (oldCapture) { DebugString("Restoring old capture\n"); SetCapture(oldCapture); oldCapture = NULL; }*/ inputCaptured = 0; preventcancelcapture = 0; return 1; } int BaseWnd::getCapture() { if (inputCaptured && Wasabi::Std::Wnd::getCapture() == getOsWindowHandle() && curVirtualChildCaptured == NULL) return 1; return 0; } void BaseWnd::cancelCapture() { if (curVirtualChildCaptured != NULL) { curVirtualChildCaptured->cancelCapture(); return ; } if (getCapture()) endCapture(); onCancelCapture(); } int BaseWnd::onMouseMove(int x, int y) { onTipMouseMove(); return 0; } void BaseWnd::onTipMouseMove() { POINT p; if (dragging) return ; if (disable_tooltip_til_recapture) return ; tipbeenchecked = TRUE; Wasabi::Std::getMousePos(&p); if (WASABI_API_WND->rootWndFromPoint(&p) != (ifc_window *)this) { // leaving area tip_done = FALSE; if (tipawaytimer) killTimer(TIP_AWAY_ID); tipawaytimer = FALSE; if (tipshowtimer) { // TODO: on the mac, use CreateMouseTrackingRegion TRACKMOUSEEVENT tracker; tracker.cbSize=sizeof(tracker); tracker.dwFlags = TME_HOVER|TME_CANCEL; tracker.hwndTrack = this->getOsWindowHandle(); tracker.dwHoverTime = TIP_TIMER_THRESHOLD; TrackMouseEvent(&tracker); } tipshowtimer = FALSE; destroyTip(); } else { // moving in area const wchar_t *t = getTip(); if (!disable_tooltip_til_recapture && !tipshowtimer && !tip_done && t != NULL && *t != 0) { //entering area & need tip // TODO: on the mac, use CreateMouseTrackingRegion TRACKMOUSEEVENT tracker; tracker.cbSize=sizeof(tracker); tracker.dwFlags = TME_HOVER; tracker.hwndTrack = this->getOsWindowHandle(); tracker.dwHoverTime = TIP_TIMER_THRESHOLD; TrackMouseEvent(&tracker); tipshowtimer = TRUE; } /*else if (tipshowtimer) { TRACKMOUSEEVENT tracker; tracker.cbSize=sizeof(tracker); tracker.dwFlags = TME_HOVER; tracker.hwndTrack = this->getOsWindowHandle(); tracker.dwHoverTime = TIP_TIMER_THRESHOLD; TrackMouseEvent(&tracker); }*/ } } int BaseWnd::onLeftButtonDblClk(int x, int y) { return 0; } int BaseWnd::onRightButtonDblClk(int x, int y) { return 0; } int BaseWnd::onGetFocus() { // return TRUE if you override this hasfocus = 1; notifyParent(ChildNotify::GOTFOCUS); getRootParent()->onSetRootFocus(this); invalidate(); Accessible *a = getAccessibleObject(); if (a != NULL) a->onGetFocus(); return 1; } int BaseWnd::onKillFocus() { // return TRUE if you override this hasfocus = 0; notifyParent(ChildNotify::KILLFOCUS); invalidate(); return 1; } #if defined(_WIN64) int BaseWnd::childNotify(ifc_window* child, int msg, int p1, int p2) { return 0; } #else int BaseWnd::childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2) { return 0; } #endif int BaseWnd::addDragItem(const wchar_t *droptype, void *item) { ASSERT(droptype != NULL); if (item == NULL) return -1; DragSet *set; int pos = dragCheckData(droptype); if (pos == -1) { set = new DragSet(); set->setName(droptype); dragsets.addItem(set); pos = dragsets.getNumItems() - 1; } else set = dragsets[pos]; set->addItem(item); return pos; } #ifdef _WIN32 int BaseWnd::handleDrag() { abortTip(); if (dragsets.getNumItems() == 0) return 0; Wasabi::Std::Wnd::setCapture(hwnd); SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_APPSTARTING))); dragging = 1; stickyWnd = NULL; return 1; } #endif int BaseWnd::resetDragSet() { dragsets.deleteAll(); return 1; } int BaseWnd::dragEnter(ifc_window *sourceWnd) { ifc_window *rw = getParent(); //api_window::rootwndFromRootWnd(getParent()); //FG> note to self, check! if (rw) return DI(rw).dragEnter(sourceWnd); return 0; } int BaseWnd::dragSetSticky(ifc_window *wnd, int left, int right, int up, int down) { ASSERT(dragging); stickyWnd = wnd; if (left < 0) left = 0; if (right < 0) right = 0; if (up < 0) up = 0; if (down < 0) down = 0; Wasabi::Std::setRect(&sticky, left, up, right, down); return 1; } void BaseWnd::setSuggestedDropTitle(const wchar_t *title) { ASSERT(title != NULL); suggestedTitle = title; } const wchar_t *BaseWnd::dragGetSuggestedDropTitle() { return suggestedTitle; // can be NULL } int BaseWnd::dragCheckData(const wchar_t *type, int *nitems) { for (int i = 0; i < dragsets.getNumItems(); i++) { if (!WCSICMP(type, dragsets[i]->getName())) { if (nitems != NULL) *nitems = dragsets[i]->getNumItems(); return i; } } return -1; } void *BaseWnd::dragGetData(int slot, int itemnum) { if (slot < 0 || slot >= dragsets.getNumItems()) return 0; if (itemnum < 0 || itemnum >= dragsets[slot]->getNumItems()) return 0; return dragsets[slot]->enumItem(itemnum); } void BaseWnd::addDroppedFile(const wchar_t *filename, PtrList *plist) { #ifdef RECURSE_SUBDIRS_ON_DROP const char *slash = filename + STRLEN(filename) - 1; for (; slash > filename; slash--) if (*slash == '/' || *slash == '\\') break; if (STREQL(slash + 1, ".") || STREQL(slash + 1, "..")) return ; char buf[WA_MAX_PATH] = {0}; STRCPY(buf, filename); // try to resolve shortcuts char *ext = buf + STRLEN(buf) - 1; for (; ext > buf; ext--) if (*ext == '.' || *ext == '\\' || *ext == '/') break; #ifdef WIN32 if (!STRICMP(ext, ".lnk")) { char buf2[MAX_PATH] = {0}; if (StdFile::resolveShortcut(buf, buf2)) STRCPY(buf, buf2); } #endif int isdir = 0; // handle root dir specially? WIN32_FIND_DATA data = {0}; HANDLE r = FindFirstFile(buf, &data); if (!r) return ; FindClose(r); if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) isdir = 1; if (isdir) { onExternalDropDirScan(buf); // enumerate that dir char search[WA_MAX_PATH] = {0}; wsprintf(search, "%s\\*.*", buf); HANDLE files = FindFirstFile(search, &data); if (files == INVALID_HANDLE_VALUE) return ; // nothin' in it for (;;) { wchar_t obuf[WA_MAX_PATH] = {0}; swprintf(obuf, L"%s\\%s", buf, data.cFileName); addDroppedFile(obuf, plist); if (!FindNextFile(files, &data)) { FindClose(files); return ; } } // should never get here } else { addDragItem(DD_FILENAME, plist->addItem(new FilenamePS(StringPrintfW(L"file:%s", buf)))); } #else addDragItem(DD_FILENAME, plist->addItem(new FilenamePS(StringPrintfW(L"file:%s", filename)))); #endif } bool BaseWnd::getNoCopyBits(void) { return ncb; } void BaseWnd::setNoCopyBits(bool newncb) { ncb = newncb; } int BaseWnd::onEraseBkgnd(HDC dc) { return 1; } void BaseWnd::setIcon(OSICONHANDLE icon, int _small) { Wasabi::Std::Wnd::setIcon(getOsWindowHandle(), icon, !_small); //CUT SendMessageW(getOsWindowHandle(), WM_SETICON, _small ? ICON_SMALL : ICON_BIG, (int)icon); } const wchar_t *BaseWnd::getTip() { return tip; } void BaseWnd::setTip(const wchar_t *_tooltip) { tip = _tooltip; abortTip(); } int BaseWnd::getStartHidden() { return start_hidden; } void BaseWnd::abortTip() { if (tipshowtimer) { // TODO: on the mac, use CreateMouseTrackingRegion TRACKMOUSEEVENT tracker; tracker.cbSize=sizeof(tracker); tracker.dwFlags = TME_HOVER|TME_CANCEL; tracker.hwndTrack = this->getOsWindowHandle(); tracker.dwHoverTime = TIP_TIMER_THRESHOLD; TrackMouseEvent(&tracker); } tipshowtimer = FALSE; if (tipawaytimer) killTimer(TIP_AWAY_ID); tipawaytimer = FALSE; if (tipdestroytimer) killTimer(TIP_DESTROYTIMER_ID); tipdestroytimer = FALSE; destroyTip(); tip_done = FALSE; RECT r; if (getOsWindowHandle() && Wasabi::Std::Wnd::getUpdateRect(getOsWindowHandle(), &r) != 0) // FG> avoids xoring over disapearing tip repaint(); } int BaseWnd::isVisible(int within) { if (!isVirtual() && !getOsWindowHandle()) return 0; if (!this_visible) return 0; if (within) return this_visible; // whatever, local if (isVirtual()) // virtual, global if (getParent()) return getParent()->isVisible(); else return 0; // non virtual, global if (Wasabi::Std::Wnd::isPopup(getOsWindowHandle())) return this_visible; if (!Wasabi::Std::Wnd::isValidWnd(Wasabi::Std::Wnd::getParent(getOsWindowHandle()))) return 0; if (getParent()) return getParent()->isVisible(); // not a popup, check its parent or fail return this_visible; } void BaseWnd::registerRootWndChild(ifc_window *child) { rootwndchildren.addItem(child); if (child->isVirtual()) virtualChildren.addItem(child); } void BaseWnd::unregisterRootWndChild(ifc_window *child) { delTabOrderEntry(child); rootwndchildren.removeItem(child); if (curVirtualChildCaptured == child) { setVirtualChildCapture(NULL); } if (curVirtualChildFocus == child) curVirtualChildFocus = NULL; virtualChildren.removeItem(child); //WASABI_API_WND->timer_remove(this, -1); if (isPostOnInit() && isVisible()) postDeferredCallback(DEFERREDCB_INVALIDATE, 0); } int BaseWnd::isVirtual() { return 0; } //CUT?inline int isInRect(RECT *r,int x,int y) { //CUT? if (x>=r->left&&x<=r->right&&y>=r->top&&y<=r->bottom) return 1; //CUT? return 0; //CUT?} int BaseWnd::ensureVirtualCanvasOk() { RECT ncr; if (isVirtual() && getParent()) return 1; int size_w = rwidth; int size_h = rheight; if (!size_w || !size_h) return 0; if (!virtualCanvas || virtualCanvasH != size_h || virtualCanvasW != size_w) { if (virtualCanvas) { deleteFrameBuffer(virtualCanvas); virtualCanvas = NULL; } delete scalecanvas; scalecanvas = NULL; virtualCanvas = createFrameBuffer(size_w, size_h); prepareFrameBuffer(virtualCanvas, size_w, size_h); virtualCanvas->setBaseWnd(this); virtualCanvasH = size_h; virtualCanvasW = size_w; BaseWnd::getNonClientRect(&ncr); deferedInvalidateRect(&ncr); } return 1; } Canvas *BaseWnd::createFrameBuffer(int w, int h) { return new BltCanvas(w, h, getOsWindowHandle()); } void BaseWnd::prepareFrameBuffer(Canvas *canvas, int w, int h) { RECT r = {0, 0, w, h}; RegionI reg(&r); virtualBeforePaint(®); #ifdef _WIN32 canvas->selectClipRgn(NULL); canvas->fillRect(&r, 0); #elif defined(__APPLE__) CGContextClearRect(canvas->getHDC(), CGRectInfinite); // TODO: make "clear" function in canvas #endif virtualAfterPaint(®); } void BaseWnd::deleteFrameBuffer(Canvas *canvas) { delete canvas; } // paints the client content, followed by the virtual child tree. recursive int BaseWnd::paintTree(Canvas *canvas, api_region *r) { onPaint(canvas, r); #ifdef WASABI_DRAW_FOCUS_RECT if (gotFocus()) { RECT ncr; getNonClientRect(&ncr); // try to use skinned focus rect if (WASABI_API_WND->paintset_present(Paintset::FOCUSRECT)) WASABI_API_WND->paintset_render(Paintset::FOCUSRECT, canvas, &ncr, 128); else // otherwise this looks kinda nice :P canvas->drawRect(&ncr, 0, 0xFFFFFF, 128); } #endif if (isVirtual() && !hasVirtualChildren()) return 0; api_region *hostrgn = NULL; api_region *update = r; if (!(hwnd != NULL && getParent() == NULL)) { hostrgn = getRegion(); update = r->clone(); if (hostrgn && !isRectRgn()) { RECT ncr = clientRect(); api_region *hostclone = hostrgn->clone(); hostclone->addRegion(getComposedRegion()); hostclone->offset(ncr.left, ncr.top); update->andRegion(hostclone); hostrgn->disposeClone(hostclone); } } RegionI client_update; for (int i = 0;i < virtualChildren.getNumItems();i++) { if (!virtualChildren[i]->isVisible(1)) continue; RECT rChild; ifc_window *w = virtualChildren[i]; w->getNonClientRect(&rChild); if ((rChild.right != rChild.left) && (rChild.bottom != rChild.top)) if (update->intersectRect(&rChild, &client_update)) { w->paintTree(canvas, &client_update); } } if (update != r) r->disposeClone(update); return 1; } void BaseWnd::setVirtualCanvas(Canvas *c) { virtualCanvas = c; } int BaseWnd::pointInWnd(POINT *p) { RECT r; if (!isVisible(1)) return 0; getWindowRect(&r); if (!Wasabi::Std::pointInRect(r, *p)) return 0; for (int i = 0; i < getNumRootWndChildren(); i++) { ifc_window *c = enumRootWndChildren(i); if (!c->isVisible(1)) continue; RECT rChild; c->getWindowRect(&rChild); if (Wasabi::Std::pointInRect(rChild, *p)) return 0; } //NONPORTABLE /* HWND child = GetWindow(getOsWindowHandle(), GW_CHILD); while (child != NULL) { if (IsWindowVisible(child)) { RECT r2; GetWindowRect(child, &r2); if (Std::pointInRect(r2, *p)) return 0; } child = GetWindow(child, GW_HWNDNEXT); }*/ return 1; } int BaseWnd::paint(Canvas *c, api_region *r) { if (isVirtual()) { RegionI d; RECT cr; getClientRect(&cr); if (r == NULL) { d.addRect(&cr); } else { d.addRegion(r); d.offset(cr.left, cr.top); } ifc_window *rp = getRootParent(); deferedInvalidate(); rp->paint(NULL, &d); BltCanvas *cc = static_cast(rp->getFrameBuffer()); if (r != NULL) c->selectClipRgn(r); cc->blit(cr.left, cr.top, c, 0, 0, cr.right - cr.left, cr.bottom - cr.top); return 1; } if (!ensureVirtualCanvasOk()) return 0; RegionI *deleteme = NULL; if (r == NULL) { RECT cr; getNonClientRect(&cr); deleteme = new RegionI(&cr); r = deleteme; } virtualBeforePaint(r); RECT rcPaint; r->getBox(&rcPaint); double ra = getRenderRatio(); if (deferedInvalidRgn) { api_region *nr = NULL; if (renderRatioActive()) { nr = r->clone(); double d = 1.0 / ra; nr->scale(d, d, TRUE); } if (deferedInvalidRgn->isEmpty() == 0) { // some deferednvalidated regions needs to be repainted // TODO: need a "clear region" function in canvas api_region *i = deferedInvalidRgn->clone(); #ifdef _WIN32 FillRgn(virtualCanvas->getHDC(), i->getOSHandle(), (HBRUSH)GetStockObject(BLACK_BRUSH)); #elif defined(__APPLE__) CGContextSaveGState(virtualCanvas->getHDC()); virtualCanvas->selectClipRgn(i); CGContextClearRect(virtualCanvas->getHDC(), CGRectInfinite); // virtualCanvas->selectClipRgn(0); CGContextRestoreGState(virtualCanvas->getHDC()); #endif paintTree(virtualCanvas, i); deferedValidateRgn(i); deferedInvalidRgn->disposeClone(i); } if (nr) r->disposeClone(nr); } virtualAfterPaint(r); if (c != NULL) { commitFrameBuffer(c, &rcPaint, ra); //TH WDP2-212 } delete deleteme; return 1; } int BaseWnd::virtualOnPaint() { #ifdef _WIN32 RECT cr; getNonClientRect(&cr); if (cr.left >= cr.right || cr.top >= cr.bottom) return 0; if (!ensureVirtualCanvasOk()) return 0; RegionI reg; //CUT GetUpdateRgn(getOsWindowHandle(), r->getOSHandle(), FALSE); Wasabi::Std::Wnd::getUpdateRegion(getOsWindowHandle(), reg.getOSHandle()); PaintCanvas paintcanvas; if (!paintcanvas.beginPaint(this)) { virtualAfterPaint(®); return 0; } // DO NOT DELETE - This looks like it does nothing, but it actually makes the GDI call us again with WM_PAINT if some window // moves over this one between BeginPaint and EndPaint. We still use GetUpdateRgn so we don't have to check for // the version of Windows. See doc. If this function is not available (should be here in 95/98/NT/2K, but we never know) // then we use the rcPaint rect... less precise, but still works. //CUT if (getRandomRgn) { if (Wasabi::Std::Wnd::haveGetRandomRegion()) { RegionI zap; //CUT getRandomRgn(paintcanvas.getHDC(), zap.getOSHandle(), SYSRGN); Wasabi::Std::Wnd::getRandomRegion(paintcanvas.getHDC(), zap.getOSHandle()); } else { RECT z; paintcanvas.getRcPaint(&z); reg.setRect(&z); } // ------------- /*// for debug HDC dc = GetDC(getOsWindowHandle()); InvertRgn(dc, r->getHRGN()); InvertRgn(dc, r->getHRGN()); ReleaseDC(getOsWindowHandle(), dc);*/ paint(&paintcanvas, ®); #else #warning port me or remove me #endif return 1; } ifc_window *BaseWnd::enumVirtualChild(int _enum) { return virtualChildren[_enum]; } int BaseWnd::getNumVirtuals() { return virtualChildren.getNumItems(); } ifc_window *BaseWnd::enumRootWndChildren(int n) { return rootwndchildren.enumItem(n); } int BaseWnd::getNumRootWndChildren() { return rootwndchildren.getNumItems(); } ifc_window *BaseWnd::findRootWndChild(int x, int y, int only_virtuals) { for (int i = getNumRootWndChildren() - 1; i > -1; i--) { RECT r; ifc_window *child = enumRootWndChildren(i); //DebugStringW(L"findRootWndChild = entering = %s\n", child->getId()); if (only_virtuals && !child->isVirtual()) continue; child->getNonClientRect(&r); int _x = x; int _y = y; if (!child->isVirtual()) { POINT pt; child->getPosition(&pt); _x -= pt.x; _y -= pt.y; } int iv = child->isVisible(1); //int gpa = child->getPaintingAlpha(); POINT _p = Wasabi::Std::makePoint(_x, _y); if (iv /*&& gpa > 0*/ && Wasabi::Std::pointInRect(r, _p)) { // GROUP ifc_window *z = child->findRootWndChild(_x, _y); if (z) return z; } /*gpa > 0 &&*/ /*if (iv && _x>=r.left&&_x<=r.right&&_y>=r.top&&_y<=r.bottom && !child->isClickThrough() && child->ptInRegion(_x, _y)) { return child; }*/ } return (!isClickThrough() && ptInRegion(x, y)) ? this : NULL; } //PORTME int BaseWnd::handleVirtualChildMsg(UINT uMsg, int x, int y, void *p, void *d) { #ifdef _WIN32 ifc_window *child = NULL; if (curVirtualChildCaptured) child = curVirtualChildCaptured; else child = findRootWndChild(x, y, 1); // warning, can return this which is not virtual // ASSERT(child != NULL); // BU this came up and I don't know why, looks like it should never happen // FG> actually it can happen when coming back from a popup menu when cpu usage is high, the window might be // hidden (destroying) and ptInRegion returns false. if (!child) return 0; //int isvirtual = child->isVirtual(); if (child) child = child->getForwardWnd(); if (child && child->isEnabled()) { switch (uMsg) { case WM_LBUTTONDOWN: /* if (isvirtual && child != curVirtualChildFocus) focusVirtualChild(child);*/ autoFocus(child); if (child->wantLeftClicks()) child->onLeftButtonDown(x, y); if (child->checkDoubleClick(uMsg, x, y) && child->wantDoubleClicks()) child->onLeftButtonDblClk(x, y); return 1; case WM_RBUTTONDOWN: /* if (isvirtual && child != curVirtualChildFocus) focusVirtualChild(child);*/ autoFocus(child); if (child->wantRightClicks()) child->onRightButtonDown(x, y); if (child->checkDoubleClick(uMsg, x, y) && child->wantDoubleClicks()) child->onRightButtonDblClk(x, y); return 1; case WM_LBUTTONUP: if (child->wantLeftClicks()) child->onLeftButtonUp(x, y); return 1; case WM_RBUTTONUP: if (child->wantRightClicks()) child->onRightButtonUp(x, y); return 1; case WM_MOUSEMOVE: { if (curVirtualChildCaptured == child || (curVirtualChildCaptured == NULL)) { if (child->wantMouseMoves()) child->onMouseMove(x, y); return 1; } return 0; } case WM_MOUSEHOVER: ((BaseWnd *)child)->onTip(); break; case WM_SETCURSOR: int a = child->getCursorType(x, y); if (!p) return 0; *(int *)p = a; if (a == BASEWND_CURSOR_USERSET) { OSCURSORHANDLE c = child->getCustomCursor(x, y); if (!d) return 0; *(OSCURSORHANDLE *)d = c; } return 1; } } #else #warning port me or remove me #endif return 0; } int BaseWnd::onLeftButtonDown(int x, int y) { disable_tooltip_til_recapture = 1; abortTip(); return 0; } int BaseWnd::onLeftButtonUp(int x, int y) { disable_tooltip_til_recapture = 1; abortTip(); return 0; } void BaseWnd::setVirtualChildCapture(ifc_window *child) { if (child) { if (!inputCaptured) { beginCapture(); } } else { endCapture(); } curVirtualChildCaptured = child; } ifc_window *BaseWnd::getVirtualChildCapture() { if (inputCaptured && Wasabi::Std::Wnd::getCapture() == getOsWindowHandle()) return curVirtualChildCaptured; else if (inputCaptured) inputCaptured = 0; return NULL; } ifc_window *BaseWnd::getBaseTextureWindow() { // return our base texture window if we have it if (btexture) return btexture; // return our parent's if they have it if (getParent()) return getParent()->getBaseTextureWindow(); else return NULL; } void BaseWnd::renderBaseTexture(ifc_canvas *c, const RECT &r, int alpha) { WASABI_API_WND->skin_renderBaseTexture(getBaseTextureWindow(), c, r, this, alpha); } void BaseWnd::setBaseTextureWindow(ifc_window *w) { btexture = w; } void BaseWnd::setNotifyWindow(ifc_window *newnotify) { notifyWindow = newnotify; } ifc_window *BaseWnd::getNotifyWindow() { return destroying ? NULL : notifyWindow; } int BaseWnd::gotFocus() { return hasfocus && curVirtualChildFocus == NULL; } int BaseWnd::isActive() { OSWINDOWHANDLE h = hwnd; if (h == NULL) { ifc_window *par = getParent(); if (par == NULL) return 0; h = par->getOsWindowHandle(); } if (h == NULL) return 0; return (Wasabi::Std::Wnd::getActiveWindow() == h); } int BaseWnd::onChar(unsigned int c) { switch (c) { case 9: // TAB if (Std::keyModifier(STDKEY_SHIFT)) focusPrevious(); else focusNext(); return 1; } return 0; } /*int BaseWnd::focusVirtualChild(api_window *child) { if (!gotFocus()) setFocus(); if (!child->wantFocus()) return 0; setVirtualChildFocus(child); return 1; }*/ int BaseWnd::wantFocus() { return 0; } // Return 1 if there is a modal window that is not this int BaseWnd::checkModal() { if (bypassModal()) return 0; ifc_window *w = WASABI_API_WND->getModalWnd(); if (w && w != static_cast(this) && w != getDesktopParent()) { return 1; } return 0; } int BaseWnd::cascadeRepaintFrom(ifc_window *who, int pack) { RECT r; BaseWnd::getNonClientRect(&r); return BaseWnd::cascadeRepaintRect(&r, pack); } int BaseWnd::cascadeRepaint(int pack) { return cascadeRepaintFrom(this, pack); } int BaseWnd::cascadeRepaintRgn(api_region *r, int pack) { return cascadeRepaintRgnFrom(r, this, pack); } int BaseWnd::cascadeRepaintRect(RECT *r, int pack) { return cascadeRepaintRectFrom(r, this, pack); } int BaseWnd::cascadeRepaintRectFrom(RECT *r, ifc_window *who, int pack) { RegionI reg(r); int rt = cascadeRepaintRgnFrom(®, who, pack); return rt; } void BaseWnd::_cascadeRepaintRgn(api_region *rg) { if (!ensureVirtualCanvasOk()) return ; WndCanvas paintcanvas; if (paintcanvas.attachToClient(this) == 0) return; virtualBeforePaint(rg); deferedInvalidateRgn(rg); paintTree(virtualCanvas, rg); virtualAfterPaint(rg); double ra = getRenderRatio(); RECT rcPaint; rg->getBox(&rcPaint); RECT rc; getClientRect(&rc); //JF> this gets it in virtual (non-scaled) coordinates, // so we need to do these comparisons before scaling. rcPaint.bottom = MIN((int)rc.bottom, (int)rcPaint.bottom); rcPaint.right = MIN((int)rc.right, (int)rcPaint.right); if (renderRatioActive()) // probably faster than scaling the clone { rcPaint.left = (int)((rcPaint.left - 1) * ra); rcPaint.top = (int)((rcPaint.top - 1) * ra); rcPaint.right = (int)(rcPaint.right * ra + 0.999999); rcPaint.bottom = (int)(rcPaint.bottom * ra + 0.999999); } rcPaint.left = MAX(0, (int)rcPaint.left); rcPaint.top = MAX(0, (int)rcPaint.top); rcPaint.right = MIN((int)rcPaint.right, (int)(rwidth * ra)); rcPaint.bottom = MIN((int)rcPaint.bottom, (int)(rheight * ra)); commitFrameBuffer(&paintcanvas, &rcPaint, ra); } void BaseWnd::packCascadeRepaintRgn(api_region *rg) { if (!deferedCascadeRepaintRgn) deferedCascadeRepaintRgn = new RegionI; deferedCascadeRepaintRgn->addRegion(rg); need_flush_cascaderepaint = 1; } int BaseWnd::cascadeRepaintRgnFrom(api_region *_rg, ifc_window *who, int pack) { api_region *rg = _rg->clone(); int j = virtualChildren.searchItem(who); for (int i = 0; i < virtualChildren.getNumItems(); i++) { ifc_window *w = virtualChildren[i]; if (w != who && w->wantSiblingInvalidations()) w->onSiblingInvalidateRgn(rg, who, j, i); } if (!pack) { _cascadeRepaintRgn(rg); } else { packCascadeRepaintRgn(rg); } _rg->disposeClone(rg); return 1; } void BaseWnd::setDesktopAlpha(int a) { if (a && !Wasabi::Std::Wnd::isDesktopAlphaAvailable()) return ; if (a == w2k_alpha) return ; w2k_alpha = a; if (!a && scalecanvas) { delete scalecanvas; scalecanvas = NULL; } setLayeredWindow(w2k_alpha); onSetDesktopAlpha(a); } void BaseWnd::onSetDesktopAlpha(int a) { } void BaseWnd::commitFrameBuffer(Canvas *paintcanvas, RECT *r, double ra) { if (w2k_alpha && Wasabi::Std::Wnd::isDesktopAlphaAvailable() && !cloaked) { //CUT BLENDFUNCTION blend= {AC_SRC_OVER, 0, wndalpha, AC_SRC_ALPHA }; //CUT POINT pt={0,0}; RECT spr; getWindowRect(&spr); //CUT POINT sp={spr.left,spr.top}; //CUT SIZE ss={spr.right-spr.left, spr.bottom-spr.top}; int sw = spr.right - spr.left, sh = spr.bottom - spr.top; //CUT SysCanvas c; if (handleRatio() && renderRatioActive()) { // eek slow! RECT r; getWindowRect(&r); int w = r.right - r.left; int h = r.bottom - r.top; if (!scalecanvas) scalecanvas = new BltCanvas(w, h, getOsWindowHandle()); virtualCanvas->stretchblit(0, 0, (int)((double)virtualCanvasW * 65536.0), (int)((double)virtualCanvasH * 65536.0), scalecanvas, 0, 0, w, h); } //CUT updateLayeredWindow(hwnd, c.getHDC(), &sp, &ss, (scalecanvas ? scalecanvas : virtualCanvas)->getHDC(), &pt, 0, &blend, ULW_ALPHA); Wasabi::Std::Wnd::updateLayeredWnd(hwnd, spr.left, spr.top, sw, sh, (scalecanvas ? scalecanvas : virtualCanvas)->getHDC(), wndalpha); } else { if (ABS(ra - 1.0) <= 0.01) { virtualCanvas->blit(r->left, r->top, paintcanvas, r->left, r->top, r->right - r->left, r->bottom - r->top); } else { RECT tr = *r; double invra = 65536.0 / ra; int lp = tr.left; int tp = tr.top; int w = tr.right - tr.left; int h = tr.bottom - tr.top; int sx = (int)((double)lp * invra); int sy = (int)((double)tp * invra); int sw = (int)((double)w * invra); int sh = (int)((double)h * invra); virtualCanvas->stretchblit(sx, sy, sw, sh, paintcanvas, lp, tp, w, h); } } } void BaseWnd::flushPaint() { postDeferredCallback(DEFERREDCB_FLUSHPAINT, 0); } void BaseWnd::do_flushPaint() { if (!deferedInvalidRgn || deferedInvalidRgn->isEmpty()) return ; api_region *r = deferedInvalidRgn->clone(); cascadeRepaintRgn(r); deferedInvalidRgn->disposeClone(r); deferedInvalidRgn->empty(); } int BaseWnd::isMouseOver(int x, int y) { POINT pt = {x, y}; clientToScreen(&pt); return (WASABI_API_WND->rootWndFromPoint(&pt) == this); } void BaseWnd::freeResources() {} void BaseWnd::reloadResources() { invalidate(); } double BaseWnd::getRenderRatio() { if (!handleRatio()) return 1.0; if (!ratiolinked) return ratio; return getParent() ? getParent()->getRenderRatio() : ratio; } void BaseWnd::setRenderRatio(double r) { // "snap" to 1.0 if (ABS(r - 1.0) <= 0.02f) r = 1.0; if (scalecanvas) { delete scalecanvas; scalecanvas = NULL; } if (isInited() && r != ratio && !isVirtual() && (!getParent() || !ratiolinked)) { // must scale size & region accordingly RECT rc; BaseWnd::getWindowRect(&rc); rc.right = rc.left + rwidth; rc.bottom = rc.top + rheight; ratio = r; resize(&rc); invalidate(); if (isPostOnInit()) onRatioChanged(); } } void BaseWnd::setRatioLinked(int l) { ratiolinked = l; if (isPostOnInit()) setRenderRatio(ratio); } int BaseWnd::renderRatioActive() { return ABS(getRenderRatio() - 1.0) > 0.01f; } void BaseWnd::multRatio(int *x, int *y) { double rr = getRenderRatio(); if (x) *x = (int)((double)(*x) * rr); if (y) *y = (int)((double)(*y) * rr); } void BaseWnd::multRatio(RECT *r) { Wasabi::Std::scaleRect(r, getRenderRatio()); } void BaseWnd::divRatio(int *x, int *y) { double rr = getRenderRatio(); if (x) *x = (int)((double)(*x) / rr + 0.5); if (y) *y = (int)((double)(*y) / rr + 0.5); } void BaseWnd::divRatio(RECT *r) { double rr = getRenderRatio(); Wasabi::Std::scaleRect(r, 1./rr); } void BaseWnd::bringVirtualToFront(ifc_window *w) { changeChildZorder(w, 0); } void BaseWnd::bringVirtualToBack(ifc_window *w) { changeChildZorder(w, virtualChildren.getNumItems()-1); } void BaseWnd::bringVirtualAbove(ifc_window *w, ifc_window *b) { ASSERT(b->isVirtual()); int p = virtualChildren.searchItem(b); if (p == -1) return ; changeChildZorder(w, p); } void BaseWnd::bringVirtualBelow(ifc_window *w, ifc_window *b) { ASSERT(b->isVirtual()); int p = virtualChildren.searchItem(b); if (p == -1) return ; changeChildZorder(w, p + 1); } void BaseWnd::changeChildZorder(ifc_window *w, int newpos) { int p = newpos; p = MAX(p, (int)0); p = MIN(p, virtualChildren.getNumItems()-1); RECT cr; w->getClientRect(&cr); PtrList l; int i; for (i = 0;i < virtualChildren.getNumItems();i++) if (virtualChildren[i] != w) l.addItem(virtualChildren[i]); p = virtualChildren.getNumItems() - newpos - 1; virtualChildren.removeAll(); int done = 0; for (i = 0;i < l.getNumItems();i++) if (i == p && !done) { virtualChildren.addItem(w); i--; done++; } else { RECT dr, intersection; l.enumItem(i)->getClientRect(&dr); if (Wasabi::Std::rectIntersect(intersection, dr, &cr)) l[i]->invalidateRect(&intersection); virtualChildren.addItem(l.enumItem(i)); } if (i == p && !done) virtualChildren.addItem(w); w->invalidate(); } int BaseWnd::onActivate() { if (hasVirtualChildren()) { int l = getNumVirtuals(); for (int i = 0; i < l; i++) { ifc_window *r = enumVirtualChild(i); r->onActivate(); } } return 0; } int BaseWnd::onDeactivate() { if (hasVirtualChildren()) { int l = getNumVirtuals(); for (int i = 0; i < l; i++) { ifc_window *r = enumVirtualChild(i); r->onDeactivate(); } } return 0; } int BaseWnd::getDesktopAlpha() { return w2k_alpha; } api_region *BaseWnd::getRegion() { return NULL; } //CUT int BaseWnd::isTransparencyAvailable() { //CUT #ifdef WIN32 //CUT #else //CUT #pragma warning port me! //CUT #endif //CUT return 0; //CUT } int BaseWnd::handleTransparency() { return 1; // by default all windows handle transparency, only windows blitting directly on the SCREEN (if you blit directly on the DC it's still ok), } // for instance, a vis or a video using overlay should return 0, this will let the layout auto manage its alpha as that window is shown/hiden void BaseWnd::setAlpha(int active, int inactive) { if (active == 254) active = 255; if (active == 1) active = 0; if (inactive == 254) inactive = 255; if (inactive == 1) inactive = 0; int oldactivealpha = activealpha; active = MIN(255, MAX(0, active)); if (inactive != -1) inactive = MIN(255, MAX(0, inactive)); if (active != activealpha) { activealpha = active; if (isActive()) { invalidate(); if ((oldactivealpha == 0 || activealpha == 0) && (oldactivealpha != 0 || activealpha != 0)) invalidateWindowRegion(); } } if (inactive == -1) inactive = active; if (inactive != inactivealpha) { inactivealpha = inactive; if (!isActive()) { invalidate(); if ((oldactivealpha == 0 || activealpha == 0) && (oldactivealpha != 0 || activealpha != 0)) invalidateWindowRegion(); } } } void BaseWnd::getAlpha(int *active, int *inactive) { if (active) *active = activealpha; if (inactive) *inactive = inactivealpha; } int BaseWnd::getPaintingAlpha(void) { int a = isActive() ? MIN(255, MAX(0, activealpha)) : MIN(255, MAX(0, inactivealpha)); ASSERT(a >= 0 && a <= 255); if (getParent() && getParent()->isVirtual()) { int b = getParent()->getPaintingAlpha(); a = (int)((double)a / 255.0 * (double)b); } if (a == 254) a = 255; if (a == 1) a = 0; if (!isEnabled()) a = (int)(a*0.6); return a; } void BaseWnd::setClickThrough(int ct) { clickthrough = ct; } int BaseWnd::isClickThrough() { return clickthrough; } int BaseWnd::handleRatio() { return 1; } #include int BaseWnd::createTip() { destroyTip(); tooltip = new Tooltip(getTip()); return -1; } void BaseWnd::destroyTip() { // this is to avoid pb if destroytip() is being called by a time while destroying tip Tooltip *tt = tooltip; tooltip = NULL; delete tt; } int BaseWnd::runModal() { //PORTME #ifdef _WIN32 ifc_window *dp = getDesktopParent(); if (dp && dp != this) return dp->runModal(); MSG msg; // SetCapture(NULL); SetFocus(getOsWindowHandle()); WASABI_API_WND->pushModalWnd(this); returnvalue = 0; mustquit = 0; // Main message loop: while (!mustquit) { mustquit = !GetMessage(&msg, NULL, 0, 0); if (!msg.hwnd || !TranslateAccelerator(msg.hwnd, NULL, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } WASABI_API_WND->popModalWnd(this); // SetCapture(NULL); return returnvalue; #else #warning port me return 0; #endif } void BaseWnd::endModal(int ret) { ifc_window *dp = getDesktopParent(); if (dp && dp != this) { dp->endModal(ret); return ; } returnvalue = ret; mustquit = 1; } int BaseWnd::wantAutoContextMenu() { return 1; } void BaseWnd::onCancelCapture() {} ifc_window *BaseWnd::getNextVirtualFocus(ifc_window *w) { if (w == NULL) { if (childtabs.getNumItems() > 0) return childtabs.getFirst()->wnd; } int a = getTabOrderEntry(w) + 1; if (a < childtabs.getNumItems()) return childtabs.enumItem(a)->wnd; return NULL; } void BaseWnd::setVirtualChildFocus(ifc_window *w) { ASSERT(w && w->isVirtual()); if (curVirtualChildFocus) curVirtualChildFocus->onKillFocus(); curVirtualChildFocus = w; onSetRootFocus(w); Wasabi::Std::Wnd::setFocus(getOsWindowHandle()); if (curVirtualChildFocus) curVirtualChildFocus->onGetFocus(); } int BaseWnd::ptInRegion(int x, int y) { RECT cr; getNonClientRect(&cr); POINT pt = {x - cr.left, y - cr.top}; api_region *reg = getRegion(); if (isRectRgn()) return (x >= cr.left && x <= cr.right && y >= cr.top && y <= cr.bottom); return reg ? reg->ptInRegion(&pt) : 0; } api_region *BaseWnd::getComposedRegion() { ensureWindowRegionValid(); return composedrgn; } api_region *BaseWnd::getSubtractorRegion() { ensureWindowRegionValid(); return subtractorrgn; } int BaseWnd::ensureWindowRegionValid() { if (!isInited()) return 0; if (wndregioninvalid) { computeComposedRegion(); return 1; } return 0; } void BaseWnd::invalidateWindowRegion() { wndregioninvalid = 1; if (getParent()) getParent()->invalidateWindowRegion(); } void BaseWnd::computeComposedRegion() { if (!isPostOnInit()) return ; wndregioninvalid = 0; RECT r; getNonClientRect(&r); api_region *reg = getRegion(); RegionI *_reg = NULL; if (!reg) { _reg = new RegionI; reg = _reg; if (isRectRgn()) reg->setRect(&r); } else if (isRectRgn()) reg->setRect(&r); api_region *wr = reg->clone(); if (!subtractorrgn) subtractorrgn = new RegionI(); subtractorrgn->empty(); if (!composedrgn) composedrgn = new RegionI; composedrgn->empty(); RegionI *subme = NULL; RegionI *andme = NULL; RegionI *orme = NULL; // if subregion is now empty, we need to only use our region RECT gr; getNonClientRect(&gr); for (int i = 0;i < virtualChildren.getNumItems();i++) { ifc_window *srw = virtualChildren.enumItem(i); if (!srw->isVisible(1) || srw->getPaintingAlpha() == 0) continue; if (srw->getRegionOp() != REGIONOP_NONE) { api_region *sr = srw->getComposedRegion(); if (sr) { api_region *osr = sr->clone(); RECT r; srw->getNonClientRect(&r); r.left -= gr.left; r.top -= gr.top; osr->offset(r.left, r.top); /* sr->debug(); osr->debug();*/ if (srw->getRegionOp() == REGIONOP_OR) { if (!orme) orme = new RegionI; orme->addRegion(osr); } else if (srw->getRegionOp() == REGIONOP_AND) { if (!andme) andme = new RegionI; andme->addRegion(osr); } else if (srw->getRegionOp() == REGIONOP_SUB) { if (!subme) subme = new RegionI; subme->addRegion(osr); } else if (srw->getRegionOp() == REGIONOP_SUB2) { if (!subme) subme = new RegionI; subtractorrgn->addRegion(osr); } sr->disposeClone(osr); } } api_region *sr = srw->getSubtractorRegion(); if (sr != NULL && !sr->isEmpty()) { api_region *osr = sr->clone(); RECT r; srw->getNonClientRect(&r); r.left -= gr.left; r.top -= gr.top; osr->offset(r.left, r.top); subtractorrgn->addRegion(osr); sr->disposeClone(osr); } } if (andme) { wr->andRegion(andme); delete andme; } if (orme) { wr->addRegion(orme); delete orme; } if (subme) { wr->subtractRgn(subme); delete subme; } composedrgn->addRegion(wr); reg->disposeClone(wr); delete _reg; } void BaseWnd::updateWindowRegion() { if (!isPostOnInit() || isVirtual()) return ; if (getDesktopAlpha()) { // if desktopalpha is on, we can't use regions (thanks MS), we have to rely on the framebuffer correctness //CUT SetWindowRgn(getOsWindowHandle(), NULL, FALSE); Wasabi::Std::Wnd::setWndRegion(getOsWindowHandle(), NULL); return ; } api_region *_r = getComposedRegion(); api_region *_s = getSubtractorRegion(); ASSERT(_r != NULL && _s != NULL); api_region *z = _r->clone(); z->subtractRgn(_s); assignWindowRegion(z); _r->disposeClone(z); } // wr is NOT scaled!!! void BaseWnd::assignWindowRegion(api_region *wr) { ASSERT(wr != NULL); if (!isPostOnInit()) return ; int isrect = wr->isRect(); RECT r; BaseWnd::getWindowRect(&r); //DebugStringW( L"\nBaseWnd::assignWindowRegion() r before - x = %d, y = %d, w = %d, h = %d \n", r.left, r.top, r.right - r.left, r.bottom - r.top ); r.right -= r.left; r.left = 0; r.bottom -= r.top; r.top = 0; //DebugStringW( L"BaseWnd::assignWindowRegion() r after - x = %d, y = %d, w = %d, h = %d \n", r.left, r.top, r.right - r.left, r.bottom - r.top ); RECT z; wr->getBox(&z); //DebugStringW( L"BaseWnd::assignWindowRegion() z before - x = %d, y = %d, w = %d, h = %d \n", z.left, z.top, z.right - z.left, z.bottom - z.top ); z.left = 0; z.top = 0; //DebugStringW( L"BaseWnd::assignWindowRegion() z after - x = %d, y = %d, w = %d, h = %d \n", z.left, z.top, z.right - z.left, z.bottom - z.top ); if (renderRatioActive()) { double i = getRenderRatio(); wr->scale(i, i, FALSE); } RECT sz; wr->getBox(&sz); //DebugStringW( L"BaseWnd::assignWindowRegion() sz before - x = %d, y = %d, w = %d, h = %d \n", sz.left, sz.top, sz.right - sz.left, sz.bottom - sz.top ); sz.right -= sz.left; sz.bottom -= sz.top; sz.left = 0; sz.top = 0; //DebugStringW( L"BaseWnd::assignWindowRegion() sz after - x = %d, y = %d, w = %d, h = %d \n", sz.left, sz.top, sz.right - sz.left, sz.bottom - sz.top ); if (isrect && ((z.right == rwidth && z.bottom == rheight) || (sz.left == r.left && sz.right == r.right && sz.top == r.top && sz.bottom == r.bottom) || (0) ) ) { //CUT SetWindowRgn(getOsWindowHandle(), NULL, TRUE); if (!lastnullregion) { Wasabi::Std::Wnd::setWndRegion(getOsWindowHandle(), NULL, TRUE); lastnullregion = 1; } } else { //DebugStringW(L"setting region, rwidth = %d, rheight = %d, z.right = %d, z.bottom = %d\n", rwidth, rheight, z.right, z.bottom); //CUT SetWindowRgn(getOsWindowHandle(), wr->makeWindowRegion(), TRUE); Wasabi::Std::Wnd::setWndRegion(getOsWindowHandle(), wr->makeWindowRegion(), TRUE); lastnullregion = 0; } } void BaseWnd::performBatchProcesses() { // recompute the window region if needed and apply it to the HWND if (wndregioninvalid && !isVirtual()) if (ensureWindowRegionValid()) updateWindowRegion(); if (need_flush_cascaderepaint) { _cascadeRepaintRgn(deferedCascadeRepaintRgn); deferedCascadeRepaintRgn->empty(); need_flush_cascaderepaint = 0; } } int BaseWnd::getRegionOp() { return regionop; } void BaseWnd::setRegionOp(int op) { if (regionop != op) { regionop = op; invalidateWindowRegion(); } } int BaseWnd::isRectRgn() { return rectrgn; } void BaseWnd::setRectRgn(int i) { rectrgn = i; } TimerClient *BaseWnd::timerclient_getMasterClient() { if (!isVirtual()) return this; ifc_window *w = getParent(); if (w) { TimerClient *tc = w->getTimerClient(); if (tc) return tc->timerclient_getMasterClient(); } return NULL; } void BaseWnd::timerclient_onMasterClientMultiplex() { performBatchProcesses(); } TimerClient *BaseWnd::getTimerClient() { return this; } ifc_dependent *BaseWnd::rootwnd_getDependencyPtr() { return this; } ifc_dependent *BaseWnd::timerclient_getDependencyPtr() { return this; } void BaseWnd::addMinMaxEnforcer(ifc_window *w) { minmaxEnforcers.addItem(w); signalMinMaxEnforcerChanged(); } void BaseWnd::removeMinMaxEnforcer(ifc_window *w) { minmaxEnforcers.removeItem(w); signalMinMaxEnforcerChanged(); } void BaseWnd::signalMinMaxEnforcerChanged(void) { ifc_window *w = getDesktopParent(); if (w == NULL || w == this) onMinMaxEnforcerChanged(); else w->signalMinMaxEnforcerChanged(); } int BaseWnd::getNumMinMaxEnforcers() { return minmaxEnforcers.getNumItems(); } ifc_window *BaseWnd::enumMinMaxEnforcer(int n) { return minmaxEnforcers.enumItem(n); } int BaseWnd::onAction(const wchar_t *action, const wchar_t *param, int x, int y, intptr_t p1, intptr_t p2, void *data, size_t datalen, ifc_window *source) { return 1; } int BaseWnd::sendAction(ifc_window *target, const wchar_t *action, const wchar_t *param, int x, int y, intptr_t p1, intptr_t p2, void *data, size_t datalen) { ASSERT(target != NULL); return target->onAction(action, param, x, y, p1, p2, data, datalen, this); } int BaseWnd::virtualBeforePaint(api_region *r) { if (!virtualCanvas) return 0; PaintCallbackInfoI pc(virtualCanvas, r); dependent_sendEvent(BaseWnd::depend_getClassGuid(), Event_ONPAINT, PaintCallback::BEFOREPAINT, &pc); return 1; } int BaseWnd::virtualAfterPaint(api_region *r) { if (!virtualCanvas) return 0; PaintCallbackInfoI pc(virtualCanvas, r); dependent_sendEvent(BaseWnd::depend_getClassGuid(), Event_ONPAINT, PaintCallback::AFTERPAINT, &pc); return 1; } int BaseWnd::timerclient_onDeferredCallback(intptr_t p1, intptr_t p2) { TimerClientI::timerclient_onDeferredCallback(p1, p2); return onDeferredCallback(p1, p2); } void BaseWnd::timerclient_timerCallback(int id) { TimerClientI::timerclient_timerCallback(id); timerCallback(id); } int BaseWnd::setTimer(int id, int ms) { return timerclient_setTimer(id, ms); } int BaseWnd::killTimer(int id) { return timerclient_killTimer(id); } void BaseWnd::postDeferredCallback(intptr_t p1, intptr_t p2, int mindelay) { #ifdef _WIN32 // TODO: re-enable, but post to some other window (e.g. some singleton window), not this window // because our message pump might be blocked // maybe make a hidden window in api_timer for this purpose //if (mindelay) timerclient_postDeferredCallback(p1, p2, mindelay); //else //PostMessage(hwnd, WM_DEFER_CALLBACK, p1, p2); #else #warning "port me - I can be optimized - don't use timers for this, use mac os x equiv of PostMessage!" timerclient_postDeferredCallback(p1, p2, mindelay); #endif } int BaseWnd::bypassModal() { return 0; } void BaseWnd::setRenderBaseTexture(int r) { renderbasetexture = r; if (isInited()) invalidate(); } int BaseWnd::getRenderBaseTexture() { return renderbasetexture; } GuiObject *BaseWnd::getGuiObject() { if (my_guiobject == NULL) { my_guiobject = static_cast(getInterface(guiObjectGuid)); } return my_guiobject; } //CUT someday int BaseWnd::getFlag(int flag) { /* switch (flag) { }*/ return 0; } int BaseWnd::triggerEvent(int event, intptr_t p1, intptr_t p2) { //PORTME switch (event) { case TRIGGER_ONRESIZE: if (isPostOnInit()) onResize(); break; case TRIGGER_INVALIDATE: if (isPostOnInit()) invalidate(); break; } return 0; } void BaseWnd::registerAcceleratorSection(const wchar_t *name, int global) { #if defined(WASABI_COMPILE_LOCALES) WASABI_API_LOCALE->locales_registerAcceleratorSection(name, this, global); #endif } int BaseWnd::onAcceleratorEvent(const wchar_t *name) { for (int i = 0;i < getNumRootWndChildren();i++) if (enumRootWndChildren(i)->onAcceleratorEvent(name)) return 1; return 0; } int BaseWnd::allowDeactivation() { return allow_deactivate & ((WASABI_API_WND == NULL) || WASABI_API_WND->appdeactivation_isallowed(this)); } void BaseWnd::onMinimize() { if (!isVirtual()) { dropVirtualCanvas(); } } void BaseWnd::dropVirtualCanvas() { deferedInvalidate(); delete virtualCanvas; virtualCanvas = NULL; } void BaseWnd::onRestore() { if (getDesktopParent() == this) { cascadeRepaint(TRUE); } } ifc_window *BaseWnd::findWindow(const wchar_t *id) { RootWndFinder find_object; find_object.reset(); find_object.setFindId(id); ifc_window *ret = findWindowChain(&find_object); #ifdef _DEBUG if (ret == NULL) DebugStringW(L"findWindow : window not found by id ! %s \n", id); #endif return ret; } ifc_window *BaseWnd::findWindowByInterface(GUID interface_guid) { RootWndFinder find_object; find_object.reset(); find_object.setFindGuid(interface_guid); ifc_window *ret = findWindowChain(&find_object); #ifdef _DEBUG char str[256] = {0}; nsGUID::toChar(interface_guid, str); if (ret == NULL) DebugStringW(L"findWindow : object not found by guid ! %s \n", str); #endif return ret; } ifc_window *BaseWnd::findWindowByCallback(FindObjectCallback *cb) { ifc_window *ret = findWindowChain(cb); #ifdef _DEBUG if (ret == NULL) DebugStringW(L"findWindow : object not found by callback!\n"); #endif return ret; } ifc_window *BaseWnd::findWindowChain(FindObjectCallback *cb, ifc_window *wcaller) { if (!cb) return NULL; if (cb->findobjectcb_matchObject(this)) return this; // first lets not look in subdirectories for (int i = 0;i < getNumRootWndChildren();i++) { ifc_window *child = enumRootWndChildren(i); if (!child || child == wcaller) continue; if (cb->findobjectcb_matchObject(child)) return child; } // ok so it wasn't in our content, lets try to find it as a grandchildren for (int i = 0;i < getNumRootWndChildren();i++) { ifc_window *child = enumRootWndChildren(i); if (child->getNumRootWndChildren() > 0) { ifc_window *ret = child->findWindowChain(cb, this); if (ret) return ret; } } // so it wasnt one of our children, we'll hop the tree up one level and ask our parent to find it // for us. of course, our parents are smart, they won't ask us back when asking our sibblings ifc_window *p = getParent(); if (p != NULL && wcaller != p) { return p->findWindowChain(cb, this); } return NULL; } const wchar_t *BaseWnd::timerclient_getName() { tcname = StringPrintfW(L"name=\"%S\", id=\"%s\"", getRootWndName(), getId()); return tcname; } void BaseWnd::setTabOrder(int a) { if (getParent() != NULL) getParent()->setVirtualTabOrder(this, a); } int BaseWnd::getTabOrder() { if (getParent() != NULL) return getParent()->getVirtualTabOrder(this); return -1; } void BaseWnd::recursive_setVirtualTabOrder(ifc_window *w, float a, float lambda) { ASSERT(w != NULL); childtabs.setAutoSort(0); int i = getTabOrderEntry(a); if (i != -1) { TabOrderEntry *toe = childtabs.enumItem(i); if (toe->wnd != w) { lambda += TABORDER_K; if (lambda != 1.0) recursive_setVirtualTabOrder(toe->wnd, a + lambda, lambda); } else { return ; } } i = getTabOrderEntry(w); if (i != -1) { delete childtabs.enumItem(i); childtabs.removeByPos(i); } TabOrderEntry *toe = new TabOrderEntry; toe->wnd = w; toe->order = a; childtabs.addItem(toe); } void BaseWnd::setVirtualTabOrder(ifc_window *w, int a) { if (a == -1) { delTabOrderEntry(w); return ; } recursive_setVirtualTabOrder(w, (float)a); } int BaseWnd::getVirtualTabOrder(ifc_window *w) { int a = (int)getTabOrderEntry(w); if (a == -1) return -1; return (int)childtabs.enumItem(a); } int BaseWnd::getTabOrderEntry(ifc_window *w) { foreach(childtabs) if (childtabs.getfor()->wnd == w) return foreach_index; endfor; return -1; } void BaseWnd::delTabOrderEntry(int i) { int a = getTabOrderEntry((float)i); if (a == -1) return ; childtabs.removeByPos(a); } void BaseWnd::delTabOrderEntry(ifc_window *w) { int a = getTabOrderEntry(w); if (a == -1) return ; delete childtabs.enumItem(a); childtabs.removeByPos(a); } int BaseWnd::getTabOrderEntry(float order) { foreach(childtabs) if (childtabs.getfor()->order == order) return foreach_index; endfor; return -1; } void BaseWnd::setAutoTabOrder() { if (!getParent()) return ; getParent()->setVirtualAutoTabOrder(this); } void BaseWnd::setVirtualAutoTabOrder(ifc_window *w) { delTabOrderEntry(w); float o = 0; for (int i = 0;i < childtabs.getNumItems();i++) { o = MAX(o, childtabs.enumItem(i)->order); } setVirtualTabOrder(w, ((int)o) + 1); } void BaseWnd::focusNext() { ifc_window *dp = getDesktopParent(); if (dp != this) { if (dp != NULL) dp->focusNext(); return ; } ifc_window *w = getTab(TAB_GETNEXT); if (w != NULL) w->setFocus(); } void BaseWnd::focusPrevious() { ifc_window *dp = getDesktopParent(); if (dp != this) { if (dp != NULL) getDesktopParent()->focusPrevious(); return ; } ifc_window *w = getTab(TAB_GETPREVIOUS); if (w != NULL) w->setFocus(); } void BaseWnd::recursive_buildTabList(ifc_window *from, PtrList *list) { for (int i = 0;i < from->getNumTabs();i++) { ifc_window *r = from->enumTab(i); if (r->isVisible() && r->getPaintingAlpha() > 0) { if (r->wantFocus()) list->addItem(r); recursive_buildTabList(r, list); } } } ifc_window *BaseWnd::getTab(int what) { PtrList listnow; recursive_buildTabList(this, &listnow); int p = listnow.searchItem(rootfocus); if (p == -1) for (int i = 0; i < listnow.getNumItems(); i++) { ifc_window *r = listnow.enumItem(i); if (r->gotFocus()) { //DebugString("desync of rootfocus, fixing\n"); p = i; assignRootFocus(r); break; } } if (what == TAB_GETNEXT && rootfocus != NULL) { p++; if (p >= listnow.getNumItems()) p = 0; return listnow.enumItem(p); } else if (what == TAB_GETPREVIOUS && rootfocus != NULL) { p--; if (p < 0) p = listnow.getNumItems() - 1; return listnow.enumItem(p); } else if (what == TAB_GETCURRENT) { return rootfocus; } else if (what == TAB_GETFIRST || (what == TAB_GETNEXT && rootfocus == NULL)) { return listnow.getFirst(); } else if (what == TAB_GETLAST || (what == TAB_GETPREVIOUS && rootfocus == NULL)) { return listnow.getLast(); } return NULL; } int BaseWnd::getNumTabs() { return childtabs.getNumItems(); } ifc_window *BaseWnd::enumTab(int i) { childtabs.sort(); return childtabs.enumItem(i)->wnd; } void BaseWnd::onSetRootFocus(ifc_window *w) { assignRootFocus(w); ifc_window *dp = getDesktopParent(); if (dp && dp != this) dp->onSetRootFocus(w); } void BaseWnd::autoFocus(ifc_window *w) { if (w->getFocusOnClick() && w->wantFocus()) { w->setFocus(); return ; } ifc_window *g = w; while (1) { ifc_window *p = g->getParent(); if (p == NULL) break; ifc_window *dp = p->getDesktopParent(); if (dp && dp != p) { if (p->wantFocus() && p->getFocusOnClick()) { p->setFocus(); return ; } g = p; } else break; } } void BaseWnd::setNoLeftClicks(int no) { noleftclick = no; } void BaseWnd::setNoRightClicks(int no) { norightclick = no; } void BaseWnd::setNoDoubleClicks(int no) { nodoubleclick = no; } void BaseWnd::setNoMouseMoves(int no) { nomousemove = no; } void BaseWnd::setNoContextMenus(int no) { nocontextmnu = no; } void BaseWnd::setDefaultCursor(Cursor *c) { customdefaultcursor = c; } OSCURSORHANDLE BaseWnd::getCustomCursor(int x, int y) { #ifdef _WIN32 return customdefaultcursor ? customdefaultcursor->getOSHandle() : NULL; #else #warning port me return 0; #endif } Accessible *BaseWnd::createNewAccObj() { waServiceFactory *f = WASABI_API_SVC->service_enumService(WaSvc::ACCESSIBILITY, 0); if (f != NULL) { svc_accessibility *svc = castService(f); if (svc != NULL) { Accessible *a = svc->createAccessibleObject(this); WASABI_API_SVC->service_release(svc); return a; } } return NULL; } Accessible *BaseWnd::getAccessibleObject(int createifnotexist) { if (!createifnotexist) return accessible; if (!accessible) accessible = createNewAccObj(); else accessible->addRef(); return accessible; } int BaseWnd::accessibility_getState() { int state = 0; if (!isVisible()) state |= STATE_SYSTEM_INVISIBLE; //if (isVirtual() && !wantFocus()) state |= STATE_SYSTEM_INVISIBLE; if (gotFocus()) state |= STATE_SYSTEM_FOCUSED; return state; } void BaseWnd::activate() { Wasabi::Std::Wnd::setActiveWindow(getRootParent()->getOsWindowHandle()); } void BaseWnd::setOSWndName(const wchar_t *name) { if (isVirtual()) return ; //#ifdef COMPILE_WASABI_SKIN // for some reason this isn't being correctly defined if (name) { Wasabi::Std::Wnd::setWndName(getOsWindowHandle(), name); } else Wasabi::Std::Wnd::setWndName(getOsWindowHandle(), L""); } const wchar_t *BaseWnd::getOSWndName() { if (isVirtual()) return NULL; wchar_t str[4096] = {0}; Wasabi::Std::Wnd::getWndName(getOsWindowHandle(), str, 4095); str[4095] = '\0'; osname = str; return osname; } #ifdef EXPERIMENTAL_INDEPENDENT_AOT void BaseWnd::setAlwaysOnTop(int i) { // this function should not optimize itself if (getDesktopParent() == this) { if (i) { //CUT SetWindowPos(getOsWindowHandle(), HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOOWNERZORDER); Wasabi::Std::Wnd::setTopmost(getOsWindowHandle(), TRUE); } else { saveTopMosts(); //CUT SetWindowPos(getOsWindowHandle(), HWND_NOTOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOOWNERZORDER); Wasabi::Std::Wnd::setTopmost(getOsWindowHandle(), FALSE); restoreTopMosts(); } alwaysontop = i; return ; } ifc_window *p = getParent(); if (p != NULL) p->setAlwaysOnTop(i); } int BaseWnd::getAlwaysOnTop() { if (getDesktopParent() == this) return alwaysontop; ifc_window *p = getParent(); if (!p) return 0; return p->getAlwaysOnTop(); } #endif void BaseWnd::wndwatcher_onDeleteWindow(ifc_window *w) { if (w == rootfocus) { rootfocus = NULL; } } void BaseWnd::assignRootFocus(ifc_window *w) { rootfocuswatcher.watchWindow(w); rootfocus = w; } Canvas *BaseWnd::getFrameBuffer() { return virtualCanvas; } void BaseWnd::setForeignWnd(int i) { m_takenOver = i; } int BaseWnd::bufferizeLockedUIMsg(int uMsg, int wParam, int lParam) { if (WASABI_API_SKIN && !WASABI_API_SKIN->skin_getLockUI()) return 0; if (!uiwaslocked) { uiwaslocked = 1; setTimer(BUFFEREDMSG_TIMER_ID, 20); } bufferedMsgStruct msg; msg.msg = uMsg; msg.wparam = wParam; msg.lparam = lParam; bufferedmsgs.addItem(msg); return 1; } void BaseWnd::checkLockedUI() { //PORTME :( #ifdef _WIN32 if (WASABI_API_SKIN && !WASABI_API_SKIN->skin_getLockUI()) { uiwaslocked = 0; killTimer(BUFFEREDMSG_TIMER_ID); while (bufferedmsgs.getNumItems() > 0) { bufferedMsgStruct msg = bufferedmsgs.enumItem(0); bufferedmsgs.delByPos(0); SendMessageW(gethWnd(), msg.msg, msg.wparam, msg.lparam); } uiwaslocked = 0; killTimer(BUFFEREDMSG_TIMER_ID); } #else #warning port me #endif } int BaseWnd::isMinimized() { ifc_window *w = getDesktopParent(); if (w == this || w == NULL) return minimized; return w->isMinimized(); } int BaseWnd::reinit() { #ifdef _WIN32 int nochild = (GetWindowLong(gethWnd(), GWL_STYLE) & WS_POPUP) ? 1 : 0; int r = reinit(parentWnd ? parentWnd : WASABI_API_WND->main_getRootWnd(), nochild); if (w2k_alpha) setLayeredWindow(1); return r; #else #warning port me! #endif } int BaseWnd::reinit(ifc_window *parWnd, int nochild) { OSWINDOWHANDLE phwnd = parWnd->getOsWindowHandle(); ASSERT(phwnd != NULL); int ret; if (!nochild) parentWnd = parWnd; else parentWnd = NULL; ret = reinit(parWnd->getOsModuleHandle(), phwnd, nochild); if (!ret) parentWnd = NULL; // abort return ret; } int BaseWnd::reinit(OSMODULEHANDLE moduleHandle, OSWINDOWHANDLE parent, int nochild) { RECT r; int w, h; onBeforeReinit(); pushWindowRect(); preventcancelcapture = 1; int _isvisible = isVisible(1); int hadcapture = inputCaptured; //DebugString("had capture = %d\n", hadcapture); Wasabi::Std::Wnd::releaseCapture(); unparentHWNDChildren(); BaseWnd::getClientRect(&r); hinstance = moduleHandle; ASSERT(hinstance != NULL); w = (r.right - r.left); h = (r.bottom - r.top); rwidth = w; rheight = h; rx = r.left; ry = r.top; WASABI_API_WND->appdeactivation_push_disallow(this); // destroy old window Wasabi::Std::Wnd::hideWnd(hwnd); //Wasabi::Std::Wnd::destroyWnd(hwnd); ghosthwnd.addItem(hwnd); hwnd = Wasabi::Std::Wnd::createWnd(&r, nochild, acceptExternalDrops(), parent, hinstance, static_cast(this)); #ifdef __APPLE__ #warning remove me Wasabi::Std::Wnd::showWnd(hwnd); #endif WASABI_API_WND->appdeactivation_pop_disallow(this); //ASSERT(hwnd != NULL); // lets fail nicely, this could happen for some win32 reason, we don't want to fail the whole app for it, so lets just fail the wnd if (hwnd == NULL) { preventcancelcapture = 0; return 0; } //CUT nreal++; #ifdef _WIN32 //FUCKO #ifdef URLDROPS if (acceptExternalDrops()) RegisterDragDrop(hwnd, &m_target); #elif !defined(WA3COMPATIBILITY) if (!m_target && WASABI_API_WND != NULL) m_target = WASABI_API_WND->getDefaultDropTarget(); if (m_target != NULL) { RegisterDragDrop(hwnd, (IDropTarget *)m_target); } #endif #else #warning port me - register drag & drop #endif this_visible = _isvisible; //onInit(); //this_visible = !start_hidden; reparentHWNDChildren(); popWindowRect(); invalidateWindowRegion(); updateWindowRegion(); if (this_visible) Wasabi::Std::Wnd::showWnd(hwnd, FALSE); if (hadcapture) { Wasabi::Std::Wnd::setCapture(hwnd); } preventcancelcapture = 0; forcedOnResize(); redrawHWNDChildren(); //onPostOnInit(); onAfterReinit(); #ifdef WASABI_ON_REPARENT WASABI_ON_REINIT(getOsWindowHandle()); #endif return 1; } ReparentWndEntry::ReparentWndEntry(OSWINDOWHANDLE _wnd, OSWINDOWHANDLE parentwnd) { wnd = _wnd; Wasabi::Std::Wnd::getWindowRect(wnd, &rect); Wasabi::Std::Wnd::screenToClient(wnd, (int *)&(rect.left), (int *)&(rect.top)); Wasabi::Std::Wnd::clientToScreen(parentwnd, (int *)&(rect.left), (int *)&(rect.top)); } void ReparentWndEntry::unparent() { Wasabi::Std::Wnd::setWndPos(wnd, NULL, rect.left, -30000, 0, 0, TRUE, TRUE, FALSE, FALSE, TRUE); Wasabi::Std::Wnd::setParent(wnd, NULL); } void ReparentWndEntry::reparent(OSWINDOWHANDLE newparent) { Wasabi::Std::Wnd::setParent(wnd, newparent); Wasabi::Std::Wnd::setWndPos(wnd, NULL, rect.left, rect.top, 0, 0, TRUE, TRUE, FALSE, FALSE, TRUE); } #ifdef _WIN32 void BaseWnd::unparentHWNDChildren() { // just in case reparentwnds.deleteAll(); #ifndef WIN32 #error port me ! // make a list of all the children oswindows and reparent them to the desktop somewhere we can't see #endif OSWINDOWHANDLE wnd = GetWindow(getOsWindowHandle(), GW_CHILD); while (wnd) { reparentwnds.addItem(new ReparentWndEntry(wnd, getOsWindowHandle())); wnd = GetWindow(wnd, GW_HWNDNEXT); } foreach(reparentwnds) reparentwnds.getfor()->unparent(); endfor; } #endif void BaseWnd::reparentHWNDChildren() { // reparent to the new oswindowhandle foreach(reparentwnds) reparentwnds.getfor()->reparent(getOsWindowHandle()); endfor; } void BaseWnd::redrawHWNDChildren() { // reparent to the new oswindowhandle foreach(reparentwnds) Wasabi::Std::Wnd::update(getOsWindowHandle()); endfor; } void BaseWnd::maximize(int axis) { //DebugString("maximize!\n"); // if already maximized, don't use current rect, use restore_rect if (!maximized) { restore_rect.left = rx; restore_rect.top = ry; restore_rect.right = rx + rwidth; restore_rect.bottom = ry + rheight; } RECT nr = restore_rect; RECT dr; Wasabi::Std::getViewport(&dr, NULL, NULL, getOsWindowHandle(), 0); if (axis & MAXIMIZE_WIDTH) { nr.left = dr.left; nr.right = dr.right; } if (axis & MAXIMIZE_HEIGHT) { nr.top = dr.top; nr.bottom = dr.bottom; } maximized = 1; if (axis != 0) resize(&nr); onMaximize(); } void BaseWnd::restore(int what) { if (maximized) { //DebugString("restore!\n"); if (what == (RESTORE_X | RESTORE_Y | RESTORE_WIDTH | RESTORE_HEIGHT)) resize(&restore_rect); else { resize((what & RESTORE_X) ? restore_rect.left : NOCHANGE, (what & RESTORE_Y) ? restore_rect.top : NOCHANGE, (what & RESTORE_WIDTH) ? restore_rect.right - restore_rect.left : NOCHANGE, (what & RESTORE_HEIGHT) ? restore_rect.bottom - restore_rect.top : NOCHANGE); } maximized = 0; onRestore(); } } void BaseWnd::pushWindowRect() { //DebugString("pushWindowRect\n"); RECT wr; getWindowRect(&wr); wr.right = wr.left + rwidth; wr.bottom = wr.top + rheight; windowrectstack.push(wr); } int BaseWnd::popWindowRect(RECT *rc, int applyhow) { //DebugString("popWindowRect\n"); if (windowrectstack.peek() == 0) return 0; RECT _rc; windowrectstack.pop(&_rc); RECT r; getWindowRect(&r); divRatio(&r); if (applyhow) { if (applyhow == PWR_POSITION) { move(_rc.left, _rc.top); if (rc) { int w = r.right - r.left; int h = r.bottom - r.top; rc->left = _rc.left; rc->top = _rc.top; rc->right = rc->left + w; rc->bottom = rc->top + h; } } else { if (applyhow & PWR_X) r.left = _rc.left; if (applyhow & PWR_Y) r.top = _rc.top; if (applyhow & PWR_WIDTH) r.right = r.left + (_rc.right - _rc.left); if (applyhow & PWR_HEIGHT) r.bottom = r.top + (_rc.bottom - _rc.top); resizeToRect(&r); if (rc) *rc = _rc; } } else if (rc) *rc = _rc; return 1; } void BaseWnd::setRestoredRect(RECT *r) { if (!r) return ; restore_rect = *r; maximized = 1; } int BaseWnd::getRestoredRect(RECT *r) { if (!r) return 0; if (!maximized) return 0; *r = restore_rect; return 1; } void BaseWnd::notifyDeferredMove(int x, int y) { rx = x; ry = y; } void BaseWnd::setWindowTitle(const wchar_t *title) { Layout *l = static_cast(getInterface(layoutGuid)); if (l) { Container *c = l->getParentContainer(); if (c) { c->setName(title); } } } #ifdef __APPLE__ OSStatus BaseWnd::eventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) { return eventNotHandledErr; } #endif