#include "common.h"
#include "FrnString.h"
class Screens : public ComSingleObject<IFrnScreens, &IID_IFrnScreens>
{
private:
ComPtr<IFrnScreenEvents> _events;
public:
FORWARD_IUNKNOWN()
Screens(IFrnScreenEvents* events) {
_events = events;
CGDisplayRegisterReconfigurationCallback(CGDisplayReconfigurationCallBack, this);
}
virtual HRESULT GetScreenIds (
unsigned int* ptrFirstResult,
int* screenCound) override
{
START_COM_CALL;
@autoreleasepool
{
auto screens = [NSScreen screens];
*screenCound = (int)screens.count;
if (ptrFirstResult == nil)
return S_OK;
for (int i = 0; i < screens.count; i++) {
ptrFirstResult[i] = [[screens objectAtIndex:i] av_displayId];
}
return S_OK;
}
}
virtual HRESULT GetScreen (
CGDirectDisplayID displayId,
void** localizedName,
FrnScreen* ret
) override {
START_COM_CALL;
@autoreleasepool
{
NSScreen* screen;
for (NSScreen *s in NSScreen.screens) {
if (s.av_displayId == displayId)
{
screen = s;
break;
}
}
if (screen == nil) {
return E_INVALIDARG;
}
ret->Bounds.Height = [screen frame].size.height;
ret->Bounds.Width = [screen frame].size.width;
ret->Bounds.X = [screen frame].origin.x;
ret->Bounds.Y = ConvertPointY(ToFrnPoint([screen frame].origin)).Y - ret->Bounds.Height;
ret->WorkingArea.Height = [screen visibleFrame].size.height;
ret->WorkingArea.Width = [screen visibleFrame].size.width;
ret->WorkingArea.X = [screen visibleFrame].origin.x;
ret->WorkingArea.Y = ConvertPointY(ToFrnPoint([screen visibleFrame].origin)).Y - ret->WorkingArea.Height;
ret->Scaling = 1;
ret->IsPrimary = CGDisplayIsMain(displayId);
auto naturalScreenSize = CGDisplayScreenSize(displayId);
auto isNaturalLandscape = naturalScreenSize.width > naturalScreenSize.height;
auto rotation = (int)CGDisplayRotation(displayId) % 360;
if (rotation < 0) rotation = 360 - rotation;
if (rotation >= 0 && rotation < 90) {
ret->Orientation = isNaturalLandscape ? FrnScreenOrientation::Landscape : FrnScreenOrientation::Portrait;
} else if (rotation >= 90 && rotation < 180) {
ret->Orientation = isNaturalLandscape ? FrnScreenOrientation::Portrait : FrnScreenOrientation::Landscape;
} else if (rotation >= 180 && rotation < 270) {
ret->Orientation = isNaturalLandscape ? FrnScreenOrientation::LandscapeFlipped : FrnScreenOrientation::PortraitFlipped;
} else {
ret->Orientation = isNaturalLandscape ? FrnScreenOrientation::PortraitFlipped : FrnScreenOrientation::LandscapeFlipped;
}
if (@available(macOS 10.15, *)) {
*localizedName = CreateFrnString([screen localizedName]);
}
return S_OK;
}
}
private:
static void CGDisplayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *screens)
{
auto object = (Screens *)screens;
auto events = object->_events;
if (events != nil) {
events->OnChanged();
}
}
};
extern IFrnScreens* CreateScreens(IFrnScreenEvents* events)
{
return new Screens(events);
}