Instantly share code, notes, and snippets.

Embed
What would you like to do?
//
// WindowLimits.cxx
// BasicApp
//
// Created by Andrew Wright on 10/11/18.
//
#include "WindowLimits.h"
#include <unordered_map>
#ifdef CINDER_COCOA
#import <Cocoa/Cocoa.h>
#else
#include <Windows.h>
#endif
using namespace ci;
ivec2 WindowLimits::kUnbounded = ivec2(-1);
WindowLimits::Format& WindowLimits::Format::minSize(const ivec2& size)
{
_minSize = size;
return *this;
}
WindowLimits::Format& WindowLimits::Format::maxSize(const ivec2& size)
{
_maxSize = size;
return *this;
}
namespace
{
#ifdef CINDER_MSW
struct Cookie
{
WindowLimits * wl;
WNDPROC parentWndProc;
};
static std::unordered_map<HWND, Cookie> kHwndToCookie;
LRESULT APIENTRY HandleWndProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if ( kHwndToCookie.count(hwnd) )
{
auto& ck = kHwndToCookie[hwnd];
switch ( uMsg )
{
case WM_GETMINMAXINFO:
{
LPMINMAXINFO limits = (LPMINMAXINFO)lParam;
auto& min = ck.wl->getFormat().minSize();
auto& max = ck.wl->getFormat().maxSize();
if ( min != WindowLimits::kUnbounded )
{
limits->ptMinTrackSize.x = min.x;
limits->ptMinTrackSize.y = min.y;
}
if ( max != WindowLimits::kUnbounded )
{
limits->ptMaxTrackSize.x = max.x;
limits->ptMaxTrackSize.y = max.y;
}
break;
}
}
return CallWindowProc ( ck.parentWndProc, hwnd, uMsg, wParam, lParam );
}
// This mightn't be the right thing to do here. Possibly call DefWndProc?
return (LRESULT)0;
}
#endif
}
WindowLimits::WindowLimits ( const app::WindowRef& window, const Format& fmt )
: _window(window)
, _fmt(fmt)
{
#ifdef CINDER_MSW
_hwnd = static_cast<HWND> (window->getNative());
Cookie ck;
ck.wl = this;
ck.parentWndProc = (WNDPROC)(SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)(HandleWndProc)));
kHwndToCookie[_hwnd] = ck;
#else
NSView * view = (NSView *)window->getNative();
if ( _fmt.minSize() != WindowLimits::kUnbounded ) [view.window setMinSize : NSMakeSize(_fmt.minSize().x, _fmt.minSize().y)];
if ( _fmt.maxSize() != WindowLimits::kUnbounded ) [view.window setMaxSize : NSMakeSize(_fmt.maxSize().x, _fmt.maxSize().y)];
#endif
if ( _fmt.minSize() != kUnbounded && glm::any ( glm::lessThan ( _window->getSize(), _fmt.minSize() ) ) )
{
_window->setSize ( _fmt.minSize() );
}
if ( _fmt.maxSize() != kUnbounded && glm::any ( glm::greaterThan ( _window->getSize(), _fmt.minSize()) ) )
{
_window->setSize(_fmt.maxSize());
}
}
WindowLimits::~WindowLimits()
{
#ifdef CINDER_MSW
auto& cookie = kHwndToCookie[_hwnd];
SetWindowLongPtr(_hwnd, GWLP_WNDPROC, (LONG_PTR)cookie.parentWndProc);
kHwndToCookie.erase(_hwnd);
#endif
}
//
// WindowLimits.h
// BasicApp
//
// Created by Andrew Wright on 10/11/18.
//
#ifndef WindowLimits_h
#define WindowLimits_h
#include "cinder/app/App.h"
class WindowLimits : public ci::Noncopyable
{
public:
static ci::ivec2 kUnbounded;
struct Format
{
public:
Format& minSize(const ci::ivec2& size);
const ci::ivec2& minSize() const { return _minSize; }
Format& maxSize(const ci::ivec2& size);
const ci::ivec2& maxSize() const { return _maxSize; }
Format() { };
protected:
ci::ivec2 _minSize{ kUnbounded };
ci::ivec2 _maxSize{ kUnbounded };
};
WindowLimits ( const ci::app::WindowRef& window, const Format& fmt = Format() );
~WindowLimits ( );
inline const Format& getFormat ( ) const { return _fmt; };
inline Format& getFormat ( ) { return _fmt; };
protected:
Format _fmt;
ci::app::WindowRef _window;
#ifdef CINDER_MSW
HWND _hwnd{nullptr};
#endif
};
#endif /* WindowLimits_h */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment