mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-23 22:24:50 +01:00
5744 lines
127 KiB
C++
5744 lines
127 KiB
C++
#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(®);
|
|
#ifdef _WIN32
|
|
canvas->selectClipRgn(NULL);
|
|
canvas->fillRect(&r, 0);
|
|
#elif defined(__APPLE__)
|
|
CGContextClearRect(canvas->getHDC(), CGRectInfinite); // TODO: make "clear" function in canvas
|
|
#endif
|
|
virtualAfterPaint(®);
|
|
}
|
|
|
|
void BaseWnd::deleteFrameBuffer(Canvas *canvas)
|
|
{
|
|
delete canvas;
|
|
}
|
|
|
|
// paints the client content, followed by the virtual child tree. recursive
|
|
int BaseWnd::paintTree(Canvas *canvas, api_region *r)
|
|
{
|
|
onPaint(canvas, r);
|
|
|
|
#ifdef WASABI_DRAW_FOCUS_RECT
|
|
if (gotFocus())
|
|
{
|
|
RECT ncr;
|
|
getNonClientRect(&ncr);
|
|
// try to use skinned focus rect
|
|
if (WASABI_API_WND->paintset_present(Paintset::FOCUSRECT))
|
|
WASABI_API_WND->paintset_render(Paintset::FOCUSRECT, canvas, &ncr, 128);
|
|
else // otherwise this looks kinda nice :P
|
|
canvas->drawRect(&ncr, 0, 0xFFFFFF, 128);
|
|
}
|
|
#endif
|
|
|
|
if (isVirtual() && !hasVirtualChildren()) return 0;
|
|
|
|
api_region *hostrgn = NULL;
|
|
api_region *update = r;
|
|
|
|
if (!(hwnd != NULL && getParent() == NULL))
|
|
{
|
|
hostrgn = getRegion();
|
|
update = r->clone();
|
|
if (hostrgn && !isRectRgn())
|
|
{
|
|
RECT ncr = clientRect();
|
|
api_region *hostclone = hostrgn->clone();
|
|
hostclone->addRegion(getComposedRegion());
|
|
hostclone->offset(ncr.left, ncr.top);
|
|
update->andRegion(hostclone);
|
|
hostrgn->disposeClone(hostclone);
|
|
}
|
|
}
|
|
|
|
RegionI client_update;
|
|
for (int i = 0;i < virtualChildren.getNumItems();i++)
|
|
{
|
|
if (!virtualChildren[i]->isVisible(1)) continue;
|
|
RECT rChild;
|
|
ifc_window *w = virtualChildren[i];
|
|
w->getNonClientRect(&rChild);
|
|
if ((rChild.right != rChild.left) && (rChild.bottom != rChild.top))
|
|
if (update->intersectRect(&rChild, &client_update))
|
|
{
|
|
w->paintTree(canvas, &client_update);
|
|
}
|
|
}
|
|
|
|
if (update != r) r->disposeClone(update);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void BaseWnd::setVirtualCanvas(Canvas *c)
|
|
{
|
|
virtualCanvas = c;
|
|
}
|
|
|
|
int BaseWnd::pointInWnd(POINT *p)
|
|
{
|
|
RECT r;
|
|
if (!isVisible(1)) return 0;
|
|
getWindowRect(&r);
|
|
if (!Wasabi::Std::pointInRect(r, *p))
|
|
return 0;
|
|
for (int i = 0; i < getNumRootWndChildren(); i++)
|
|
{
|
|
ifc_window *c = enumRootWndChildren(i);
|
|
if (!c->isVisible(1)) continue;
|
|
RECT rChild;
|
|
c->getWindowRect(&rChild);
|
|
if (Wasabi::Std::pointInRect(rChild, *p))
|
|
return 0;
|
|
}
|
|
//NONPORTABLE
|
|
/* HWND child = GetWindow(getOsWindowHandle(), GW_CHILD);
|
|
while (child != NULL) {
|
|
if (IsWindowVisible(child)) {
|
|
RECT r2;
|
|
GetWindowRect(child, &r2);
|
|
if (Std::pointInRect(r2, *p))
|
|
return 0;
|
|
}
|
|
child = GetWindow(child, GW_HWNDNEXT);
|
|
}*/
|
|
return 1;
|
|
}
|
|
|
|
int BaseWnd::paint(Canvas *c, api_region *r)
|
|
{
|
|
if (isVirtual())
|
|
{
|
|
RegionI d;
|
|
RECT cr;
|
|
getClientRect(&cr);
|
|
if (r == NULL)
|
|
{
|
|
d.addRect(&cr);
|
|
}
|
|
else
|
|
{
|
|
d.addRegion(r);
|
|
d.offset(cr.left, cr.top);
|
|
}
|
|
ifc_window *rp = getRootParent();
|
|
deferedInvalidate();
|
|
rp->paint(NULL, &d);
|
|
BltCanvas *cc = static_cast<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(®); return 0;
|
|
}
|
|
|
|
// DO NOT DELETE - This looks like it does nothing, but it actually makes the GDI call us again with WM_PAINT if some window
|
|
// moves over this one between BeginPaint and EndPaint. We still use GetUpdateRgn so we don't have to check for
|
|
// the version of Windows. See doc. If this function is not available (should be here in 95/98/NT/2K, but we never know)
|
|
// then we use the rcPaint rect... less precise, but still works.
|
|
//CUT if (getRandomRgn) {
|
|
if (Wasabi::Std::Wnd::haveGetRandomRegion())
|
|
{
|
|
RegionI zap;
|
|
//CUT getRandomRgn(paintcanvas.getHDC(), zap.getOSHandle(), SYSRGN);
|
|
Wasabi::Std::Wnd::getRandomRegion(paintcanvas.getHDC(), zap.getOSHandle());
|
|
}
|
|
else
|
|
{
|
|
RECT z;
|
|
paintcanvas.getRcPaint(&z);
|
|
reg.setRect(&z);
|
|
}
|
|
|
|
// -------------
|
|
|
|
/*// for debug
|
|
HDC dc = GetDC(getOsWindowHandle());
|
|
InvertRgn(dc, r->getHRGN());
|
|
InvertRgn(dc, r->getHRGN());
|
|
ReleaseDC(getOsWindowHandle(), dc);*/
|
|
|
|
paint(&paintcanvas, ®);
|
|
#else
|
|
#warning port me or remove me
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
ifc_window *BaseWnd::enumVirtualChild(int _enum)
|
|
{
|
|
return virtualChildren[_enum];
|
|
}
|
|
|
|
int BaseWnd::getNumVirtuals()
|
|
{
|
|
return virtualChildren.getNumItems();
|
|
}
|
|
|
|
ifc_window *BaseWnd::enumRootWndChildren(int n)
|
|
{
|
|
return rootwndchildren.enumItem(n);
|
|
}
|
|
|
|
int BaseWnd::getNumRootWndChildren()
|
|
{
|
|
return rootwndchildren.getNumItems();
|
|
}
|
|
|
|
ifc_window *BaseWnd::findRootWndChild(int x, int y, int only_virtuals)
|
|
{
|
|
for (int i = getNumRootWndChildren() - 1; i > -1; i--)
|
|
{
|
|
RECT r;
|
|
ifc_window *child = enumRootWndChildren(i);
|
|
//DebugStringW(L"findRootWndChild = entering = %s\n", child->getId());
|
|
if (only_virtuals && !child->isVirtual()) continue;
|
|
child->getNonClientRect(&r);
|
|
int _x = x;
|
|
int _y = y;
|
|
if (!child->isVirtual())
|
|
{
|
|
POINT pt;
|
|
child->getPosition(&pt);
|
|
_x -= pt.x;
|
|
_y -= pt.y;
|
|
}
|
|
int iv = child->isVisible(1);
|
|
//int gpa = child->getPaintingAlpha();
|
|
POINT _p = Wasabi::Std::makePoint(_x, _y);
|
|
if (iv /*&& gpa > 0*/ && Wasabi::Std::pointInRect(r, _p))
|
|
{
|
|
// GROUP
|
|
ifc_window *z = child->findRootWndChild(_x, _y);
|
|
if (z) return z;
|
|
}
|
|
/*gpa > 0 &&*/
|
|
/*if (iv && _x>=r.left&&_x<=r.right&&_y>=r.top&&_y<=r.bottom && !child->isClickThrough() && child->ptInRegion(_x, _y)) {
|
|
return child;
|
|
}*/
|
|
}
|
|
return (!isClickThrough() && ptInRegion(x, y)) ? this : NULL;
|
|
}
|
|
|
|
//PORTME
|
|
int BaseWnd::handleVirtualChildMsg(UINT uMsg, int x, int y, void *p, void *d)
|
|
{
|
|
#ifdef _WIN32
|
|
ifc_window *child = NULL;
|
|
|
|
if (curVirtualChildCaptured)
|
|
child = curVirtualChildCaptured;
|
|
else
|
|
child = findRootWndChild(x, y, 1); // warning, can return this which is not virtual
|
|
|
|
// ASSERT(child != NULL); // BU this came up and I don't know why, looks like it should never happen
|
|
// FG> actually it can happen when coming back from a popup menu when cpu usage is high, the window might be
|
|
// hidden (destroying) and ptInRegion returns false.
|
|
if (!child) return 0;
|
|
|
|
//int isvirtual = child->isVirtual();
|
|
|
|
if (child) child = child->getForwardWnd();
|
|
|
|
if (child && child->isEnabled())
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
/* if (isvirtual && child != curVirtualChildFocus)
|
|
focusVirtualChild(child);*/
|
|
autoFocus(child);
|
|
if (child->wantLeftClicks())
|
|
child->onLeftButtonDown(x, y);
|
|
if (child->checkDoubleClick(uMsg, x, y) && child->wantDoubleClicks())
|
|
child->onLeftButtonDblClk(x, y);
|
|
return 1;
|
|
case WM_RBUTTONDOWN:
|
|
/* if (isvirtual && child != curVirtualChildFocus)
|
|
focusVirtualChild(child);*/
|
|
autoFocus(child);
|
|
if (child->wantRightClicks())
|
|
child->onRightButtonDown(x, y);
|
|
if (child->checkDoubleClick(uMsg, x, y) && child->wantDoubleClicks())
|
|
child->onRightButtonDblClk(x, y);
|
|
return 1;
|
|
case WM_LBUTTONUP:
|
|
if (child->wantLeftClicks())
|
|
child->onLeftButtonUp(x, y);
|
|
return 1;
|
|
case WM_RBUTTONUP:
|
|
if (child->wantRightClicks())
|
|
child->onRightButtonUp(x, y);
|
|
return 1;
|
|
case WM_MOUSEMOVE:
|
|
{
|
|
if (curVirtualChildCaptured == child || (curVirtualChildCaptured == NULL))
|
|
{
|
|
if (child->wantMouseMoves())
|
|
child->onMouseMove(x, y);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
case WM_MOUSEHOVER:
|
|
((BaseWnd *)child)->onTip();
|
|
break;
|
|
case WM_SETCURSOR:
|
|
int a = child->getCursorType(x, y);
|
|
if (!p) return 0;
|
|
*(int *)p = a;
|
|
if (a == BASEWND_CURSOR_USERSET)
|
|
{
|
|
OSCURSORHANDLE c = child->getCustomCursor(x, y);
|
|
if (!d) return 0;
|
|
*(OSCURSORHANDLE *)d = c;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
#else
|
|
#warning port me or remove me
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int BaseWnd::onLeftButtonDown(int x, int y)
|
|
{
|
|
disable_tooltip_til_recapture = 1;
|
|
abortTip();
|
|
return 0;
|
|
}
|
|
|
|
int BaseWnd::onLeftButtonUp(int x, int y)
|
|
{
|
|
disable_tooltip_til_recapture = 1;
|
|
abortTip();
|
|
return 0;
|
|
}
|
|
|
|
void BaseWnd::setVirtualChildCapture(ifc_window *child)
|
|
{
|
|
if (child)
|
|
{
|
|
if (!inputCaptured)
|
|
{
|
|
beginCapture();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
endCapture();
|
|
}
|
|
curVirtualChildCaptured = child;
|
|
}
|
|
|
|
ifc_window *BaseWnd::getVirtualChildCapture()
|
|
{
|
|
if (inputCaptured && Wasabi::Std::Wnd::getCapture() == getOsWindowHandle())
|
|
return curVirtualChildCaptured;
|
|
else
|
|
if (inputCaptured) inputCaptured = 0;
|
|
return NULL;
|
|
}
|
|
|
|
ifc_window *BaseWnd::getBaseTextureWindow()
|
|
{
|
|
// return our base texture window if we have it
|
|
if (btexture)
|
|
return btexture;
|
|
// return our parent's if they have it
|
|
if (getParent())
|
|
return getParent()->getBaseTextureWindow();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
void BaseWnd::renderBaseTexture(ifc_canvas *c, const RECT &r, int alpha)
|
|
{
|
|
WASABI_API_WND->skin_renderBaseTexture(getBaseTextureWindow(), c, r, this, alpha);
|
|
}
|
|
|
|
void BaseWnd::setBaseTextureWindow(ifc_window *w)
|
|
{
|
|
btexture = w;
|
|
}
|
|
|
|
void BaseWnd::setNotifyWindow(ifc_window *newnotify)
|
|
{
|
|
notifyWindow = newnotify;
|
|
}
|
|
|
|
ifc_window *BaseWnd::getNotifyWindow()
|
|
{
|
|
return destroying ? NULL : notifyWindow;
|
|
}
|
|
|
|
int BaseWnd::gotFocus()
|
|
{
|
|
return hasfocus && curVirtualChildFocus == NULL;
|
|
}
|
|
|
|
int BaseWnd::isActive()
|
|
{
|
|
OSWINDOWHANDLE h = hwnd;
|
|
if (h == NULL)
|
|
{
|
|
ifc_window *par = getParent();
|
|
if (par == NULL) return 0;
|
|
h = par->getOsWindowHandle();
|
|
}
|
|
if (h == NULL) return 0;
|
|
return (Wasabi::Std::Wnd::getActiveWindow() == h);
|
|
}
|
|
|
|
int BaseWnd::onChar(unsigned int c)
|
|
{
|
|
switch (c)
|
|
{
|
|
case 9: // TAB
|
|
if (Std::keyModifier(STDKEY_SHIFT))
|
|
focusPrevious();
|
|
else
|
|
focusNext();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*int BaseWnd::focusVirtualChild(api_window *child) {
|
|
if (!gotFocus()) setFocus();
|
|
if (!child->wantFocus()) return 0;
|
|
setVirtualChildFocus(child);
|
|
return 1;
|
|
}*/
|
|
|
|
int BaseWnd::wantFocus()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Return 1 if there is a modal window that is not this
|
|
int BaseWnd::checkModal()
|
|
{
|
|
if (bypassModal()) return 0;
|
|
ifc_window *w = WASABI_API_WND->getModalWnd();
|
|
if (w && w != static_cast<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(®, 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
|