1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-26 02:14:22 +00:00

Added display rotation support for iOS - see the Desktop class for implementation methods. Also fixed a couple of minor build issues.

This commit is contained in:
Julian Storer 2010-10-13 19:16:01 +01:00
parent c583b68cd6
commit 4bc85a9dc3
22 changed files with 776 additions and 283 deletions

View file

@ -88,6 +88,24 @@ BEGIN_JUCE_NAMESPACE
#include "common/juce_MidiDataConcatenator.h"
#undef Point
template <class RectType>
static const Rectangle<int> convertToRectInt (const RectType& r)
{
return Rectangle<int> ((int) r.origin.x, (int) r.origin.y, (int) r.size.width, (int) r.size.height);
}
template <class RectType>
static const Rectangle<float> convertToRectFloat (const RectType& r)
{
return Rectangle<float> (r.origin.x, r.origin.y, r.size.width, r.size.height);
}
template <class RectType>
static CGRect convertToCGRect (const RectType& r)
{
return CGRectMake ((CGFloat) r.getX(), (CGFloat) r.getY(), (CGFloat) r.getWidth(), (CGFloat) r.getHeight());
}
//==============================================================================
#define JUCE_INCLUDED_FILE 1

View file

@ -1098,15 +1098,15 @@ public:
const int width = image.getWidth();
const int height = image.getHeight();
HeapBlock <char> colour (width * height);
HeapBlock <uint32> colour (width * height);
int index = 0;
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
colour[index++] = static_cast<char> (image.getPixelAt (x, y).getARGB());
colour[index++] = image.getPixelAt (x, y).getARGB();
XImage* ximage = XCreateImage (display, CopyFromParent, 24, ZPixmap,
0, colour.getData(),
0, reinterpret_cast<char*> (colour.getData()),
width, height, 32, 0);
Pixmap pixmap = XCreatePixmap (display, DefaultRootWindow (display),
@ -2902,6 +2902,10 @@ void Desktop::setMousePosition (const Point<int>& newPosition)
XWarpPointer (display, None, root, 0, 0, 0, 0, newPosition.getX(), newPosition.getY());
}
Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
{
return upright;
}
//==============================================================================
static bool screenSaverAllowed = true;

View file

@ -177,22 +177,6 @@ bool Desktop::isScreenSaverEnabled()
}
//==============================================================================
void juce_updateMultiMonitorInfo (Array <Rectangle <int> >& monitorCoords, const bool clipToWorkArea)
{
const ScopedAutoReleasePool pool;
monitorCoords.clear();
CGRect r = clipToWorkArea ? [[UIScreen mainScreen] applicationFrame]
: [[UIScreen mainScreen] bounds];
monitorCoords.add (Rectangle<int> ((int) r.origin.x,
(int) r.origin.y,
(int) r.size.width,
(int) r.size.height));
}
#endif
#endif

View file

