diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Library/ml_devices/widgetHost.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Plugins/Library/ml_devices/widgetHost.cpp')
-rw-r--r-- | Src/Plugins/Library/ml_devices/widgetHost.cpp | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_devices/widgetHost.cpp b/Src/Plugins/Library/ml_devices/widgetHost.cpp new file mode 100644 index 00000000..0b8e2ae9 --- /dev/null +++ b/Src/Plugins/Library/ml_devices/widgetHost.cpp @@ -0,0 +1,391 @@ +#include "main.h" +#include "./widgetHost.h" + + +#define WIDGETHOST_WINDOW_CLASS L"NullsoftDevicesWidgetHost" +#define WIDGETHOST_WIDGET_ID 1000 + +typedef +enum WidgetHostState +{ + WIDGETHOST_STATE_FROZEN_UI = (1 << 0), +} WidgetHostState; +DEFINE_ENUM_FLAG_OPERATORS(WidgetHostState); + +typedef struct WidgetHost +{ + WidgetHostState state; + WidgetStyle widgetStyle; + HFONT font; + HRGN updateRegion; + POINT updateOffset; +} WidgetHost; + +typedef struct WidgetHostCreateParam +{ + WidgetCreateProc widgetCreate; + void *widgetCreateParam; +} WidgetHostCreateParam; + +#define WIDGETHOST(_hwnd) ((WidgetHost*)(LONGX86)GetWindowLongPtrW((_hwnd), 0)) +#define WIDGETHOST_RET_VOID(_self, _hwnd) {(_self) = WIDGETHOST((_hwnd)); if (NULL == (_self)) return;} +#define WIDGETHOST_RET_VAL(_self, _hwnd, _error) {(_self) = WIDGETHOST((_hwnd)); if (NULL == (_self)) return (_error);} + +#define WIDGETHOST_WIDGET(_hostWindow) (GetDlgItem((_hostWindow), WIDGETHOST_WIDGET_ID)) + +#define WIDGETHOST_IS_FROZEN(_self) (0 != (WIDGETHOST_STATE_FROZEN_UI & (_self)->state)) +#define WIDGETHOST_FREEZE(_self) (((_self)->state) |= WIDGETHOST_STATE_FROZEN_UI) +#define WIDGETHOST_THAW(_self) (((_self)->state) &= ~WIDGETHOST_STATE_FROZEN_UI) + + +static LRESULT CALLBACK +WidgetHost_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam); + +static ATOM +WidgetHost_GetClassAtom(HINSTANCE instance) +{ + WNDCLASSEXW klass; + ATOM klassAtom; + + klassAtom = (ATOM)GetClassInfoExW(instance, WIDGETHOST_WINDOW_CLASS, &klass); + if (0 != klassAtom) + return klassAtom; + + memset(&klass, 0, sizeof(klass)); + klass.cbSize = sizeof(klass); + klass.style = CS_DBLCLKS; + klass.lpfnWndProc = WidgetHost_WindowProc; + klass.cbClsExtra = 0; + klass.cbWndExtra = sizeof(WidgetHost*); + klass.hInstance = instance; + klass.hIcon = NULL; + klass.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + klass.hbrBackground = NULL; + klass.lpszMenuName = NULL; + klass.lpszClassName = WIDGETHOST_WINDOW_CLASS; + klass.hIconSm = NULL; + klassAtom = RegisterClassExW(&klass); + + return klassAtom; +} + + +HWND +WidgetHost_Create(unsigned int windowStyle, int x, int y, int width, int height, + HWND parentWindow, WidgetCreateProc createProc, void *createParam) +{ + HINSTANCE instance; + ATOM klassAtom; + HWND hwnd; + WidgetHostCreateParam hostParam; + + + if (NULL == createProc) + return NULL; + + instance = GetModuleHandleW(NULL); + klassAtom = WidgetHost_GetClassAtom(instance); + if (0 == klassAtom) + return NULL; + + hostParam.widgetCreate = createProc; + hostParam.widgetCreateParam = createParam; + + + hwnd = CreateWindowExW(WS_EX_NOPARENTNOTIFY |WS_EX_CONTROLPARENT, + (LPCWSTR)MAKEINTATOM(klassAtom), NULL, + WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | windowStyle, + x, y, width, height, + parentWindow, NULL, instance, &hostParam); + + return hwnd; +} + +static void +WidgetHost_Layout(HWND hwnd, BOOL redraw) +{ + WidgetHost *self; + RECT rect; + WIDGETHOST_RET_VOID(self, hwnd); + + if (FALSE == GetClientRect(hwnd, &rect)) + return; + + HWND widgetWindow = WIDGETHOST_WIDGET(hwnd); + if (NULL != widgetWindow) + { + unsigned int flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER; + if (FALSE == redraw) + flags |= SWP_NOREDRAW; + + SetWindowPos(widgetWindow, NULL, 0, 0, RECTWIDTH(rect), RECTHEIGHT(rect), flags); + } +} + +static void +WidgetHost_Paint(HWND hwnd, HDC hdc, const RECT *paintRect, BOOL erase) +{ + if (FALSE != erase) + { + COLORREF backColor, prevBackColor; + backColor = Graphics_GetSkinColor(WADLG_WNDBG); + prevBackColor = SetBkColor(hdc, backColor); + + ExtTextOut(hdc, 0, 0, ETO_OPAQUE, paintRect, NULL, 0, NULL); + SetBkColor(hdc, prevBackColor); + } +} + +static void +WidgetHost_UpdateSkin(HWND hwnd) +{ + WidgetHost *self; + WIDGETHOST_RET_VOID(self, hwnd); + BOOL styleChanged = FALSE; + + if (FALSE != WidgetStyle_UpdateDefaultColors(&self->widgetStyle)) + styleChanged = TRUE; + + if (FALSE != styleChanged) + { + HWND widgetWindow = WIDGETHOST_WIDGET(hwnd); + if (NULL != widgetWindow) + { + WIDGET_STYLE_COLOR_CHANGED(widgetWindow); + InvalidateRect(widgetWindow, NULL, TRUE); + } + } + +} + +static void +WidgetHost_UpdateFont(HWND hwnd, BOOL redraw) +{ + WidgetHost *self; + BOOL styleChanged = FALSE; + long unitWidth, unitHeight; + + WIDGETHOST_RET_VOID(self, hwnd); + + if (FALSE == Graphics_GetWindowBaseUnits(hwnd, &unitWidth, &unitHeight)) + { + unitWidth = 6; + unitHeight = 13; + } + + if (FALSE != WidgetStyle_UpdateDefaultFonts(&self->widgetStyle, self->font, unitWidth, unitHeight)) + styleChanged = TRUE; + + if (FALSE != styleChanged) + { + HWND widgetWindow = WIDGETHOST_WIDGET(hwnd); + if (NULL != widgetWindow) + { + WIDGET_STYLE_COLOR_CHANGED(widgetWindow); + InvalidateRect(widgetWindow, NULL, TRUE); + } + } + +} + +static LRESULT +WidgetHost_OnCreate(HWND hwnd, CREATESTRUCT *createStruct) +{ + WidgetHost *self; + HWND widgetWindow; + WidgetHostCreateParam *createParam; + + if (NULL == createStruct) + return -1; + + createParam = (WidgetHostCreateParam*)createStruct->lpCreateParams; + if (NULL == createParam) + return -1; + + self = (WidgetHost*)malloc(sizeof(WidgetHost)); + if (NULL == self) + return -1; + + SetLastError(ERROR_SUCCESS); + if (!SetWindowLongPtr(hwnd, 0, (LONGX86)self) && ERROR_SUCCESS != GetLastError()) + return -1; + + memset(self, 0, sizeof(WidgetHost)); + + WIDGETHOST_FREEZE(self); + + MLSkinWindow2(Plugin_GetLibraryWindow(), hwnd, SKINNEDWND_TYPE_WINDOW, + SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS); + + WidgetHost_UpdateFont(hwnd, FALSE); + WidgetHost_UpdateSkin(hwnd); + + widgetWindow = NULL; + if (NULL != createParam->widgetCreate) + widgetWindow = createParam->widgetCreate(hwnd, createParam->widgetCreateParam); + + if (NULL == widgetWindow) + return -1; + + SetWindowLongPtrW(widgetWindow, GWLP_ID, WIDGETHOST_WIDGET_ID); + + WIDGET_SET_STYLE(widgetWindow, &self->widgetStyle); + + SetWindowPos(widgetWindow, NULL, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_FRAMECHANGED); + + ShowWindow(widgetWindow, SW_SHOWNA); + + SetWindowPos(widgetWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + + WIDGETHOST_THAW(self); + + SetWindowPos(hwnd, NULL, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); + + return 0; +} + +static void +WidgetHost_OnDestroy(HWND hwnd) +{ + WidgetHost *self; + + self = WIDGETHOST(hwnd); + SetWindowLongPtr(hwnd, 0, 0); + + if (NULL == self) + return; + + WIDGETHOST_FREEZE(self); + + WidgetStyle_Free(&self->widgetStyle); + free(self); +} + +static void +WidgetHost_OnPaint(HWND hwnd) +{ + PAINTSTRUCT ps; + + if (NULL != BeginPaint(hwnd, &ps)) + { + WidgetHost_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase); + EndPaint(hwnd, &ps); + } +} + +static void +WidgetHost_OnPrintClient(HWND hwnd, HDC hdc, UINT options) +{ + RECT clientRect; + if (GetClientRect(hwnd, &clientRect)) + { + WidgetHost_Paint(hwnd, hdc, &clientRect, TRUE); + } +} + +static void +WidgetHost_OnWindowPosChanged(HWND hwnd, WINDOWPOS *windowPos) +{ + if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED) & windowPos->flags)) + { + WidgetHost *self; + WIDGETHOST_RET_VOID(self, hwnd); + + if (FALSE != WIDGETHOST_IS_FROZEN(self)) + return; + + WidgetHost_Layout(hwnd, 0 == (SWP_NOREDRAW & windowPos->flags)); + } +} + +static void +WidgetHost_OnDisplayChanged(HWND hwnd, INT bpp, INT dpi_x, INT dpi_y) +{ + WidgetHost *self; + WIDGETHOST_RET_VOID(self, hwnd); + + if (FALSE != WIDGETHOST_IS_FROZEN(self)) + return; + + WidgetHost_UpdateSkin(hwnd); + InvalidateRect(hwnd, NULL, TRUE); +} + +static void +WidgetHost_OnSetFont(HWND hwnd, HFONT font, BOOL redraw) +{ + WidgetHost *self; + LOGFONTW prevFont, newFont; + + WIDGETHOST_RET_VOID(self, hwnd); + + if (NULL == self->font || + sizeof(LOGFONTW) != GetObjectW(self->font, sizeof(prevFont), &prevFont)) + { + ZeroMemory(&prevFont, sizeof(prevFont)); + } + + self->font = font; + + + if (NULL == self->font || + sizeof(newFont) != GetObjectW(self->font, sizeof(newFont), &newFont)) + { + ZeroMemory(&newFont, sizeof(newFont)); + } + + if (0 != memcmp(&prevFont, &newFont, sizeof(prevFont)) && + FALSE == WIDGETHOST_IS_FROZEN(self)) + { + WidgetHost_UpdateFont(hwnd, redraw); + } +} + +static HFONT +WidgetHost_OnGetFont(HWND hwnd) +{ + WidgetHost *self; + WIDGETHOST_RET_VAL(self, hwnd, NULL); + + return self->font; +} + +static void +WidgetHost_OnSetUpdateRegion(HWND hwnd, HRGN updateRegion, POINTS regionOffset) +{ + WidgetHost *self; + WIDGETHOST_RET_VOID(self, hwnd); + + self->updateRegion = updateRegion; + self->updateOffset.x = regionOffset.x; + self->updateOffset.y = regionOffset.y; +} + + +static LRESULT CALLBACK +WidgetHost_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_CREATE: return WidgetHost_OnCreate(hwnd, (CREATESTRUCT*)lParam); + case WM_DESTROY: WidgetHost_OnDestroy(hwnd); return 0; + case WM_PAINT: WidgetHost_OnPaint(hwnd); return 0; + case WM_PRINTCLIENT: WidgetHost_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0; + case WM_PRINT: return 0; + case WM_ERASEBKGND: return 0; + case WM_WINDOWPOSCHANGED: WidgetHost_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0; + case WM_SIZE: return 0; + case WM_MOVE: return 0; + case WM_DISPLAYCHANGE: WidgetHost_OnDisplayChanged(hwnd, (INT)wParam, LOWORD(lParam), HIWORD(lParam)); return 0; + case WM_SETFONT: WidgetHost_OnSetFont(hwnd, (HFONT)wParam, LOWORD(lParam)); return 0; + case WM_GETFONT: return (LRESULT)WidgetHost_OnGetFont(hwnd); + + // gen_ml flickerless drawing + case WM_USER + 0x200: return 1; + case WM_USER + 0x201: WidgetHost_OnSetUpdateRegion(hwnd, (HRGN)lParam, MAKEPOINTS(wParam)); return 0; + + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +}
\ No newline at end of file |