diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2020-12-29 16:09:43 +0100 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2020-12-29 16:39:54 +0100 |
commit | 645250e1cd8ce9bc1faea599df7a1b05836bfeb8 (patch) | |
tree | c6311afab3900d2dd2aecbfbe1ac348d0e48c428 /plugingui/nativewindow_win32.cc | |
parent | dce64999d3325c5b55499d6ba657066efa48fbff (diff) |
Split UI code into application/plugin UI and UI library.
Diffstat (limited to 'plugingui/nativewindow_win32.cc')
-rw-r--r-- | plugingui/nativewindow_win32.cc | 584 |
1 files changed, 0 insertions, 584 deletions
diff --git a/plugingui/nativewindow_win32.cc b/plugingui/nativewindow_win32.cc deleted file mode 100644 index 4b31130..0000000 --- a/plugingui/nativewindow_win32.cc +++ /dev/null @@ -1,584 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * nativewindow_win32.cc - * - * Fri Dec 28 18:45:52 CET 2012 - * Copyright 2012 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "nativewindow_win32.h" - -#include <cstring> -#include <algorithm> -#include <commctrl.h> - -#include "window.h" - -namespace GUI -{ - -static BOOL trackMouse(HWND hwnd) -{ - TRACKMOUSEEVENT ev{}; - ev.cbSize = sizeof(ev); - ev.dwFlags = TME_HOVER | TME_LEAVE; - ev.hwndTrack = hwnd; - ev.dwHoverTime = 1; - return TrackMouseEvent(&ev); -} - -LRESULT CALLBACK NativeWindowWin32::dialogProc(HWND hwnd, UINT msg, - WPARAM wp, LPARAM lp) -{ - NativeWindowWin32* native = - (NativeWindowWin32*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled. - if(!native) - { - return DefWindowProc(hwnd, msg, wp, lp); - } - - Window& window = native->window; - - switch(msg) - { - case WM_SIZE: - if(wp > 4) - { - // Bogus value - ignore - break; - } - { - auto resizeEvent = std::make_shared<ResizeEvent>(); - resizeEvent->width = LOWORD(lp); - resizeEvent->height = HIWORD(lp); - native->event_queue.push_back(resizeEvent); - } - break; - - case WM_MOVE: - { - auto moveEvent = std::make_shared<MoveEvent>(); - moveEvent->x = (short)LOWORD(lp); - moveEvent->y = (short)HIWORD(lp); - native->event_queue.push_back(moveEvent); - } - break; - - case WM_CLOSE: - { - auto closeEvent = std::make_shared<CloseEvent>(); - native->event_queue.push_back(closeEvent); - } - return 0; // Do not call DefWindowProc for this event. -// HWND child, old; -// old = 0; - -// numDialogs--; - -// while(old != (child = GetNextDlgGroupItem(hwnd, hwnd, false))) { -// old = child; -// EndDialog(child, 0); -// } - -// if(numDialogs) EndDialog(hwnd, 0); -// else PostQuitMessage(0); -// return 0; - case WM_MOUSEMOVE: - { - trackMouse(native->m_hwnd); - auto mouseMoveEvent = std::make_shared<MouseMoveEvent>(); - mouseMoveEvent->x = (short)LOWORD(lp); - mouseMoveEvent->y = (short)HIWORD(lp); - native->last_mouse_position = { mouseMoveEvent->x, mouseMoveEvent->y }; - - if(!native->mouse_in_window) - { - auto enterEvent = std::make_shared<MouseEnterEvent>(); - enterEvent->x = native->last_mouse_position.first; - enterEvent->y = native->last_mouse_position.second; - native->event_queue.push_back(enterEvent); - native->mouse_in_window = true; - } - native->event_queue.push_back(mouseMoveEvent); - } - break; - - case WM_MOUSEWHEEL: - { - auto scrollEvent = std::make_shared<ScrollEvent>(); - - // NOTE: lp is coordinates in screen space, not client space. - POINT p; - p.x = (short)LOWORD(lp); - p.y = (short)HIWORD(lp); - ScreenToClient(hwnd, &p); - - scrollEvent->x = p.x; - scrollEvent->y = p.y; - scrollEvent->delta = -1 * (short)HIWORD(wp) / 60.0f; - native->event_queue.push_back(scrollEvent); - } - break; - - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_RBUTTONUP: - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MBUTTONDBLCLK: - case WM_MBUTTONDOWN: - { - auto buttonEvent = std::make_shared<ButtonEvent>(); - - buttonEvent->x = (short)LOWORD(lp); - buttonEvent->y = (short)HIWORD(lp); - - if(msg == WM_LBUTTONUP || - msg == WM_LBUTTONDBLCLK || - msg == WM_LBUTTONDOWN) - { - buttonEvent->button = MouseButton::left; - } - else if(msg == WM_MBUTTONUP || - msg == WM_MBUTTONDBLCLK || - msg == WM_MBUTTONDOWN) - { - buttonEvent->button = MouseButton::middle; - } - else if(msg == WM_RBUTTONUP || - msg == WM_RBUTTONDBLCLK || - msg == WM_RBUTTONDOWN) - { - buttonEvent->button = MouseButton::right; - } - else - { - break; // unknown button - } - - // Double-clicking the a mouse button actually generates a sequence - // of four messages: WM_xBUTTONDOWN, WM_xBUTTONUP, WM_xBUTTONDBLCLK, and - // WM_xBUTTONUP. In other words the second WM_xBUTTONDOWN is replaced by a - // WM_xBUTTONDBLCLK. We simply 'return it' as a WM_xBUTTONDOWN but set the - // doubleClick boolean hint accordingly. - if(msg == WM_LBUTTONUP || - msg == WM_RBUTTONUP || - msg == WM_MBUTTONUP) - { - buttonEvent->direction = Direction::up; - } - else if(msg == WM_LBUTTONDOWN || - msg == WM_RBUTTONDOWN || - msg == WM_MBUTTONDOWN || - msg == WM_LBUTTONDBLCLK || - msg == WM_RBUTTONDBLCLK || - msg == WM_MBUTTONDBLCLK) - { - buttonEvent->direction = Direction::down; - } - - buttonEvent->doubleClick = (msg == WM_LBUTTONDBLCLK || - msg == WM_RBUTTONDBLCLK || - msg == WM_MBUTTONDBLCLK); - - native->event_queue.push_back(buttonEvent); - } - break; - - case WM_KEYDOWN: - case WM_KEYUP: - { - auto keyEvent = std::make_shared<KeyEvent>(); - - switch(wp) { - case VK_LEFT: keyEvent->keycode = Key::left; break; - case VK_RIGHT: keyEvent->keycode = Key::right; break; - case VK_UP: keyEvent->keycode = Key::up; break; - case VK_DOWN: keyEvent->keycode = Key::down; break; - case VK_BACK: keyEvent->keycode = Key::backspace; break; - case VK_DELETE: keyEvent->keycode = Key::deleteKey; break; - case VK_HOME: keyEvent->keycode = Key::home; break; - case VK_END: keyEvent->keycode = Key::end; break; - case VK_PRIOR: keyEvent->keycode = Key::pageUp; break; - case VK_NEXT: keyEvent->keycode = Key::pageDown; break; - case VK_RETURN: keyEvent->keycode = Key::enter; break; - default: keyEvent->keycode = Key::unknown; break; - } - - keyEvent->text = ""; - keyEvent->direction = - (msg == WM_KEYDOWN) ? Direction::down : Direction::up; - - native->event_queue.push_back(keyEvent); - } - break; - - case WM_CHAR: - { - if(wp >= ' ') // Filter control chars. - { - auto keyEvent = std::make_shared<KeyEvent>(); - keyEvent->keycode = Key::character; - keyEvent->text += (char)wp; - keyEvent->direction = Direction::up; - native->event_queue.push_back(keyEvent); - } - } - break; - - case WM_PAINT: - { - RECT rect; - GetUpdateRect(hwnd, &rect, FALSE); - - // Bypass partial update, which is apparrently broken. - rect.left = 0; - rect.top = 0; - rect.right = window.wpixbuf.width; - rect.bottom = window.wpixbuf.height; - - auto repaintEvent = std::make_shared<RepaintEvent>(); - repaintEvent->x = rect.left; - repaintEvent->y = rect.top; - repaintEvent->width = rect.right - rect.left; - repaintEvent->height = rect.bottom - rect.top; - native->event_queue.push_back(repaintEvent); - - // Move to window.h (in class) - HDC pDC; - HBITMAP old; - HBITMAP ourbitmap; - int* framebuf; - PixelBuffer& px = window.wpixbuf; - - { // Create bitmap - HDC hDC; - BITMAPINFO bitmapinfo; - hDC = CreateCompatibleDC(nullptr); - bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bitmapinfo.bmiHeader.biWidth = px.width; - bitmapinfo.bmiHeader.biHeight = -px.height; // top-down - bitmapinfo.bmiHeader.biPlanes = 1; - bitmapinfo.bmiHeader.biBitCount = 32; - bitmapinfo.bmiHeader.biCompression = BI_RGB; - bitmapinfo.bmiHeader.biSizeImage = 0; - bitmapinfo.bmiHeader.biClrUsed = 256; - bitmapinfo.bmiHeader.biClrImportant = 256; - ourbitmap = CreateDIBSection(hDC, &bitmapinfo, - DIB_RGB_COLORS, (void**)&framebuf, 0, 0); - pDC=CreateCompatibleDC(nullptr); - old = (HBITMAP__*)SelectObject(pDC, ourbitmap); - DeleteDC(hDC); - } - - int from_x = rect.left; - int to_x = std::min(rect.right, (long)px.width); - int from_y = rect.top; - int to_y = std::min(rect.bottom, (long)px.height); - { // Copy PixelBuffer to framebuffer - int idx = 0; - for(int y = from_y; y < to_y; ++y) - { - for(int x = from_x; x < to_x; ++x) - { - *(framebuf + idx) = RGB(px.buf[(x + y * px.width) * 3 + 2], - px.buf[(x + y * px.width) * 3 + 1], - px.buf[(x + y * px.width) * 3 + 0]); - ++idx; - } - } - } - - PAINTSTRUCT ps; - HDC hdc = BeginPaint(native->m_hwnd, &ps); - BitBlt(hdc, from_x, from_y, to_x, to_y, pDC, from_x, from_y, SRCCOPY); - EndPaint(native->m_hwnd, &ps); - - { // Destroy bitmap (move to window.cc) - SelectObject(pDC,old); - DeleteDC(pDC); - DeleteObject(ourbitmap); - } - } - break; - - case WM_MOUSELEAVE: - { - auto leaveEvent = std::make_shared<MouseLeaveEvent>(); - leaveEvent->x = native->last_mouse_position.first; - leaveEvent->y = native->last_mouse_position.second; - native->event_queue.push_back(leaveEvent); - native->mouse_in_window = false; - } - break; - } - - return DefWindowProc(hwnd, msg, wp, lp); -} - -LRESULT CALLBACK NativeWindowWin32::subClassProc(HWND hwnd, UINT msg, - WPARAM wp, LPARAM lp, - UINT_PTR id, DWORD_PTR data) -{ - NativeWindowWin32* native = (NativeWindowWin32*)data; - - // NOTE: 'native' is nullptr intil the WM_CREATE message has been handled. - if(!native) - { - return DefWindowProc(hwnd, msg, wp, lp); - } - - switch(msg) - { - case WM_SIZE: - if(wp > 4) - { - // Bogus value - ignore - break; - } - { - // Parent window size changed, replicate this size in inner window. - int width = LOWORD(lp); - int height = HIWORD(lp); - SetWindowPos(native->m_hwnd, nullptr, -1, -1, width, height, SWP_NOMOVE); - } - break; - } - - return DefSubclassProc(hwnd, msg, wp, lp); -} - -NativeWindowWin32::NativeWindowWin32(void* native_window, Window& window) - : window(window) -{ - WNDCLASSEX wcex{}; - - //Time to register a window class. - //Generic flags and everything. cbWndExtra is the size of a pointer to an - // object - we need this in the wndproc handler. - - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_DBLCLKS;//class_style; - wcex.lpfnWndProc = (WNDPROC)dialogProc; - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - // Set data: - wcex.cbWndExtra = sizeof(NativeWindowWin32*); // Size of data. - wcex.hInstance = GetModuleHandle(nullptr); - - // if(ex_style && WS_EX_TRANSPARENT == WS_EX_TRANSPARENT) { - // wcex.hbrBackground = nullptr; - // } else { - wcex.hbrBackground = nullptr;//(HBRUSH) COLOR_BACKGROUND + 1; - // } - - const char* name = "DrumGizmoClass"; - char* c_name = (char*)malloc(strlen(name) + 1); - strcpy(c_name, name); - wcex.lpszClassName = m_className = c_name; - - RegisterClassEx(&wcex); - - parent_window = (HWND)native_window; - - int width = 1, height = 1; - if(parent_window) - { - // Listen in on parent size changes. - SetWindowSubclass(parent_window, subClassProc, 42, (LONG_PTR)this); - - // Resize newly created window to fit into parent. - RECT rect; - GetClientRect(parent_window, &rect); - - auto resizeEvent = std::make_shared<ResizeEvent>(); - width = resizeEvent->width = rect.right - rect.left; - height = resizeEvent->height = rect.bottom - rect.top; - event_queue.push_back(resizeEvent); - } - - m_hwnd = CreateWindowEx(0/*ex_style*/, m_className, - "DGBasisWidget", - (native_window?WS_CHILD:WS_OVERLAPPEDWINDOW) | - (native_window?WS_VISIBLE:0), - 0, 0, - width, height, - parent_window, nullptr, - GetModuleHandle(nullptr), nullptr); - - SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); - - // Set up initial tracking of the mouse leave events - trackMouse(m_hwnd); -} - -NativeWindowWin32::~NativeWindowWin32() -{ - if(parent_window) - { - RemoveWindowSubclass(parent_window, subClassProc, 42); - } - DestroyWindow(m_hwnd); - UnregisterClass(m_className, GetModuleHandle(nullptr)); - free(m_className); -} - -void NativeWindowWin32::setFixedSize(std::size_t width, std::size_t height) -{ - resize(width, height); - LONG style = GetWindowLong(m_hwnd, GWL_STYLE); - style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); - SetWindowLong(m_hwnd, GWL_STYLE, style); -} - -void NativeWindowWin32::setAlwaysOnTop(bool always_on_top) -{ - this->always_on_top = always_on_top; - SetWindowPos(m_hwnd, always_on_top ? HWND_TOPMOST : nullptr, - 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); -} - -void NativeWindowWin32::resize(std::size_t width, std::size_t height) -{ - auto hwnd = m_hwnd; - //if(parent_window) - //{ - // hwnd = parent_window; - //} - - // Set requested size on the window (or parent) - SetWindowPos(hwnd, always_on_top ? HWND_TOPMOST : nullptr, - -1, -1, (int)width, (int)height, SWP_NOMOVE); - - // Ask the client window what size it actually got - RECT rect; - GetClientRect(m_hwnd, &rect); - int w = width - rect.right; - int h = height - rect.bottom; - - // Set the compensated size on the window (or parent) - SetWindowPos(hwnd, always_on_top ? HWND_TOPMOST : nullptr, - -1, -1, width + w, height + h, SWP_NOMOVE); -} - -std::pair<std::size_t, std::size_t> NativeWindowWin32::getSize() const -{ - RECT rect; - GetClientRect(m_hwnd, &rect); - return std::make_pair(rect.right - rect.left, rect.bottom - rect.top); -} - -void NativeWindowWin32::move(int x, int y) -{ - SetWindowPos(m_hwnd, always_on_top ? HWND_TOPMOST : nullptr, - (int)x, (int)y, -1, -1, SWP_NOSIZE); -} - -std::pair<int, int> NativeWindowWin32::getPosition() const -{ - RECT rect; - GetClientRect(m_hwnd, &rect); - return std::make_pair(rect.left, rect.top); -} - -void NativeWindowWin32::show() -{ - ShowWindow(m_hwnd, SW_SHOW); -} - -void NativeWindowWin32::hide() -{ - ShowWindow(m_hwnd, SW_HIDE); -} - -bool NativeWindowWin32::visible() const -{ - return IsWindowVisible(m_hwnd); -} - -void NativeWindowWin32::redraw(const Rect& dirty_rect) -{ - // Send WM_PAINT message. Buffer transfering is handled in MessageHandler. - if(parent_window == nullptr) - { - RECT rect = - { - (long)dirty_rect.x1, - (long)dirty_rect.y1, - (long)dirty_rect.x2, - (long)dirty_rect.y2 - }; - RedrawWindow(m_hwnd, &rect, nullptr, RDW_INVALIDATE); - UpdateWindow(m_hwnd); - } - else - { - InvalidateRect(m_hwnd, 0, TRUE); - } -} - -void NativeWindowWin32::setCaption(const std::string &caption) -{ - SetWindowText(m_hwnd, caption.c_str()); -} - -void NativeWindowWin32::grabMouse(bool grab) -{ - if(grab) - { - SetCapture(m_hwnd); - } - else - { - ReleaseCapture(); - } -} - -EventQueue NativeWindowWin32::getEvents() -{ - MSG msg; - while(PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE) != 0) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - EventQueue events; - std::swap(events, event_queue); - return events; -} - -void* NativeWindowWin32::getNativeWindowHandle() const -{ - return (void*)m_hwnd; -} - -Point NativeWindowWin32::translateToScreen(const Point& point) -{ - POINT p{ point.x, point.y }; - ClientToScreen(m_hwnd, &p); - return { p.x, p.y }; -} - -} // GUI:: |