@ -61,6 +61,16 @@ END_JUCE_NAMESPACE
@end
#define JuceUIViewController MakeObjCClassName(JuceUIViewController)
@interface JuceUIViewController : UIViewController
{
}
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation;
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation;
@end
//==============================================================================
#define JuceUIWindow MakeObjCClassName(JuceUIWindow)
@ -131,6 +141,9 @@ public:
void updateHiddenTextContent (TextInputTarget* target);
void globalFocusChanged (Component*);
virtual BOOL shouldRotate (UIInterfaceOrientation interfaceOrientation);
virtual void displayRotated();
void handleTouches (UIEvent* e, bool isDown, bool isUp, bool isCancel);
//==============================================================================
@ -142,6 +155,7 @@ public:
UIWindow* window;
JuceUIView* view;
JuceUIViewController* controller;
bool isSharedWindow, fullScreen, insideDrawRect;
static ModifierKeys currentModifiers;
@ -151,12 +165,84 @@ public:
+ (int64) ([e timestamp] * 1000.0);
}
static const Rectangle<int> rotatedScreenPosToReal (const Rectangle<int>& r)
{
const Rectangle<int> screen (convertToRectInt ([[UIScreen mainScreen] bounds]));
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
}
return r;
}
static const Rectangle<int> realScreenPosToRotated (const Rectangle<int>& r)
{
const Rectangle<int> screen (convertToRectInt ([[UIScreen mainScreen] bounds]));
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
}
return r;
}
Array <UITouch*> currentTouches;
};
//==============================================================================
END_JUCE_NAMESPACE
@implementation JuceUIViewController
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation
{
JuceUIView* juceView = (JuceUIView*) [self view];
jassert (juceView != 0 && juceView->owner != 0);
return juceView->owner->shouldRotate (interfaceOrientation);
}
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation
{
JuceUIView* juceView = (JuceUIView*) [self view];
jassert (juceView != 0 && juceView->owner != 0);
juceView->owner->displayRotated();
}
@end
@implementation JuceUIView
- (JuceUIView*) initWithOwner: (UIViewComponentPeer*) owner_
@ -302,12 +388,12 @@ UIViewComponentPeer::UIViewComponentPeer (Component* const component,
UIView* viewToAttachTo)
: ComponentPeer (component, windowStyleFlags),
window (0),
view (0),
view (0), controller (0),
isSharedWindow (viewToAttachTo != 0),
fullScreen (false),
insideDrawRect (false)
{
CGRect r = CGRectMake (0, 0, (float) component->getWidth(), (float) component->getHeight());
CGRect r = convertToCGRect (component->getLocalBounds());
view = [[JuceUIView alloc] initWithOwner: this withFrame: r];
@ -320,8 +406,10 @@ UIViewComponentPeer::UIViewComponentPeer (Component* const component,
}
else
{
r.origin.x = (float) component->getX();
r.origin.y = (float) component->getY();
controller = [[JuceUIViewController alloc] init];
controller.view = view;
r = convertToCGRect (rotatedScreenPosToReal (component->getBounds()));
r.origin.y = [[UIScreen mainScreen] bounds].size.height - (r.origin.y + r.size.height);
window = [[JuceUIWindow alloc] init];
@ -358,6 +446,7 @@ UIViewComponentPeer::~UIViewComponentPeer()
view->owner = 0;
[view removeFromSuperview];
[view release];
[controller release];
if (! isSharedWindow)
{
@ -401,15 +490,9 @@ void UIViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNo
w = jmax (0, w);
h = jmax (0, h);
CGRect r;
r.origin.x = (float) x;
r.origin.y = (float) y;
r.size.width = (float) w;
r.size.height = (float) h;
if (isSharedWindow)
{
//r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height);
CGRect r = CGRectMake ((float) x, (float) y, (float) w, (float) h);
if ([view frame].size.width != r.size.width
|| [view frame].size.height != r.size.height)
@ -419,8 +502,11 @@ void UIViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNo
}
else
{
window.frame = r;
view.frame = CGRectMake (0, 0, r.size.width, r.size.height);
const Rectangle<int> bounds (rotatedScreenPosToReal (Rectangle<int> (x, y, w, h)));
window.frame = convertToCGRect (bounds);
view.frame = CGRectMake (0, 0, (float) bounds.getWidth(), (float) bounds.getHeight());
handleMovedOrResized();
}
}
@ -432,12 +518,14 @@ const Rectangle<int> UIViewComponentPeer::getBounds (const bool global) const
{
r = [view convertRect: r toView: nil];
CGRect wr = [[view window] frame];
r.origin.x += wr.origin.x;
r.origin.y += wr.origin.y;
const Rectangle<int> windowBounds (realScreenPosToRotated (convertToRectInt (wr)));
r.origin.x = windowBounds.getX();
r.origin.y = windowBounds.getY();
}
return Rectangle<int> ((int) r.origin.x, (int) r.origin.y,
(int) r.size.width, (int) r.size.height);
return convertToRectInt (r);
}
const Rectangle<int> UIViewComponentPeer::getBounds() const
@ -469,11 +557,8 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r)
r.origin.y = [[UIScreen mainScreen] bounds].size.height - r.origin.y - r.size.height;
Rectangle<int> pos ((int) r.origin.x, (int) r.origin.y,
(int) r.size.width, (int) r.size.height);
Rectangle<int> original ((int) current.origin.x, (int) current.origin.y,
(int) current.size.width, (int) current.size.height);
Rectangle<int> pos (convertToRectInt (r));
Rectangle<int> original (convertToRectInt (current));
constrainer->checkBounds (pos, original,
Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(),
@ -493,7 +578,6 @@ CGRect UIViewComponentPeer::constrainRect (CGRect r)
void UIViewComponentPeer::setMinimised (bool shouldBeMinimised)
{
// xxx
}
bool UIViewComponentPeer::isMinimised() const
@ -505,19 +589,17 @@ void UIViewComponentPeer::setFullScreen (bool shouldBeFullScreen)
{
if (! isSharedWindow)
{
Rectangle<int> r (lastNonFullscreenBounds);
Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea()
: lastNonFullscreenBounds);
setMinimised (false);
if ((! shouldBeFullScreen) && r.isEmpty())
r = getBounds();
if (fullScreen != shouldBeFullScreen)
{
if (shouldBeFullScreen)
r = Desktop::getInstance().getMainMonitorArea();
// (can't call the component's setBounds method because that'll reset our fullscreen flag)
if (! r.isEmpty())
setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen);
// (can't call the component's setBounds method because that'll reset our fullscreen flag)
if (r != getComponent()->getBounds() && ! r.isEmpty())
setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen);
}
component->repaint();
}
}
@ -526,17 +608,61 @@ bool UIViewComponentPeer::isFullScreen() const
return fullScreen;
}
static Desktop::DisplayOrientation convertToJuceOrientation (UIInterfaceOrientation interfaceOrientation)
{
switch (interfaceOrientation)
{
case UIInterfaceOrientationPortrait: return Desktop::upright;
case UIInterfaceOrientationPortraitUpsideDown: return Desktop::upsideDown;
case UIInterfaceOrientationLandscapeLeft: return Desktop::rotatedClockwise;
case UIInterfaceOrientationLandscapeRight: return Desktop::rotatedAntiClockwise;
default: jassertfalse; // unknown orientation!
}
return Desktop::upright;
}
BOOL UIViewComponentPeer::shouldRotate (UIInterfaceOrientation interfaceOrientation)
{
return Desktop::getInstance().isOrientationEnabled (convertToJuceOrientation (interfaceOrientation));
}
void UIViewComponentPeer::displayRotated()
{
const Rectangle<int> oldArea (component->getBounds());
const Rectangle<int> oldDesktop (Desktop::getInstance().getMainMonitorArea());
Desktop::getInstance().refreshMonitorSizes();
if (fullScreen)
{
fullScreen = false;
setFullScreen (true);
}
else
{
const float l = oldArea.getX() / (float) oldDesktop.getWidth();
const float r = oldArea.getRight() / (float) oldDesktop.getWidth();
const float t = oldArea.getY() / (float) oldDesktop.getHeight();
const float b = oldArea.getBottom() / (float) oldDesktop.getHeight();
const Rectangle<int> newDesktop (Desktop::getInstance().getMainMonitorArea());
setBounds ((int) (l * newDesktop.getWidth()),
(int) (t * newDesktop.getHeight()),
(int) ((r - l) * newDesktop.getWidth()),
(int) ((b - t) * newDesktop.getHeight()),
false);
}
}
bool UIViewComponentPeer::contains (const Point<int>& position, bool trueIfInAChildWindow) const
{
if (((unsigned int) position.getX()) >= (unsigned int) component->getWidth()
|| ((unsigned int) position.getY()) >= (unsigned int) component->getHeight())
return false;
CGPoint p;
p.x = (float) position.getX();
p.y = (float) position.getY();
UIView* v = [view hitTest: p withEvent: nil];
UIView* v = [view hitTest: CGPointMake ((float) position.getX(), (float) position.getY())
withEvent: nil];
if (trueIfInAChildWindow)
return v != nil;
@ -546,20 +672,7 @@ bool UIViewComponentPeer::contains (const Point<int>& position, bool trueIfInACh
const BorderSize UIViewComponentPeer::getFrameSize() const
{
BorderSize b;
if (! isSharedWindow)
{
CGRect v = [view convertRect: [view frame] toView: nil];
CGRect w = [window frame];
b.setTop ((int) (w.size.height - (v.origin.y + v.size.height)));
b.setBottom ((int) v.origin.y);
b.setLeft ((int) v.origin.x);
b.setRight ((int) (w.size.width - (v.origin.x + v.size.width)));
}
return b;
return BorderSize();
}
bool UIViewComponentPeer::setAlwaysOnTop (bool alwaysOnTop)
@ -824,8 +937,7 @@ void UIViewComponentPeer::repaint (const Rectangle<int>& area)
}
else
{
[view setNeedsDisplayInRect: CGRectMake ((float) area.getX(), (float) area.getY(),
(float) area.getWidth(), (float) area.getHeight())];
[view setNeedsDisplayInRect: convertToCGRect (area)];
}
}
@ -865,6 +977,22 @@ void Desktop::setMousePosition (const Point<int>&)
{
}
Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
{
return convertToJuceOrientation ([[UIApplication sharedApplication] statusBarOrientation]);
}
void juce_updateMultiMonitorInfo (Array <Rectangle <int> >& monitorCoords, const bool clipToWorkArea)
{
const ScopedAutoReleasePool pool;
monitorCoords.clear();
CGRect r = clipToWorkArea ? [[UIScreen mainScreen] applicationFrame]
: [[UIScreen mainScreen] bounds];
monitorCoords.add (UIViewComponentPeer::realScreenPosToRotated (convertToRectInt (r)));
}
//==============================================================================
const int KeyPress::spaceKey = ' ';
const int KeyPress::returnKey = 0x0d;

