winamp/Src/Wasabi/api/wndmgr/resize.cpp

384 lines
9.2 KiB
C++

#include <precomp.h>
#ifdef WIN32
#include <windows.h>
#endif
#include <bfc/assert.h>
#include <api/wndmgr/resize.h>
#include <api/wnd/wndtrack.h>
#include <api/wnd/basewnd.h>
#include <api/wndmgr/layout.h>
#define tag L"wa3_resizerclass"
extern HINSTANCE hInstance;
//----------------------------------------------------------------------
resizeClass::resizeClass(ifc_window *wnd, int minx, int miny, int maxx, int maxy, int sugx, int sugy)
{
screenWidth = Wasabi::Std::getScreenWidth();
screenHeight = Wasabi::Std::getScreenHeight();
#if defined (_WIN32) || defined(_WIN64)
WNDCLASSW wc;
if (!GetClassInfoW(hInstance, tag, &wc))
{
MEMSET(&wc, 0, sizeof(wc));
wc.lpfnWndProc = resizeWndProc;
wc.hInstance = hInstance; // hInstance of DLL
wc.lpszClassName = tag; // our window class name
wc.style = 0;
int _r = RegisterClassW(&wc);
ASSERTPR(_r, "cannot create resizer wndclass");
}
hWnd = CreateWindowExW(0, tag, L"", 0, 0, 0, 1, 1, NULL, NULL, hInstance, NULL);
ASSERT(hWnd);
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)this);
if (minx > maxx && maxx != -1) minx = maxx;
if (miny > maxy && maxy != -1) miny = maxy;
#endif
minWinWidth = minx;
minWinHeight = miny;
maxWinWidth = maxx;
maxWinHeight = maxy;
sugWinWidth = sugx;
sugWinHeight = sugy;
if (wnd->getInterface(layoutGuid))
{
static_cast<Layout *>(wnd)->getSnapAdjust(&snapAdjust);
if (minWinWidth != -1) minWinWidth -= snapAdjust.left + snapAdjust.right;
if (minWinHeight != -1) minWinHeight -= snapAdjust.bottom + snapAdjust.top;
if (maxWinWidth != -1) maxWinWidth -= snapAdjust.left + snapAdjust.right;
if (maxWinHeight != -1) maxWinHeight -= snapAdjust.bottom + snapAdjust.top;
if (sugWinWidth != -1) sugWinWidth -= snapAdjust.left + snapAdjust.right;
if (sugWinHeight != -1) sugWinHeight -= snapAdjust.bottom + snapAdjust.top;
}
dc = NULL;
#ifdef WIN32
oldB = NULL;
brush = NULL;
oldP = NULL;
pen = NULL;
#endif
}
//----------------------------------------------------------------------
resizeClass::~resizeClass()
{
#ifdef WIN32
if (dc)
{
SelectObject(dc, oldB);
SelectObject(dc, oldP);
SetROP2(dc, mix);
DeleteObject(pen);
DeleteObject(brush);
ReleaseDC(NULL, dc);
}
if (IsWindow(hWnd))
DestroyWindow(hWnd);
//BU win98 sucks UnregisterClass(tag, Main::gethInstance());
#else
if (dc)
{
XFreeGC(Linux::getDisplay(), dc->gc);
FREE(dc);
}
#endif
}
//----------------------------------------------------------------------
BOOL CALLBACK invalidateChildren(HWND hwnd, LPARAM lParam)
{
InvalidateRect(hwnd, NULL, FALSE);
return TRUE;
}
//----------------------------------------------------------------------
BOOL CALLBACK invalidateAll(HWND hwnd, LPARAM lParam)
{
EnumChildWindows(hwnd, invalidateChildren, 0);
InvalidateRect(hwnd, NULL, FALSE);
return TRUE;
}
//----------------------------------------------------------------------
int resizeClass::resizeWindow(ifc_window *wnd, int way)
{
// paintHookStart();
wnd->getWindowRect(&originalRect);
snapAdjust.left = 0;
snapAdjust.top = 0;
snapAdjust.right = 0;
snapAdjust.bottom = 0;
if (wnd->getInterface(layoutGuid))
{
static_cast<Layout *>(wnd)->getSnapAdjust(&snapAdjust);
if (wnd->getRenderRatio() != 1.0)
{
double rr = wnd->getRenderRatio();
snapAdjust.left = (int)((double)(snapAdjust.left) * rr);
snapAdjust.top = (int)((double)(snapAdjust.top) * rr);
snapAdjust.right = (int)((double)(snapAdjust.right) * rr);
snapAdjust.bottom = (int)((double)(snapAdjust.bottom) * rr);
}
originalRect.left += snapAdjust.left;
originalRect.top += snapAdjust.top;
originalRect.right -= snapAdjust.right;
originalRect.bottom -= snapAdjust.bottom;
}
curRect = originalRect;
resizeWay = way;
resizedWindow = wnd->gethWnd();
resizedWindowR = wnd;
POINT pt;
Wasabi::Std::getMousePos(&pt);
cX = pt.x;
cY = pt.y;
#ifdef WIN32
SetCapture(hWnd);
#endif
SetTimer(hWnd, 1, 100, NULL); // this timer will make sure that we never get interlock
drawFrame();
MSG msg;
cancelit = 1;
while (GetCapture() == hWnd && GetMessage( &msg, hWnd, 0, 0 ))
{
TranslateMessage( &msg );
#ifdef LINUX
if ( msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE )
wndProc( msg.hwnd, msg.message, msg.wParam, msg.lParam );
else
#endif
DispatchMessage( &msg );
}
drawFrame();
// paintHookStop();
if (GetCapture() == hWnd) ReleaseCapture();
KillTimer(hWnd, 1);
if (!cancelit)
{
curRect.left -= snapAdjust.left;
curRect.top -= snapAdjust.top;
curRect.right += snapAdjust.right;
curRect.bottom += snapAdjust.bottom;
}
else
{
curRect = originalRect;
// evil, but less evil than InvalidateRect(NULL, NULL, FALSE);
EnumWindows(invalidateAll, 0);
}
return !cancelit;
}
//----------------------------------------------------------------------
RECT resizeClass::getRect(void)
{
return curRect;
}
//#define nifty
//----------------------------------------------------------------------
void resizeClass::drawFrame(void)
{
RECT outRect;
#ifdef WIN32
if (!dc)
{
dc = GetDC(NULL);
brush = CreateSolidBrush(0xFFFFFF);
pen = CreatePen(PS_SOLID, 0, 0xFFFFFF);
oldB = (HBRUSH)SelectObject(dc, brush);
oldP = (HPEN)SelectObject(dc, pen);
mix = SetROP2(dc, R2_XORPEN);
}
outRect = curRect;
#ifndef nifty
DrawFocusRect(dc, &outRect);
#else
RECT inRect;
inRect = outRect;
inRect.left += 10;
inRect.right -= 10;
inRect.top += 24;
inRect.bottom -= 10;
MoveToEx(dc, inRect.left, inRect.top, NULL);
LineTo(dc, inRect.right, inRect.top);
LineTo(dc, inRect.right, inRect.bottom);
LineTo(dc, inRect.left, inRect.bottom);
LineTo(dc, inRect.left, inRect.top);
MoveToEx(dc, outRect.left, 0, NULL);
LineTo(dc, outRect.left, screenHeight);
MoveToEx(dc, outRect.right, 0, NULL);
LineTo(dc, outRect.right, screenHeight);
MoveToEx(dc, 0, outRect.top, NULL);
LineTo(dc, screenWidth, outRect.top);
MoveToEx(dc, 0, outRect.bottom, NULL);
LineTo(dc, screenWidth, outRect.bottom);
#endif
#endif//WIN32
#ifdef LINUX
outRect = curRect;
if ( ! dc )
{
dc = (HDC)MALLOC( sizeof( hdc_typ ) );
XGCValues gcv;
gcv.function = GXxor;
gcv.subwindow_mode = IncludeInferiors;
gcv.foreground = 0xffffff;
gcv.line_style = LineOnOffDash;
gcv.dashes = 1;
dc->gc = XCreateGC( Linux::getDisplay(), Linux::RootWin(), GCFunction | GCForeground | GCSubwindowMode, &gcv );
}
XDrawRectangle( Linux::getDisplay(), Linux::RootWin(), dc->gc,
outRect.left, outRect.top, outRect.right - outRect.left,
outRect.bottom - outRect.top );
#endif
//PORTME
}
LRESULT resizeClass::wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONUP:
cancelit = 0;
ReleaseCapture();
return 0;
case WM_MOUSEMOVE:
{
POINT pt;
int iX, iY;
Wasabi::Std::getMousePos(&pt);
iX = pt.x - cX;
iY = pt.y - cY;
drawFrame();
if (resizeWay & TOP)
curRect.top = originalRect.top + iY;
if (resizeWay & BOTTOM)
curRect.bottom = originalRect.bottom + iY;
if (resizeWay & LEFT)
curRect.left = originalRect.left + iX;
if (resizeWay & RIGHT)
curRect.right = originalRect.right + iX;
if (abs((curRect.right - curRect.left) - sugWinWidth) < 10)
if (resizeWay & RIGHT)
curRect.right = curRect.left + sugWinWidth;
else if (resizeWay & LEFT)
curRect.left = curRect.right - sugWinWidth;
if (abs((curRect.bottom - curRect.top) - sugWinHeight) < 10)
if (resizeWay & BOTTOM)
curRect.bottom = curRect.top + sugWinHeight;
else if (resizeWay & TOP)
curRect.top = curRect.bottom - sugWinHeight;
curRect.left -= snapAdjust.left;
curRect.top -= snapAdjust.top;
curRect.right += snapAdjust.right;
curRect.bottom += snapAdjust.bottom;
windowTracker->autoDock(resizedWindowR, &curRect, resizeWay);
curRect.left += snapAdjust.left;
curRect.top += snapAdjust.top;
curRect.right -= snapAdjust.right;
curRect.bottom -= snapAdjust.bottom;
if ((curRect.right - curRect.left) < minWinWidth)
if (resizeWay & RIGHT)
curRect.right = curRect.left + minWinWidth;
else if (resizeWay & LEFT)
curRect.left = curRect.right - minWinWidth;
if ((curRect.bottom - curRect.top) < minWinHeight)
if (resizeWay & BOTTOM)
curRect.bottom = curRect.top + minWinHeight;
else if (resizeWay & TOP)
curRect.top = curRect.bottom - minWinHeight;
if (maxWinWidth != -1 && (curRect.right - curRect.left) > maxWinWidth)
if (resizeWay & RIGHT)
curRect.right = curRect.left + maxWinWidth;
else if (resizeWay & LEFT)
curRect.left = curRect.right - maxWinWidth;
if (maxWinHeight != -1 && (curRect.bottom - curRect.top) > maxWinHeight)
if (resizeWay & BOTTOM)
curRect.bottom = curRect.top + maxWinHeight;
else if (resizeWay & TOP)
curRect.top = curRect.bottom - maxWinHeight;
drawFrame();
}
return 0;
}
#ifdef WIN32
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
#else
return 0;
#endif
}
// Window Procedure
//
LRESULT CALLBACK resizeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
#ifdef WIN32
resizeClass *gThis = (resizeClass *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
if (!gThis)
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
else
return gThis->wndProc(hwnd, uMsg, wParam, lParam);
#else
return 0;
#endif
}
void resizeClass::setResizeCursor(int action)
{}