#include "precomp_wasabi_bfc.h" #include "wasabi_std_wnd.h" #include "api.h" #include #include #include #include #include "../winamp/wa_ipc.h" #ifndef AC_SRC_ALPHA const int AC_SRC_ALPHA = 1; #endif #ifndef THBN_CLICKED #define THBN_CLICKED 0x1800 #endif static int nreal = 0; #ifdef __APPLE__ OSStatus MyWindowEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); OSStatus MyControlEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData); #endif #ifdef _WIN32 static HINSTANCE gdi32instance = NULL; static int(WINAPI *getRandomRgn)(HDC dc, HRGN rgn, int i) = NULL; static int grrfailed = 0; static void register_wndClass(HINSTANCE hInstance); static int versionChecked = 0; static int isNT = 0; static int IsNT() { if (versionChecked) return isNT; if (GetVersion() < 0x80000000) isNT = 1; versionChecked = 1; return isNT; } int Wasabi::Std::Wnd::alphaStretchBlit(HDC destHDC, int dstx, int dsty, int dstw, int dsth, HDC sourceHDC, int srcx, int srcy, int srcw, int srch) { if (IsNT()) { SetStretchBltMode(destHDC, HALFTONE); StretchBlt(destHDC, dstx, dsty, dstw, dsth, sourceHDC, srcx , srcy, srcw, srch, SRCCOPY); return 1; } else return 0; } #endif #ifdef __APPLE__ enum { kWasabi = 'WASA' }; const ControlID kWasabiID = { kWasabi, 0 }; void GetWasabiHIView(WindowRef window, HIViewRef *control) { GetControlByID(window, &kWasabiID, control); } OSStatus CreateHIView ( WindowRef inWindow, const Rect* inBounds, ControlRef* outControl ) { OSStatus err; ControlRef root; EventRef event; // Make an initialization event err = CreateEvent( NULL, kEventClassHIObject, kEventHIObjectInitialize, GetCurrentEventTime(), 0, &event ); require_noerr( err, CantCreateEvent ); // If bounds were specified, push the them into the initialization event // so that they can be used in the initialization handler. if ( inBounds != NULL ) { err = SetEventParameter( event, 'boun', typeQDRectangle, sizeof( Rect ), inBounds ); require_noerr( err, CantSetParameter ); } err = HIObjectCreate( kHIViewClassID, event, (HIObjectRef*) outControl ); require_noerr( err, CantCreate ); // If a parent window was specified, place the new view into the // parent window. if ( inWindow != NULL ) { err = GetRootControl( inWindow, &root ); require_noerr( err, CantGetRootControl ); err = HIViewAddSubview( root, *outControl ); SetControlID( *outControl, &kWasabiID ); HIViewSetVisible(*outControl, true); } CantCreate: CantGetRootControl: CantSetParameter: CantCreateEvent: ReleaseEvent( event ); CantRegister: return err; } #endif OSWINDOWHANDLE Wasabi::Std::Wnd::createWnd(RECT *r, int nochild, int acceptdrops, OSWINDOWHANDLE parent, OSMODULEHANDLE module, ifc_window *rw) { #ifdef _WIN32 register_wndClass(module); int style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; int exstyle=0; if (parent == NULL) { exstyle |= WS_EX_TOOLWINDOW; style |= WS_POPUP; } else style |= WS_CHILD; if (nochild) style=WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; if (acceptdrops) exstyle |= WS_EX_ACCEPTFILES; HWND ret = CreateWindowExW(exstyle, BASEWNDCLASSNAME, NULL, style, r->left, r->top, r->right - r->left, r->bottom - r->top, parent, NULL, module, (LPVOID)rw); if (ret != INVALIDOSWINDOWHANDLE) { nreal++; if(NULL != WASABI_API_APP && 0 != (WS_POPUP & style)) WASABI_API_APP->app_registerGlobalWindow(ret); } return ret; #elif defined(__APPLE__) Rect wndRect; SetRect(&wndRect, r->left, r->top, r->right, r->bottom); WindowRef newWnd; CreateNewWindow(kOverlayWindowClass, kWindowCompositingAttribute, &wndRect, &newWnd); SetWindowGroup(newWnd, GetWindowGroupOfClass(kDocumentWindowClass)); // install a window event handler const EventTypeSpec windowEventList[] = { { kEventClassCommand, kEventProcessCommand }, // { kEventClassWindow, kEventWindowBoundsChanging }, { kEventClassWindow, kEventWindowBoundsChanged }, // { kEventClassWindow, kEventWindowInit }, {kEventClassMouse, kEventMouseDown}, {kEventClassMouse, kEventMouseUp}, {kEventClassMouse, kEventMouseMoved}, {kEventClassMouse, kEventMouseDragged}, //{kEventClassMouse, kEventMouseEntered}, //{kEventClassMouse, kEventMouseExited}, //{kEventClassMouse, kEventMouseWheelMoved}, {kEventClassKeyboard, kEventRawKeyDown}, {kEventClassKeyboard, kEventRawKeyUp}, }; InstallWindowEventHandler(newWnd, MyWindowEventHandler, GetEventTypeCount(windowEventList), windowEventList, rw, NULL); // create the content view HIViewRef myHIView; CreateHIView(newWnd,&wndRect,(ControlRef*)&myHIView); const EventTypeSpec controlEventList[] = { { kEventClassControl, kEventControlDraw}, { kEventClassControl, kEventControlApplyBackground}, }; InstallEventHandler(GetControlEventTarget(myHIView), MyControlEventHandler, GetEventTypeCount(controlEventList), controlEventList, rw, NULL); return newWnd; #endif } void Wasabi::Std::Wnd::destroyWnd(OSWINDOWHANDLE wnd) { #ifdef _WIN32 if(NULL != WASABI_API_APP && 0 != (WS_POPUP & GetWindowLongPtr(wnd, GWL_STYLE))) WASABI_API_APP->app_unregisterGlobalWindow(wnd); DestroyWindow(wnd); nreal--; if (nreal == 0) { if (gdi32instance) FreeLibrary(gdi32instance); gdi32instance = NULL; getRandomRgn = NULL; } #elif defined(__APPLE__) DisposeWindow(wnd); #endif } int Wasabi::Std::Wnd::isValidWnd(OSWINDOWHANDLE wnd) { #ifdef _WIN32 return IsWindow(wnd); #elif defined(__APPLE__) // TODO: docs suggest that this function is slow if (!wnd) return 0; return IsValidWindowPtr(wnd); #endif } #ifdef _WIN32 void Wasabi::Std::Wnd::setLayeredWnd(OSWINDOWHANDLE wnd, int layered) { if (layered) { // have to clear and reset, can't just set SetWindowLong(wnd, GWL_EXSTYLE, GetWindowLong(wnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); SetWindowLong(wnd, GWL_EXSTYLE, GetWindowLong(wnd, GWL_EXSTYLE) | WS_EX_LAYERED); } else { SetWindowLong(wnd, GWL_EXSTYLE, GetWindowLong(wnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); } } int Wasabi::Std::Wnd::isLayeredWnd(OSWINDOWHANDLE wnd) { DWORD dwLong = GetWindowLong(wnd, GWL_EXSTYLE); return !!(dwLong & WS_EX_LAYERED); } void Wasabi::Std::Wnd::setLayeredAlpha(OSWINDOWHANDLE wnd, int amount) { if (!isDesktopAlphaAvailable()) return; SetLayeredWindowAttributes(wnd, RGB(0, 0, 0), amount, LWA_ALPHA); } void Wasabi::Std::Wnd::updateLayeredWnd(OSWINDOWHANDLE wnd, int x, int y, int w, int h, HDC surfdc, int alpha) { if (!isDesktopAlphaAvailable()) return; BLENDFUNCTION blend = {AC_SRC_OVER, 0, (BYTE)alpha, AC_SRC_ALPHA }; POINT sp = {x, y}, pt = {0, 0}; SIZE ss = { w, h }; //HDC sysdc = GetDC(NULL); UpdateLayeredWindow(wnd, NULL/*sysdc*/, &sp, &ss, surfdc, &pt, 0, &blend, ULW_ALPHA); //ReleaseDC(NULL, sysdc); } #endif void Wasabi::Std::Wnd::setWndPos(OSWINDOWHANDLE wnd, OSWINDOWHANDLE zorder, int x, int y, int w, int h, int nozorder, int noactive, int nocopybits, int nomove, int noresize) { #ifdef _WIN32 SetWindowPos(wnd, zorder, x, y, w, h, SWP_DEFERERASE | // we ignore WM_SYNCPAINT anyway (nozorder ? SWP_NOZORDER : 0) | (noactive ? SWP_NOACTIVATE : 0) | (nocopybits ? SWP_NOCOPYBITS : 0) | (nomove ? SWP_NOMOVE : 0) | (noresize ? SWP_NOSIZE : 0)); #elif defined(__APPLE__) if (!nomove) { MoveWindow(wnd, x, y, false); } if (!noresize) { Rect newRect; newRect.left = x; newRect.right=x+w; newRect.top = y; newRect.bottom = y+h; // SetWindowBounds(wnd, kWindowStructureRgn, &newRect); SizeWindow(wnd, w, h, false); } if (!noactive) SelectWindow(wnd); if (!nocopybits) Wasabi::Std::Wnd::invalidateRect(wnd, 0); #endif } void Wasabi::Std::Wnd::bringToFront(OSWINDOWHANDLE wnd) { #ifdef _WIN32 SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_NOOWNERZORDER); #elif defined(__APPLE__) BringToFront(wnd); #endif } void Wasabi::Std::Wnd::sendToBack(OSWINDOWHANDLE wnd) { #ifdef _WIN32 SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_NOOWNERZORDER); #elif defined(__APPLE__) SendBehind(wnd, 0); #endif } OSWINDOWHANDLE Wasabi::Std::Wnd::getWindowFromPoint(POINT pt) { #ifdef _WIN32 return ::WindowFromPoint(pt); #else #warning port me return 0; #endif } int Wasabi::Std::Wnd::isWndVisible(OSWINDOWHANDLE wnd) { return IsWindowVisible(wnd); } void Wasabi::Std::Wnd::showWnd(OSWINDOWHANDLE wnd, int noactivate) { #ifdef _WIN32 ShowWindow(wnd, noactivate ? SW_SHOWNA : SW_SHOWNORMAL); #elif defined(__APPLE__) ShowWindow(wnd); if (!noactivate) ActivateWindow(wnd, 1); #endif } void Wasabi::Std::Wnd::hideWnd(OSWINDOWHANDLE wnd) { #ifdef _WIN32 ShowWindow(wnd, SW_HIDE); #elif defined(__APPLE__) HideWindow(wnd); #endif } int Wasabi::Std::Wnd::isPopup(OSWINDOWHANDLE wnd) { #ifdef _WIN32 return !!(GetWindowLong(wnd, GWL_STYLE) & WS_POPUP); #elif defined(__APPLE__) return 0; // TODO: maybe use window class or window group to determine #endif } #ifdef _WIN32 void Wasabi::Std::Wnd::setEnabled(OSWINDOWHANDLE wnd, int enabled) { EnableWindow(wnd, enabled); } #endif void Wasabi::Std::Wnd::setFocus(OSWINDOWHANDLE wnd) { #ifdef _WIN32 SetFocus(wnd); #elif defined(__APPLE__) SetUserFocusWindow(wnd); #endif } OSWINDOWHANDLE Wasabi::Std::Wnd::getFocus() { #ifdef _WIN32 return GetFocus(); #elif defined(__APPLE__) return GetUserFocusWindow(); #endif } #ifdef _WIN32 void Wasabi::Std::Wnd::setTopmost(OSWINDOWHANDLE wnd, int topmost) { SetWindowPos(wnd, topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE); } #endif void Wasabi::Std::Wnd::invalidateRect(OSWINDOWHANDLE wnd, RECT *r) { #ifdef _WIN32 OSREGIONHANDLE reg = NULL; if (r == NULL) { RECT cr; if (!IsWindow(wnd)) return; GetClientRect(wnd, &cr); reg = CreateRectRgnIndirect(&cr); } else reg = CreateRectRgnIndirect(r); invalidateRegion(wnd, reg); DeleteObject(reg); #elif defined(__APPLE__) HIViewRef view; GetWasabiHIView(wnd, &view); if (r == 0) { HIViewSetNeedsDisplay(view, true); } else { HIRect rect = CGRectMake(r->left, r->top, r->right-r->left, r->bottom - r->top); HIViewSetNeedsDisplayInRect(view, &rect, true); } #endif } void Wasabi::Std::Wnd::invalidateRegion(OSWINDOWHANDLE wnd, OSREGIONHANDLE region) { #ifdef _WIN32 clipOSChildren(wnd, region); InvalidateRgn(wnd, region, FALSE); #elif defined(__APPLE__) HIViewRef view; GetWasabiHIView(wnd, &view); HIViewSetNeedsDisplayInShape(view, region, true); #endif } void Wasabi::Std::Wnd::validateRect(OSWINDOWHANDLE wnd, RECT *r) { #ifdef _WIN32 ValidateRect(wnd, r); #elif defined(__APPLE__) HIViewRef view; GetWasabiHIView(wnd, &view); if (r == 0) { HIViewSetNeedsDisplay(view, false); } else { HIRect rect = CGRectMake(r->left, r->top, r->right-r->left, r->bottom - r->top); HIViewSetNeedsDisplayInRect(view, &rect, false); } #endif } void Wasabi::Std::Wnd::validateRegion(OSWINDOWHANDLE wnd, OSREGIONHANDLE region) { #ifdef _WIN32 ValidateRgn(wnd, region); #elif defined(__APPLE__) HIViewRef view; GetWasabiHIView(wnd, &view); HIViewSetNeedsDisplayInShape(view, region, false); #endif } void Wasabi::Std::Wnd::update(OSWINDOWHANDLE wnd) { #ifdef _WIN32 if (wnd != NULL) UpdateWindow(wnd); #elif defined(__APPLE__) if (wnd) { HIViewRef view; GetWasabiHIView(wnd, &view); HIViewRender(view); } #endif } int Wasabi::Std::Wnd::getUpdateRect(OSWINDOWHANDLE wnd, RECT *r) { #ifdef _WIN32 return GetUpdateRect(wnd, r, FALSE); #else Rect updateRect; GetWindowBounds(wnd, kWindowUpdateRgn, &updateRect); r->left=updateRect.left; r->right = updateRect.right; r->top = updateRect.top; r->bottom = updateRect.bottom; #endif } #ifdef _WIN32 void Wasabi::Std::Wnd::getUpdateRegion(OSWINDOWHANDLE wnd, OSREGIONHANDLE region) { GetUpdateRgn(wnd, region, FALSE); } #elif defined(__APPLE__) // TODO: GetWindowRegion(wnd, kWindowUpdateRgn, region); #endif #ifdef _WIN32 int Wasabi::Std::Wnd::haveGetRandomRegion() { // I assume linux will just return FALSE if (gdi32instance == NULL && !grrfailed) { gdi32instance = LoadLibrary(L"GDI32.dll"); if (gdi32instance != NULL) { getRandomRgn = (int(WINAPI *)(HDC, HRGN, int)) GetProcAddress(gdi32instance, "GetRandomRgn"); if (getRandomRgn == NULL) { grrfailed = 1; FreeLibrary(gdi32instance); gdi32instance = NULL; } } else { grrfailed = 1; } } return (getRandomRgn != NULL); } void Wasabi::Std::Wnd::getRandomRegion(HDC hdc, OSREGIONHANDLE region) { if (!haveGetRandomRegion()) return; (*getRandomRgn)(hdc, region, SYSRGN); } #endif void Wasabi::Std::Wnd::setWndRegion(OSWINDOWHANDLE wnd, OSREGIONHANDLE region, int redraw) { #ifdef _WIN32 SetWindowRgn(wnd, region, !!redraw); #elif defined(__APPLE__) #warning port me? #endif } #ifdef _WIN32 int Wasabi::Std::Wnd::isDesktopAlphaAvailable() { return 1; // we're only targetting windows 2000 and up, so it's always available } #endif int Wasabi::Std::Wnd::isTransparencyAvailable() { #ifdef _WIN32 // there is no win32 implementation that supports setLayeredWindowAttributes but not updateLayeredWindow return Wasabi::Std::Wnd::isDesktopAlphaAvailable(); #elif defined(__APPLE__) return 1; #else #error port me #endif } void Wasabi::Std::Wnd::getClientRect(OSWINDOWHANDLE wnd, RECT *r) { #ifdef _WIN32 GetClientRect(wnd, r); #elif defined(__APPLE__) Rect temp; GetWindowBounds(wnd, kWindowContentRgn, &temp); r->left = 0; r->top = 0; r->right = temp.right-temp.left; r->bottom = temp.bottom-temp.top; #endif } void Wasabi::Std::Wnd::getWindowRect(OSWINDOWHANDLE wnd, RECT *r) { #ifdef _WIN32 GetWindowRect(wnd, r); #elif defined(__APPLE__) Rect temp; GetWindowBounds(wnd, kWindowGlobalPortRgn, &temp); r->left = temp.left; r->top = temp.top; r->right = temp.right; r->bottom = temp.bottom; #endif } void Wasabi::Std::Wnd::clientToScreen(OSWINDOWHANDLE wnd, int *x, int *y) { #ifdef _WIN32 POINT p = { x ? *x : 0, y ? *y : 0 }; ClientToScreen(wnd, &p); if (x) *x = p.x; if (y) *y = p.y; #elif defined(__APPLE__) Point pt; pt.h = x?*x:0; pt.v = y?*y:0; QDLocalToGlobalPoint(GetWindowPort(wnd) , &pt); if (x) *x = pt.h; if (y) *y = pt.v; #endif } void Wasabi::Std::Wnd::screenToClient(OSWINDOWHANDLE wnd, int *x, int *y) { #ifdef _WIN32 POINT p = { x ? *x : 0, y ? *y : 0 }; ScreenToClient(wnd, &p); if (x) *x = p.x; if (y) *y = p.y; #elif defined(__APPLE__) Point pt; pt.h = x?*x:0; pt.v = y?*y:0; QDGlobalToLocalPoint(GetWindowPort(wnd) , &pt); if (x) *x = pt.h; if (y) *y = pt.v; #endif } #ifdef _WIN32 void Wasabi::Std::Wnd::setParent(OSWINDOWHANDLE child, OSWINDOWHANDLE newparent) { SetParent(child, newparent); } #endif OSWINDOWHANDLE Wasabi::Std::Wnd::getParent(OSWINDOWHANDLE wnd) { #ifdef _WIN32 return GetParent(wnd); #else return 0; #endif } #ifdef _WIN32 OSWINDOWHANDLE Wasabi::Std::Wnd::getTopmostChild(OSWINDOWHANDLE wnd) { return GetWindow(wnd, GW_CHILD); } void Wasabi::Std::Wnd::setCapture(OSWINDOWHANDLE wnd) { SetCapture(wnd); } void Wasabi::Std::Wnd::releaseCapture() { ReleaseCapture(); } OSWINDOWHANDLE Wasabi::Std::Wnd::getCapture() { return GetCapture(); } void Wasabi::Std::Wnd::revokeDragNDrop(OSWINDOWHANDLE wnd) { if (wnd == NULL) return; RevokeDragDrop(wnd); } #endif void Wasabi::Std::Wnd::setWndName(OSWINDOWHANDLE wnd, const wchar_t *name) { #ifdef _WIN32 SetWindowTextW(wnd, name); #elif defined(__APPLE__) // TODO: //SetWindowTitleWithCFString(wnd, #endif } void Wasabi::Std::Wnd::getWndName(OSWINDOWHANDLE wnd, wchar_t *name, int maxlen) { #ifdef _WIN32 GetWindowTextW(wnd, name, maxlen); #else name[0]=0; #warning port me #endif } void Wasabi::Std::Wnd::setIcon(OSWINDOWHANDLE wnd, OSICONHANDLE icon, int large) { #ifdef _WIN32 SendMessageW(wnd, WM_SETICON, !large ? ICON_SMALL : ICON_BIG, (LPARAM)icon); #else #warning port me #endif } OSWINDOWHANDLE Wasabi::Std::Wnd::getActiveWindow() { #ifdef _WIN32 return GetActiveWindow(); #elif defined(__APPLE__) return ActiveNonFloatingWindow(); #endif } void Wasabi::Std::Wnd::setActiveWindow(OSWINDOWHANDLE wnd) { #ifdef _WIN32 SetActiveWindow(wnd); #elif defined(__APPLE__) SelectWindow(wnd); #endif } #ifdef _WIN32 // clip oswindow children off the invalidation region void Wasabi::Std::Wnd::clipOSChildren(OSWINDOWHANDLE wnd, OSREGIONHANDLE reg) { HWND w = GetWindow(wnd, GW_CHILD); while (w != NULL) { if (IsWindowVisible(w)) { RECT r; GetClientRect(w, &r); POINT p = {r.left, r.top}; ClientToScreen(w, &p); ScreenToClient(wnd, &p); OffsetRect(&r, p.x, p.y); OSREGIONHANDLE cr = CreateRectRgnIndirect(&r); OSREGIONHANDLE or = CreateRectRgn(0, 0, 0, 0); CombineRgn(or, reg, 0, RGN_COPY); CombineRgn(reg, or, cr, RGN_DIFF); DeleteObject(cr); DeleteObject(or); } w = GetWindow(w, GW_HWNDNEXT); } } ////////////////////////// static LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // fetch out the api_window * if (uMsg == WM_CREATE) { CREATESTRUCT *cs = (CREATESTRUCT *)lParam; ASSERT(cs->lpCreateParams != NULL); // stash pointer to self SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams); } // pass the messages into the BaseWnd ifc_window *rootwnd = (ifc_window*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); if (rootwnd == NULL || rootwnd->getOsWindowHandle() != hWnd) { return DefWindowProcW(hWnd, uMsg, wParam, lParam); } else { LRESULT r = 0; switch (uMsg) { case WM_CLOSE: PostMessage(GetParent(hWnd), WM_CLOSE, wParam, lParam); return 0; case WM_NCPAINT: return 0; case WM_SYNCPAINT: return 0; // case WM_SETFOCUS: r = rootwnd->windowEvent(WndEvent::SETFOCUS); // case WM_KILLFOCUS: r = rootwnd->windowEvent(WndEvent::KILLFOCUS); case WM_ACTIVATE: if ( (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) && IsIconic(GetParent(hWnd)) ) { ShowWindow(GetParent(hWnd), SW_RESTORE); } r = rootwnd->wndProc(hWnd, uMsg, wParam, lParam); break; case WM_COMMAND: if (HIWORD(wParam) == THBN_CLICKED) { HWND parentWnd = GetParent(hWnd); if (parentWnd == NULL) parentWnd = hWnd; switch (LOWORD(wParam)) { case 0: //previous { SendMessage(parentWnd, WM_COMMAND, 40044, 0); } break; case 1: //play { SendMessage(parentWnd, WM_COMMAND, 40045, 0); } break; case 2: //pause { SendMessage(parentWnd, WM_COMMAND, 40046, 0); } break; case 3: //stop { SendMessage(parentWnd, WM_COMMAND, 40047, 0); } break; case 4: //next { SendMessage(parentWnd, WM_COMMAND, 40048, 0); } break; } } default: r = rootwnd->wndProc(hWnd, uMsg, wParam, lParam); } if (IsWindow(hWnd)) // wndProc may have switched skin and killed this window rootwnd->performBatchProcesses(); return r; } } static void register_wndClass(HINSTANCE hInstance) { WNDCLASSW wc; if (GetClassInfoW(hInstance, BASEWNDCLASSNAME, &wc)) return; // regiszter pane class wc.style = 0; wc.lpfnWndProc = (WNDPROC)wndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = BASEWNDCLASSNAME; int r = RegisterClassW(&wc); if (r == 0) { int res = GetLastError(); if (res != ERROR_CLASS_ALREADY_EXISTS) { char florp[WA_MAX_PATH] = {0}; SPRINTF(florp, "Failed to register class, err %d", res); ASSERTPR(0, florp); } } } #endif #ifdef __APPLE__ // TODO: call into BaseWnd and take this out of here #include #include #include OSStatus MyWindowEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) { HICommand hiCommand; OSStatus err = eventNotHandledErr; UInt32 eventClass = GetEventClass(inEvent); UInt32 eventKind = GetEventKind(inEvent); ifc_window *wasabiWnd = (ifc_window *)inUserData; WindowRef window = wasabiWnd->getOsWindowHandle(); switch (eventClass) { case kEventClassKeyboard: switch (eventKind) { case kEventRawKeyDown: { UInt32 keyCode; GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(keyCode), NULL, &keyCode); if (wasabiWnd->onKeyDown(keyCode)) err = noErr; } break; case kEventRawKeyUp: { UInt32 keyCode; GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(keyCode), NULL, &keyCode); if (wasabiWnd->onKeyUp(keyCode)) err = noErr; } break; } break; case kEventClassMouse: switch (eventKind) { case kEventMouseDown: { HIPoint point; GetEventParameter(inEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point); EventMouseButton button; GetEventParameter(inEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); UInt32 modifiers; GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); switch (button) { case kEventMouseButtonPrimary: if (modifiers & controlKey) // fake right click wasabiWnd->onRightButtonDown(point.x, point.y); else wasabiWnd->onLeftButtonDown(point.x, point.y); break; case kEventMouseButtonSecondary: wasabiWnd->onRightButtonDown(point.x, point.y); break; } } break; case kEventMouseUp: { HIPoint point; GetEventParameter(inEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point); EventMouseButton button; GetEventParameter(inEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); switch (button) { case kEventMouseButtonPrimary: wasabiWnd->onLeftButtonUp(point.x, point.y); break; case kEventMouseButtonSecondary: wasabiWnd->onRightButtonUp(point.x, point.y); break; } } break; case kEventMouseMoved: case kEventMouseDragged: { HIPoint point; GetEventParameter(inEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point); wasabiWnd->onMouseMove(point.x, point.y); } break; } break; case kEventClassCommand: if (eventKind == kEventProcessCommand) { err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &hiCommand); switch (hiCommand.commandID) { default: err = eventNotHandledErr; break; } } break; case kEventClassWindow: switch (eventKind) { case kEventWindowBoundsChanging: break; case kEventWindowBoundsChanged: { HIRect bounds; UInt32 attributes; Rect origBounds; Rect currBounds; ControlRef control; // Get the change attributes err = GetEventParameter(inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof(UInt32), NULL, &attributes); // If the window size changed //kWindowBoundsChangeOriginChanged if (attributes & kWindowBoundsChangeSizeChanged) { GetEventParameter(inEvent, kEventParamOriginalBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &origBounds); GetEventParameter(inEvent, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &currBounds); // Get the clock control err = GetControlByID( window, &kWasabiID, &control ); // Hide it (to avoid remnants when downsizing) //HIViewSetVisible( control, false ); // Resize it HIViewGetFrame( control, &bounds ); #define QDRECTWIDTH(R) ((R).right - (R).left) #define QDRECTHEIGHT(R) ((R).bottom - (R).top) bounds.size.width += QDRECTWIDTH( currBounds ) - QDRECTWIDTH( origBounds ); bounds.size.height += QDRECTHEIGHT( currBounds ) - QDRECTHEIGHT( origBounds ); HIViewSetFrame( control, &bounds ); // Show it //HIViewSetVisible( control, true ); } err = noErr; } break; case kEventWindowInit: break; } break; } return err; } OSStatus MyControlEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) { HICommand hiCommand; OSStatus err = eventNotHandledErr; UInt32 eventClass = GetEventClass(inEvent); UInt32 eventKind = GetEventKind(inEvent); ifc_window *wasabiWnd = (ifc_window *)inUserData; switch(eventClass) { case kEventClassControl: switch(eventKind) { case kEventControlDraw: { CGContextRef context; RgnHandle rgn; HIShapeRef shape; HIViewRef view; if (GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(context), NULL, &context) == noErr && GetEventParameter(inEvent, kEventParamRgnHandle, typeQDRgnHandle, NULL, sizeof(rgn), NULL, &rgn) == noErr && GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(view), NULL, &view) == noErr) { GetEventParameter(inEvent, kEventParamShape, typeHIShapeRef, NULL, sizeof(shape), NULL, &shape); HIRect bounds; HIViewGetBounds(view, &bounds); Canvas canvas(context); // RegionI region(rgn); RegionI region(shape); //((RootWndI *)wasabiWnd)->rootwnd_paintTree(&canvas, ®ion); wasabiWnd->paint(&canvas, ®ion); // TODO: should be virtualOnPaint() err = noErr; } } break; } break; } return err; } #endif