View file

@ -159,6 +159,11 @@ void Desktop::setMousePosition (const Point<int>& newPosition)
CGAssociateMouseAndMouseCursorPosition (true);
}
Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
{
return upright;
}
//==============================================================================
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
class ScreenSaverDefeater : public Timer,
@ -246,10 +251,9 @@ void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const
NSRect r = clipToWorkArea ? [s visibleFrame]
: [s frame];
monitorCoords.add (Rectangle<int> ((int) r.origin.x,
(int) (mainScreenBottom - (r.origin.y + r.size.height)),
(int) r.size.width,
(int) r.size.height));
r.origin.y = mainScreenBottom - (r.origin.y + r.size.height);
monitorCoords.add (convertToRectInt (r));
}
jassert (monitorCoords.size() > 0);

View file

@ -1034,7 +1034,7 @@ const Rectangle<int> NSViewComponentPeer::getBounds (const bool global) const
r.origin.y = [[view superview] frame].size.height - r.origin.y - r.size.height;
}
return Rectangle<int> ((int) r.origin.x, (int) r.origin.y, (int) r.size.width, (int) r.size.height);
return Rectangle<int> (convertToRectInt (r));
}
const Rectangle<int> NSViewComponentPeer::getBounds() const
@ -1066,11 +1066,8 @@ NSRect NSViewComponentPeer::constrainRect (NSRect r)
r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.origin.y - r.size.height;
Rectangle<int> pos ((int) r.origin.x, (int) r.origin.y,
(int) r.size.width, (int) r.size.height);
Rectangle<int> original ((int) current.origin.x, (int) current.origin.y,
(int) current.size.width, (int) current.size.height);
Rectangle<int> pos (convertToRectInt (r));
Rectangle<int> original (convertToRectInt (current));
constrainer->checkBounds (pos, original,
Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(),

View file

@ -81,6 +81,11 @@ bool Desktop::canUseSemiTransparentWindows() throw()
return updateLayeredWindow != 0;
}
Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
{
return upright;
}
//==============================================================================
const int extendedKeyModifier = 0x10000;