aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/wnd/basewnd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/api/wnd/basewnd.cpp')
-rw-r--r--Src/Wasabi/api/wnd/basewnd.cpp5743
1 files changed, 5743 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/basewnd.cpp b/Src/Wasabi/api/wnd/basewnd.cpp
new file mode 100644
index 00000000..f24e4d6f
--- /dev/null
+++ b/Src/Wasabi/api/wnd/basewnd.cpp
@@ -0,0 +1,5743 @@
+#include <precomp.h>
+
+#include <bfc/wasabi_std.h>
+#include <bfc/wasabi_std_wnd.h>
+#include <api/wnd/wndevent.h>
+
+#include <bfc/bfc_assert.h>
+#include <api/wnd/wndclass/tooltip.h>
+#include <api/wnd/cursor.h>
+#include <api/wnd/accessible.h>
+#include <api/service/svcs/svc_accessibility.h>
+#include <api/wnd/paintsets.h>
+#include <api/wnd/PaintCanvas.h>
+
+#ifdef _WIN32
+#include <shellapi.h> // for HDROP
+#endif
+#include <tataki/canvas/bltcanvas.h>
+
+#define DESKTOPALPHA
+#define REFRESH_RATE 25
+#define DRAWTIMERID 125
+
+#include <api/wnd/basewnd.h>
+#include <api/wnd/usermsg.h>
+
+#include <api/wnd/paintcb.h>
+#include <tataki/canvas/canvas.h>
+#include <bfc/file/filename.h>
+#include <tataki/region/region.h>
+#include <api/wnd/wndclass/guiobjwnd.h>
+#include <api/script/scriptguid.h>
+#include <api/wnd/notifmsg.h>
+#include <api/metrics/metricscb.h>
+
+#include <api/wndmgr/gc.h>
+#include <api/wndmgr/layout.h>
+
+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<void>, 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<ifc_window*>(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<GuiObject *>(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<FilenamePS> 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<FilenamePS> *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(&reg);
+#ifdef _WIN32
+ canvas->selectClipRgn(NULL);
+ canvas->fillRect(&r, 0);
+#elif defined(__APPLE__)
+ CGContextClearRect(canvas->getHDC(), CGRectInfinite); // TODO: make "clear" function in canvas
+#endif
+ virtualAfterPaint(&reg);
+}
+
+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<BltCanvas*>(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(&reg); 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, &reg);
+#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<ifc_window*>(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(&reg, 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<ifc_window> 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 <api/script/objects/c_script/c_rootobj.h>
+
+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<GuiObject *>(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<ifc_window> *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<ifc_window> 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<svc_accessibility>(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<ifc_window*>(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<Layout *>(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