- Library code update

- project update (added Eigen)

git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@94 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2014-12-20 20:59:48 +00:00
parent 1b4d8e9f54
commit dc5560392f
312 changed files with 6349 additions and 4195 deletions
@@ -43,7 +43,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* en
JUCEApplicationBase* app = JUCEApplicationBase::createInstance();
if (! app->initialiseApp())
exit (0);
exit (app->getApplicationReturnValue());
jassert (MessageManager::getInstance()->isThisTheMessageThread());
}
@@ -91,7 +91,7 @@ DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas");
METHOD (hasFocus, "hasFocus", "()Z") \
METHOD (invalidate, "invalidate", "(IIII)V") \
METHOD (containsPoint, "containsPoint", "(II)Z") \
METHOD (showKeyboard, "showKeyboard", "(Z)V") \
METHOD (showKeyboard, "showKeyboard", "(Ljava/lang/String;)V") \
METHOD (createGLView, "createGLView", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;") \
DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView");
@@ -234,14 +234,14 @@ public:
view.callIntMethod (ComponentPeerView.getTop));
}
Point<int> localToGlobal (Point<int> relativePosition) override
Point<float> localToGlobal (Point<float> relativePosition) override
{
return relativePosition + getScreenPosition();
return relativePosition + getScreenPosition().toFloat();
}
Point<int> globalToLocal (Point<int> screenPosition) override
Point<float> globalToLocal (Point<float> screenPosition) override
{
return screenPosition - getScreenPosition();
return screenPosition - getScreenPosition().toFloat();
}
void setMinimised (bool shouldBeMinimised) override
@@ -320,7 +320,7 @@ public:
lastMousePos = pos;
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before.
handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time);
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time);
if (isValidPeer (this))
handleMouseDragCallback (index, pos, time);
@@ -333,8 +333,8 @@ public:
jassert (index < 64);
touchesDown = (touchesDown | (1 << (index & 63)));
currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier);
handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons()
.withFlags (ModifierKeys::leftButtonModifier), time);
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons()
.withFlags (ModifierKeys::leftButtonModifier), time);
}
void handleMouseUpCallback (int index, Point<float> pos, int64 time)
@@ -347,7 +347,7 @@ public:
if (touchesDown == 0)
currentModifiers = currentModifiers.withoutMouseButtons();
handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time);
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time);
}
void handleKeyDownCallback (int k, int kc)
@@ -378,14 +378,30 @@ public:
handleFocusLoss();
}
void textInputRequired (const Point<int>&) override
static const char* getVirtualKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept
{
view.callVoidMethod (ComponentPeerView.showKeyboard, true);
switch (type)
{
case TextInputTarget::textKeyboard: return "text";
case TextInputTarget::numericKeyboard: return "number";
case TextInputTarget::urlKeyboard: return "textUri";
case TextInputTarget::emailAddressKeyboard: return "textEmailAddress";
case TextInputTarget::phoneNumberKeyboard: return "phone";
default: jassertfalse; break;
}
return "text";
}
void textInputRequired (Point<int>, TextInputTarget& target) override
{
view.callVoidMethod (ComponentPeerView.showKeyboard,
javaString (getVirtualKeyboardType (target.getKeyboardType())).get());
}
void dismissPendingTextInput() override
{
view.callVoidMethod (ComponentPeerView.showKeyboard, false);
view.callVoidMethod (ComponentPeerView.showKeyboard, javaString ("").get());
}
//==============================================================================
@@ -595,12 +611,12 @@ bool MouseInputSource::SourceList::addSource()
return true;
}
Point<int> MouseInputSource::getCurrentRawMousePosition()
Point<float> MouseInputSource::getCurrentRawMousePosition()
{
return AndroidComponentPeer::lastMousePos.toInt();
return AndroidComponentPeer::lastMousePos;
}
void MouseInputSource::setRawMousePosition (Point<int>)
void MouseInputSource::setRawMousePosition (Point<float>)
{
// not needed
}
@@ -24,6 +24,14 @@
class UIViewComponentPeer;
// The way rotation works changed in iOS8..
static bool isUsingOldRotationMethod() noexcept
{
static bool isPreV8 = ([[[UIDevice currentDevice] systemVersion] compare: @"8.0"
options: NSNumericSearch] == NSOrderedAscending);
return isPreV8;
}
namespace Orientations
{
static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation)
@@ -42,12 +50,15 @@ namespace Orientations
static CGAffineTransform getCGTransformFor (const Desktop::DisplayOrientation orientation) noexcept
{
switch (orientation)
if (isUsingOldRotationMethod())
{
case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0);
case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0);
case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0);
default: break;
switch (orientation)
{
case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0);
case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0);
case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0);
default: break;
}
}
return CGAffineTransformIdentity;
@@ -85,10 +96,10 @@ using namespace juce;
- (void) drawRect: (CGRect) r;
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event;
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
@@ -106,6 +117,7 @@ using namespace juce;
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation;
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration;
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation;
- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator;
- (void) viewDidLoad;
- (void) viewWillAppear: (BOOL) animated;
@@ -145,8 +157,8 @@ public:
Rectangle<int> getBounds() const override { return getBounds (! isSharedWindow); }
Rectangle<int> getBounds (bool global) const;
Point<int> localToGlobal (Point<int> relativePosition) override;
Point<int> globalToLocal (Point<int> screenPosition) override;
Point<float> localToGlobal (Point<float> relativePosition) override;
Point<float> globalToLocal (Point<float> screenPosition) override;
void setAlpha (float newAlpha) override;
void setMinimised (bool) override {}
bool isMinimised() const override { return false; }
@@ -168,7 +180,7 @@ public:
void viewFocusLoss();
bool isFocused() const override;
void grabFocus() override;
void textInputRequired (const Point<int>&) override;
void textInputRequired (Point<int>, TextInputTarget&) override;
BOOL textViewReplaceCharacters (Range<int>, const String&);
void updateHiddenTextContent (TextInputTarget*);
@@ -189,7 +201,7 @@ public:
bool isSharedWindow, fullScreen, insideDrawRect;
static ModifierKeys currentModifiers;
static int64 getMouseTime (UIEvent* e)
static int64 getMouseTime (UIEvent* e) noexcept
{
return (Time::currentTimeMillis() - Time::getMillisecondCounter())
+ (int64) ([e timestamp] * 1000.0);
@@ -197,26 +209,29 @@ public:
static Rectangle<int> rotatedScreenPosToReal (const Rectangle<int>& r)
{
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
switch ([[UIApplication sharedApplication] statusBarOrientation])
if (isUsingOldRotationMethod())
{
case UIInterfaceOrientationPortrait:
return r;
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
}
}
return r;
@@ -224,26 +239,29 @@ public:
static Rectangle<int> realScreenPosToRotated (const Rectangle<int>& r)
{
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
switch ([[UIApplication sharedApplication] statusBarOrientation])
if (isUsingOldRotationMethod())
{
case UIInterfaceOrientationPortrait:
return r;
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
}
}
return r;
@@ -273,6 +291,13 @@ private:
};
};
static void sendScreenBoundsUpdate (JuceUIViewController* c)
{
JuceUIView* juceView = (JuceUIView*) [c view];
jassert (juceView != nil && juceView->owner != nullptr);
juceView->owner->updateTransformAndScreenBounds();
}
} // (juce namespace)
//==============================================================================
@@ -301,19 +326,23 @@ private:
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation
{
(void) fromInterfaceOrientation;
JuceUIView* juceView = (JuceUIView*) [self view];
jassert (juceView != nil && juceView->owner != nullptr);
juceView->owner->updateTransformAndScreenBounds();
sendScreenBoundsUpdate (self);
[UIView setAnimationsEnabled: YES];
}
- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator
{
[super viewWillTransitionToSize: size withTransitionCoordinator: coordinator];
sendScreenBoundsUpdate (self);
// On some devices the screen-size isn't yet updated at this point, so also trigger another
// async update to double-check..
MessageManager::callAsync ([=]() { sendScreenBoundsUpdate (self); });
}
- (void) viewDidLoad
{
JuceUIView* juceView = (JuceUIView*) [self view];
jassert (juceView != nil && juceView->owner != nullptr);
juceView->owner->updateTransformAndScreenBounds();
sendScreenBoundsUpdate (self);
}
- (void) viewWillAppear: (BOOL) animated
@@ -477,7 +506,7 @@ void ModifierKeys::updateCurrentModifiers() noexcept
currentModifiers = UIViewComponentPeer::currentModifiers;
}
Point<int> juce_lastMousePos;
Point<float> juce_lastMousePos;
//==============================================================================
UIViewComponentPeer::UIViewComponentPeer (Component& comp, const int windowStyleFlags, UIView* viewToAttachTo)
@@ -603,14 +632,14 @@ Rectangle<int> UIViewComponentPeer::getBounds (const bool global) const
return convertToRectInt (r);
}
Point<int> UIViewComponentPeer::localToGlobal (Point<int> relativePosition)
Point<float> UIViewComponentPeer::localToGlobal (Point<float> relativePosition)
{
return relativePosition + getBounds (true).getPosition();
return relativePosition + getBounds (true).getPosition().toFloat();
}
Point<int> UIViewComponentPeer::globalToLocal (Point<int> screenPosition)
Point<float> UIViewComponentPeer::globalToLocal (Point<float> screenPosition)
{
return screenPosition - getBounds (true).getPosition();
return screenPosition - getBounds (true).getPosition().toFloat();
}
void UIViewComponentPeer::setAlpha (float newAlpha)
@@ -702,10 +731,7 @@ void UIViewComponentPeer::toFront (bool makeActiveWindow)
void UIViewComponentPeer::toBehind (ComponentPeer* other)
{
UIViewComponentPeer* const otherPeer = dynamic_cast <UIViewComponentPeer*> (other);
jassert (otherPeer != nullptr); // wrong type of window?
if (otherPeer != nullptr)
if (UIViewComponentPeer* const otherPeer = dynamic_cast<UIViewComponentPeer*> (other))
{
if (isSharedWindow)
{
@@ -716,6 +742,10 @@ void UIViewComponentPeer::toBehind (ComponentPeer* other)
// don't know how to do this
}
}
else
{
jassertfalse; // wrong type of window?
}
}
void UIViewComponentPeer::setIcon (const Image& /*newIcon*/)
@@ -736,8 +766,8 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons
continue;
CGPoint p = [touch locationInView: view];
const Point<int> pos ((int) p.x, (int) p.y);
juce_lastMousePos = pos + getBounds (true).getPosition();
const Point<float> pos (p.x, p.y);
juce_lastMousePos = pos + getBounds (true).getPosition().toFloat();
const int64 time = getMouseTime (event);
const int touchIndex = currentTouches.getIndexOfTouch (touch);
@@ -781,7 +811,7 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons
if (isUp || isCancel)
{
handleMouseEvent (touchIndex, Point<int> (-1, -1), modsToSend, time);
handleMouseEvent (touchIndex, Point<float> (-1.0f, -1.0f), modsToSend, time);
if (! isValidPeer (this))
return;
}
@@ -828,12 +858,28 @@ void UIViewComponentPeer::grabFocus()
}
}
void UIViewComponentPeer::textInputRequired (const Point<int>&)
void UIViewComponentPeer::textInputRequired (Point<int>, TextInputTarget&)
{
}
static UIKeyboardType getUIKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept
{
switch (type)
{
case TextInputTarget::textKeyboard: return UIKeyboardTypeAlphabet;
case TextInputTarget::numericKeyboard: return UIKeyboardTypeNumbersAndPunctuation;
case TextInputTarget::urlKeyboard: return UIKeyboardTypeURL;
case TextInputTarget::emailAddressKeyboard: return UIKeyboardTypeEmailAddress;
case TextInputTarget::phoneNumberKeyboard: return UIKeyboardTypePhonePad;
default: jassertfalse; break;
}
return UIKeyboardTypeDefault;
}
void UIViewComponentPeer::updateHiddenTextContent (TextInputTarget* target)
{
view->hiddenTextView.keyboardType = getUIKeyboardType (target->getKeyboardType());
view->hiddenTextView.text = juceStringToNS (target->getTextInRange (Range<int> (0, target->getHighlightedRegion().getStart())));
view->hiddenTextView.selectedRange = NSMakeRange (target->getHighlightedRegion().getStart(), 0);
}
@@ -189,7 +189,7 @@ private:
- (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex
{
owner->buttonClicked (buttonIndex);
owner->buttonClicked ((int) buttonIndex);
alertView.hidden = true;
}
@@ -312,12 +312,12 @@ bool Desktop::canUseSemiTransparentWindows() noexcept
return true;
}
Point<int> MouseInputSource::getCurrentRawMousePosition()
Point<float> MouseInputSource::getCurrentRawMousePosition()
{
return juce_lastMousePos;
}
void MouseInputSource::setRawMousePosition (Point<int>)
void MouseInputSource::setRawMousePosition (Point<float>)
{
}
@@ -42,99 +42,134 @@ bool FileChooser::isPlatformDialogAvailable()
#endif
}
void FileChooser::showPlatformDialog (Array<File>& results,
const String& title,
const File& file,
const String& filters,
bool isDirectory,
bool /* selectsFiles */,
bool isSave,
bool /* warnAboutOverwritingExistingFiles */,
bool selectMultipleFiles,
FilePreviewComponent* /* previewComponent */)
static uint64 getTopWindowID() noexcept
{
String separator;
StringArray args;
if (TopLevelWindow* top = TopLevelWindow::getActiveTopLevelWindow())
return (uint64) (pointer_sized_uint) top->getWindowHandle();
const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
const bool isKdeFullSession = SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String::empty)
.equalsIgnoreCase ("true");
return 0;
}
if (exeIsAvailable ("kdialog") && (isKdeFullSession || ! exeIsAvailable ("zenity")))
static bool isKdeFullSession()
{
return SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String())
.equalsIgnoreCase ("true");
}
static void addKDialogArgs (StringArray& args, String& separator,
const String& title, const File& file, const String& filters,
bool isDirectory, bool isSave, bool selectMultipleFiles)
{
args.add ("kdialog");
if (title.isNotEmpty())
args.add ("--title=" + title);
if (uint64 topWindowID = getTopWindowID())
{
// use kdialog for KDE sessions or if zenity is missing
args.add ("kdialog");
args.add ("--attach");
args.add (String (topWindowID));
}
if (title.isNotEmpty())
args.add ("--title=" + title);
if (selectMultipleFiles)
{
separator = "\n";
args.add ("--multiple");
args.add ("--separate-output");
args.add ("--getopenfilename");
}
else
{
if (isSave) args.add ("--getsavefilename");
else if (isDirectory) args.add ("--getexistingdirectory");
else args.add ("--getopenfilename");
}
String startPath;
if (file.exists())
{
startPath = file.getFullPathName();
}
else if (file.getParentDirectory().exists())
{
startPath = file.getParentDirectory().getFullPathName();
}
else
{
startPath = File::getSpecialLocation (File::userHomeDirectory).getFullPathName();
if (isSave)
startPath += "/" + file.getFileName();
}
args.add (startPath);
args.add (filters.replaceCharacter (';', ' '));
if (selectMultipleFiles)
{
separator = "\n";
args.add ("--multiple");
args.add ("--separate-output");
args.add ("--getopenfilename");
}
else
{
// zenity
args.add ("zenity");
args.add ("--file-selection");
if (title.isNotEmpty())
args.add ("--title=" + title);
if (selectMultipleFiles)
{
separator = ":";
args.add ("--multiple");
args.add ("--separator=" + separator);
}
else
{
if (isDirectory) args.add ("--directory");
if (isSave) args.add ("--save");
}
if (file.isDirectory())
file.setAsCurrentWorkingDirectory();
else if (file.getParentDirectory().exists())
file.getParentDirectory().setAsCurrentWorkingDirectory();
else
File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory();
if (! file.getFileName().isEmpty())
args.add ("--filename=" + file.getFileName());
if (isSave) args.add ("--getsavefilename");
else if (isDirectory) args.add ("--getexistingdirectory");
else args.add ("--getopenfilename");
}
File startPath;
if (file.exists())
{
startPath = file;
}
else if (file.getParentDirectory().exists())
{
startPath = file.getParentDirectory();
}
else
{
startPath = File::getSpecialLocation (File::userHomeDirectory);
if (isSave)
startPath = startPath.getChildFile (file.getFileName());
}
args.add (startPath.getFullPathName());
args.add (filters.replaceCharacter (';', ' '));
}
static void addZenityArgs (StringArray& args, String& separator,
const String& title, const File& file, const String& filters,
bool isDirectory, bool isSave, bool selectMultipleFiles)
{
args.add ("zenity");
args.add ("--file-selection");
if (title.isNotEmpty())
args.add ("--title=" + title);
if (selectMultipleFiles)
{
separator = ":";
args.add ("--multiple");
args.add ("--separator=" + separator);
}
else
{
if (isDirectory) args.add ("--directory");
if (isSave) args.add ("--save");
}
if (filters.isNotEmpty() && filters != "*" && filters != "*.*")
{
args.add ("--file-filter");
args.add (filters.replaceCharacter (';', ' '));
args.add ("--file-filter");
args.add ("All files | *");
}
if (file.isDirectory())
file.setAsCurrentWorkingDirectory();
else if (file.getParentDirectory().exists())
file.getParentDirectory().setAsCurrentWorkingDirectory();
else
File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory();
if (! file.getFileName().isEmpty())
args.add ("--filename=" + file.getFileName());
// supplying the window ID of the topmost window makes sure that Zenity pops up..
if (uint64 topWindowID = getTopWindowID())
setenv ("WINDOWID", String (topWindowID).toRawUTF8(), true);
}
void FileChooser::showPlatformDialog (Array<File>& results,
const String& title, const File& file, const String& filters,
bool isDirectory, bool /* selectsFiles */,
bool isSave, bool /* warnAboutOverwritingExistingFiles */,
bool selectMultipleFiles, FilePreviewComponent*)
{
const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
StringArray args;
String separator;
// use kdialog for KDE sessions or if zenity is missing
if (exeIsAvailable ("kdialog") && (isKdeFullSession() || ! exeIsAvailable ("zenity")))
addKDialogArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles);
else
addZenityArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles);
args.add ("2>/dev/null"); // (to avoid logging info ending up in the results)
ChildProcess child;
@@ -33,17 +33,18 @@ struct Atoms
{
Atoms()
{
Protocols = getIfExists ("WM_PROTOCOLS");
ProtocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS");
ProtocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW");
ProtocolList [PING] = getIfExists ("_NET_WM_PING");
ChangeState = getIfExists ("WM_CHANGE_STATE");
State = getIfExists ("WM_STATE");
UserTime = getCreating ("_NET_WM_USER_TIME");
ActiveWin = getCreating ("_NET_ACTIVE_WINDOW");
Pid = getCreating ("_NET_WM_PID");
WindowType = getIfExists ("_NET_WM_WINDOW_TYPE");
WindowState = getIfExists ("_NET_WM_STATE");
protocols = getIfExists ("WM_PROTOCOLS");
protocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS");
protocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW");
protocolList [PING] = getIfExists ("_NET_WM_PING");
changeState = getIfExists ("WM_CHANGE_STATE");
state = getIfExists ("WM_STATE");
userTime = getCreating ("_NET_WM_USER_TIME");
activeWin = getCreating ("_NET_ACTIVE_WINDOW");
pid = getCreating ("_NET_WM_PID");
windowType = getIfExists ("_NET_WM_WINDOW_TYPE");
windowState = getIfExists ("_NET_WM_STATE");
compositingManager = getCreating ("_NET_WM_CM_S0");
XdndAware = getCreating ("XdndAware");
XdndEnter = getCreating ("XdndEnter");
@@ -88,8 +89,8 @@ struct Atoms
PING = 2
};
Atom Protocols, ProtocolList[3], ChangeState, State, UserTime,
ActiveWin, Pid, WindowType, WindowState,
Atom protocols, protocolList[3], changeState, state, userTime,
activeWin, pid, windowType, windowState, compositingManager,
XdndAware, XdndEnter, XdndLeave, XdndPosition, XdndStatus,
XdndDrop, XdndFinished, XdndSelection, XdndTypeList, XdndActionList,
XdndActionDescription, XdndActionCopy, XdndActionPrivate,
@@ -314,6 +315,11 @@ namespace XRender
return xRenderQueryVersion != nullptr;
}
static bool hasCompositingWindowManager()
{
return XGetSelectionOwner (display, Atoms::get().compositingManager) != 0;
}
static XRenderPictFormat* findPictureFormat()
{
ScopedXLock xlock;
@@ -915,7 +921,7 @@ public:
clientMsg.window = windowH;
clientMsg.type = ClientMessage;
clientMsg.format = 32;
clientMsg.message_type = Atoms::get().WindowState;
clientMsg.message_type = Atoms::get().windowState;
clientMsg.data.l[0] = 0; // Remove
clientMsg.data.l[1] = fs;
clientMsg.data.l[2] = 0;
@@ -971,14 +977,14 @@ public:
Rectangle<int> getBounds() const override { return bounds; }
Point<int> localToGlobal (Point<int> relativePosition) override
Point<float> localToGlobal (Point<float> relativePosition) override
{
return relativePosition + bounds.getPosition();
return relativePosition + bounds.getPosition().toFloat();
}
Point<int> globalToLocal (Point<int> screenPosition) override
Point<float> globalToLocal (Point<float> screenPosition) override
{
return screenPosition - bounds.getPosition();
return screenPosition - bounds.getPosition().toFloat();
}
void setAlpha (float /* newAlpha */) override
@@ -1002,7 +1008,7 @@ public:
clientMsg.window = windowH;
clientMsg.type = ClientMessage;
clientMsg.format = 32;
clientMsg.message_type = Atoms::get().ChangeState;
clientMsg.message_type = Atoms::get().changeState;
clientMsg.data.l[0] = IconicState;
ScopedXLock xlock;
@@ -1018,10 +1024,10 @@ public:
{
ScopedXLock xlock;
const Atoms& atoms = Atoms::get();
GetXProperty prop (windowH, atoms.State, 0, 64, false, atoms.State);
GetXProperty prop (windowH, atoms.state, 0, 64, false, atoms.state);
return prop.success
&& prop.actualType == atoms.State
&& prop.actualType == atoms.state
&& prop.actualFormat == 32
&& prop.numItems > 0
&& ((unsigned long*) prop.data)[0] == IconicState;
@@ -1039,7 +1045,7 @@ public:
r = Desktop::getInstance().getDisplays().getMainDisplay().userArea;
if (! r.isEmpty())
setBounds (r, shouldBeFullScreen);
setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, r), shouldBeFullScreen);
component.repaint();
}
@@ -1081,9 +1087,7 @@ public:
{
for (int i = windowListSize; --i >= 0;)
{
LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]);
if (peer != 0)
if (LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]))
{
result = (peer == this);
break;
@@ -1109,9 +1113,9 @@ public:
if (c == &component)
break;
// TODO: needs scaling correctly
if (c->contains (localPos + bounds.getPosition() - c->getScreenPosition()))
return false;
if (ComponentPeer* peer = c->getPeer())
if (peer->contains (localPos + bounds.getPosition() - peer->getBounds().getPosition(), true))
return false;
}
if (trueIfInAChildWindow)
@@ -1152,7 +1156,7 @@ public:
ev.xclient.type = ClientMessage;
ev.xclient.serial = 0;
ev.xclient.send_event = True;
ev.xclient.message_type = Atoms::get().ActiveWin;
ev.xclient.message_type = Atoms::get().activeWin;
ev.xclient.window = windowH;
ev.xclient.format = 32;
ev.xclient.data.l[0] = 2;
@@ -1178,10 +1182,7 @@ public:
void toBehind (ComponentPeer* other) override
{
LinuxComponentPeer* const otherPeer = dynamic_cast <LinuxComponentPeer*> (other);
jassert (otherPeer != nullptr); // wrong type of window?
if (otherPeer != nullptr)
if (LinuxComponentPeer* const otherPeer = dynamic_cast<LinuxComponentPeer*> (other))
{
setMinimised (false);
@@ -1190,6 +1191,8 @@ public:
ScopedXLock xlock;
XRestackWindows (display, newStack, 2);
}
else
jassertfalse; // wrong type of window?
}
bool isFocused() const override
@@ -1217,11 +1220,11 @@ public:
}
}
void textInputRequired (const Point<int>&) override {}
void textInputRequired (Point<int>, TextInputTarget&) override {}
void repaint (const Rectangle<int>& area) override
{
repainter->repaint (area.getIntersection (component.getLocalBounds()));
repainter->repaint (area.getIntersection (bounds.withZeroOrigin()));
}
void performAnyPendingRepaintsNow() override
@@ -1327,6 +1330,7 @@ public:
default:
#if JUCE_USE_XSHM
if (XSHMHelpers::isShmAvailable())
{
ScopedXLock xlock;
if (event.xany.type == XShmGetEventBase (display))
@@ -1368,7 +1372,7 @@ public:
const ModifierKeys oldMods (currentModifiers);
bool keyPressed = false;
if ((sym & 0xff00) == 0xff00 || sym == XK_ISO_Left_Tab)
if ((sym & 0xff00) == 0xff00 || keyCode == XK_ISO_Left_Tab)
{
switch (sym) // Translate keypad
{
@@ -1427,6 +1431,11 @@ public:
keyCode &= 0xff;
break;
case XK_ISO_Left_Tab:
keyPressed = true;
keyCode = XK_Tab & 0xff;
break;
default:
if (sym >= XK_F1 && sym <= XK_F16)
{
@@ -1490,9 +1499,9 @@ public:
}
template <typename EventType>
static Point<int> getMousePos (const EventType& e) noexcept
static Point<float> getMousePos (const EventType& e) noexcept
{
return Point<int> (e.x, e.y);
return Point<float> ((float) e.x, (float) e.y);
}
void handleWheelEvent (const XButtonPressedEvent& buttonPressEvent, const float amount)
@@ -1698,11 +1707,11 @@ public:
{
const Atoms& atoms = Atoms::get();
if (clientMsg.message_type == atoms.Protocols && clientMsg.format == 32)
if (clientMsg.message_type == atoms.protocols && clientMsg.format == 32)
{
const Atom atom = (Atom) clientMsg.data.l[0];
if (atom == atoms.ProtocolList [Atoms::PING])
if (atom == atoms.protocolList [Atoms::PING])
{
Window root = RootWindow (display, DefaultScreen (display));
@@ -1711,7 +1720,7 @@ public:
XSendEvent (display, root, False, NoEventMask, &event);
XFlush (display);
}
else if (atom == atoms.ProtocolList [Atoms::TAKE_FOCUS])
else if (atom == atoms.protocolList [Atoms::TAKE_FOCUS])
{
if ((getStyleFlags() & juce::ComponentPeer::windowIgnoresKeyPresses) == 0)
{
@@ -1726,7 +1735,7 @@ public:
}
}
}
else if (atom == atoms.ProtocolList [Atoms::DELETE_WINDOW])
else if (atom == atoms.protocolList [Atoms::DELETE_WINDOW])
{
handleUserClosingWindow();
}
@@ -1902,7 +1911,8 @@ private:
for (const Rectangle<int>* i = originalRepaintRegion.begin(), * const e = originalRepaintRegion.end(); i != e; ++i)
{
#if JUCE_USE_XSHM
++shmPaintsPending;
if (XSHMHelpers::isShmAvailable())
++shmPaintsPending;
#endif
static_cast<XBitmapImage*> (image.getPixelData())
@@ -2166,7 +2176,7 @@ private:
netHints[1] = Atoms::getIfExists ("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
xchangeProperty (windowH, Atoms::get().WindowType, XA_ATOM, 32, &netHints, 2);
xchangeProperty (windowH, Atoms::get().windowType, XA_ATOM, 32, &netHints, 2);
int numHints = 0;
@@ -2177,7 +2187,7 @@ private:
netHints [numHints++] = Atoms::getIfExists ("_NET_WM_STATE_ABOVE");
if (numHints > 0)
xchangeProperty (windowH, Atoms::get().WindowState, XA_ATOM, 32, &netHints, numHints);
xchangeProperty (windowH, Atoms::get().windowState, XA_ATOM, 32, &netHints, numHints);
}
void createWindow (Window parentToAddTo)
@@ -2254,10 +2264,10 @@ private:
// Associate the PID, allowing to be shut down when something goes wrong
unsigned long pid = getpid();
xchangeProperty (windowH, atoms.Pid, XA_CARDINAL, 32, &pid, 1);
xchangeProperty (windowH, atoms.pid, XA_CARDINAL, 32, &pid, 1);
// Set window manager protocols
xchangeProperty (windowH, atoms.Protocols, XA_ATOM, 32, atoms.ProtocolList, 2);
xchangeProperty (windowH, atoms.protocols, XA_ATOM, 32, atoms.protocolList, 2);
// Set drag and drop flags
xchangeProperty (windowH, atoms.XdndTypeList, XA_ATOM, 32, atoms.allowedMimeTypes, numElementsInArray (atoms.allowedMimeTypes));
@@ -2314,7 +2324,7 @@ private:
long getUserTime() const
{
GetXProperty prop (windowH, Atoms::get().UserTime, 0, 65536, false, XA_CARDINAL);
GetXProperty prop (windowH, Atoms::get().userTime, 0, 65536, false, XA_CARDINAL);
return prop.success ? *(long*) prop.data : 0;
}
@@ -3042,10 +3052,10 @@ void Desktop::Displays::findDisplays (float masterScale)
d.userArea = d.totalArea = Rectangle<int> (screens[j].x_org,
screens[j].y_org,
screens[j].width,
screens[j].height) * masterScale;
screens[j].height) / masterScale;
d.isMain = (index == 0);
d.scale = masterScale;
d.dpi = getDisplayDPI (index);
d.dpi = getDisplayDPI (0); // (all screens share the same DPI)
displays.add (d);
}
@@ -3114,14 +3124,20 @@ bool MouseInputSource::SourceList::addSource()
bool Desktop::canUseSemiTransparentWindows() noexcept
{
int matchedDepth = 0;
const int desiredDepth = 32;
#if JUCE_USE_XRENDER
if (XRender::hasCompositingWindowManager())
{
int matchedDepth = 0, desiredDepth = 32;
return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0
&& (matchedDepth == desiredDepth);
return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0
&& matchedDepth == desiredDepth;
}
#endif
return false;
}
Point<int> MouseInputSource::getCurrentRawMousePosition()
Point<float> MouseInputSource::getCurrentRawMousePosition()
{
Window root, child;
int x, y, winx, winy;
@@ -3138,14 +3154,14 @@ Point<int> MouseInputSource::getCurrentRawMousePosition()
x = y = -1;
}
return Point<int> (x, y);
return Point<float> ((float) x, (float) y);
}
void MouseInputSource::setRawMousePosition (Point<int> newPosition)
void MouseInputSource::setRawMousePosition (Point<float> newPosition)
{
ScopedXLock xlock;
Window root = RootWindow (display, DefaultScreen (display));
XWarpPointer (display, None, root, 0, 0, 0, 0, newPosition.getX(), newPosition.getY());
XWarpPointer (display, None, root, 0, 0, 0, 0, roundToInt (newPosition.getX()), roundToInt (newPosition.getY()));
}
double Desktop::getDefaultMasterScale()
@@ -3364,7 +3380,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty
void MouseCursor::showInWindow (ComponentPeer* peer) const
{
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (peer))
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (peer))
lp->showMouseCursor ((Cursor) getHandle());
}
@@ -3388,7 +3404,7 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0))
if (Component* sourceComp = draggingSource->getComponentUnderMouse())
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer()))
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (sourceComp->getPeer()))
return lp->externalDragFileInit (files, canMoveFiles);
// This method must be called in response to a component's mouseDown or mouseDrag event!
@@ -3403,7 +3419,7 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0))
if (Component* sourceComp = draggingSource->getComponentUnderMouse())
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer()))
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (sourceComp->getPeer()))
return lp->externalDragTextInit (text);
// This method must be called in response to a component's mouseDown or mouseDrag event!
@@ -295,14 +295,14 @@ public:
return getBounds (! isSharedWindow);
}
Point<int> localToGlobal (Point<int> relativePosition) override
Point<float> localToGlobal (Point<float> relativePosition) override
{
return relativePosition + getBounds (true).getPosition();
return relativePosition + getBounds (true).getPosition().toFloat();
}
Point<int> globalToLocal (Point<int> screenPosition) override
Point<float> globalToLocal (Point<float> screenPosition) override
{
return screenPosition - getBounds (true).getPosition();
return screenPosition - getBounds (true).getPosition().toFloat();
}
void setAlpha (float newAlpha) override
@@ -369,7 +369,7 @@ public:
// (can't call the component's setBounds method because that'll reset our fullscreen flag)
if (r != component.getBounds() && ! r.isEmpty())
setBounds (r, shouldBeFullScreen);
setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, r), shouldBeFullScreen);
}
}
}
@@ -390,16 +390,37 @@ public:
return ComponentPeer::isKioskMode();
}
static bool isWindowAtPoint (NSWindow* w, NSPoint screenPoint)
{
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)])
return [NSWindow windowNumberAtPoint: screenPoint belowWindowWithWindowNumber: 0] == [w windowNumber];
#endif
return true;
}
bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override
{
NSRect frameRect = [view frame];
NSRect viewFrame = [view frame];
if (! (isPositiveAndBelow (localPos.getX(), (int) frameRect.size.width)
&& isPositiveAndBelow (localPos.getY(), (int) frameRect.size.height)))
if (! (isPositiveAndBelow (localPos.getX(), (int) viewFrame.size.width)
&& isPositiveAndBelow (localPos.getY(), (int) viewFrame.size.height)))
return false;
NSView* v = [view hitTest: NSMakePoint (frameRect.origin.x + localPos.getX(),
frameRect.origin.y + frameRect.size.height - localPos.getY())];
if (NSWindow* const viewWindow = [view window])
{
const NSRect windowFrame = [viewWindow frame];
const NSPoint windowPoint = [view convertPoint: NSMakePoint (localPos.x, localPos.y) toView: nil];
const NSPoint screenPoint = NSMakePoint (windowFrame.origin.x + windowPoint.x,
windowFrame.origin.y + windowFrame.size.height - windowPoint.y);
if (! isWindowAtPoint (viewWindow, screenPoint))
return false;
}
NSView* v = [view hitTest: NSMakePoint (viewFrame.origin.x + localPos.getX(),
viewFrame.origin.y + viewFrame.size.height - localPos.getY())];
return trueIfInAChildWindow ? (v != nil)
: (v == view);
@@ -553,19 +574,11 @@ public:
{
currentModifiers = currentModifiers.withoutMouseButtons();
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)]
&& [NSWindow windowNumberAtPoint: [[ev window] convertBaseToScreen: [ev locationInWindow]]
belowWindowWithWindowNumber: 0] != [window windowNumber])
{
// moved into another window which overlaps this one, so trigger an exit
handleMouseEvent (0, Point<int> (-1, -1), currentModifiers, getMouseTime (ev));
}
else
#endif
{
if (isWindowAtPoint ([ev window], [[ev window] convertBaseToScreen: [ev locationInWindow]]))
sendMouseEvent (ev);
}
else
// moved into another window which overlaps this one, so trigger an exit
handleMouseEvent (0, Point<float> (-1.0f, -1.0f), currentModifiers, getMouseTime (ev));
showArrowCursorIfNeeded();
}
@@ -936,7 +949,7 @@ public:
MouseInputSource mouse = desktop.getMainMouseSource();
if (mouse.getComponentUnderMouse() == nullptr
&& desktop.findComponentAt (mouse.getScreenPosition()) == nullptr)
&& desktop.findComponentAt (mouse.getScreenPosition().roundToInt()) == nullptr)
{
[[NSCursor arrowCursor] set];
}
@@ -1010,10 +1023,10 @@ public:
+ (int64) ([e timestamp] * 1000.0);
}
static Point<int> getMousePos (NSEvent* e, NSView* view)
static Point<float> getMousePos (NSEvent* e, NSView* view)
{
NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil];
return Point<int> ((int) p.x, (int) ([view frame].size.height - p.y));
return Point<float> ((float) p.x, (float) ([view frame].size.height - p.y));
}
static int getModifierForButtonNumber (const NSInteger num)
@@ -1136,8 +1149,9 @@ public:
bool isFocused() const override
{
return isSharedWindow ? this == currentlyFocusedPeer
: [window isKeyWindow];
return (isSharedWindow || ! JUCEApplication::isStandaloneApp())
? this == currentlyFocusedPeer
: [window isKeyWindow];
}
void grabFocus() override
@@ -1151,7 +1165,7 @@ public:
}
}
void textInputRequired (const Point<int>&) override {}
void textInputRequired (Point<int>, TextInputTarget&) override {}
//==============================================================================
void repaint (const Rectangle<int>& area) override
@@ -1221,6 +1235,8 @@ private:
const Rectangle<int> clipBounds (clipW, clipH);
const CGFloat viewH = [view frame].size.height;
clip.ensureStorageAllocated ((int) numRects);
for (int i = 0; i < numRects; ++i)
clip.addWithoutMerging (clipBounds.getIntersection (Rectangle<int> (roundToInt (rects[i].origin.x) + offset.x,
roundToInt (viewH - (rects[i].origin.y + rects[i].size.height)) + offset.y,
@@ -1687,21 +1703,22 @@ private:
};
//==============================================================================
struct JuceNSWindowClass : public ObjCClass <NSWindow>
struct JuceNSWindowClass : public ObjCClass<NSWindow>
{
JuceNSWindowClass() : ObjCClass <NSWindow> ("JUCEWindow_")
JuceNSWindowClass() : ObjCClass<NSWindow> ("JUCEWindow_")
{
addIvar<NSViewComponentPeer*> ("owner");
addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:");
addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:");
addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@");
addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect), "@");
addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize));
addMethod (@selector (zoom:), zoom, "v@:@");
addMethod (@selector (windowWillMove:), windowWillMove, "v@:@");
addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:");
addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:");
addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@");
addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect), "@");
addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize));
addMethod (@selector (windowDidExitFullScreen:), windowDidExitFullScreen, "v@:@");
addMethod (@selector (zoom:), zoom, "v@:@");
addMethod (@selector (windowWillMove:), windowWillMove, "v@:@");
addMethod (@selector (windowWillStartLiveResize:), windowWillStartLiveResize, "v@:@");
addMethod (@selector (windowDidEndLiveResize:), windowDidEndLiveResize, "v@:@");
addMethod (@selector (windowDidEndLiveResize:), windowDidEndLiveResize, "v@:@");
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
addProtocol (@protocol (NSWindowDelegate));
@@ -1767,6 +1784,11 @@ private:
return frameRect.size;
}
static void windowDidExitFullScreen (id, SEL, NSNotification*)
{
[NSApp setPresentationOptions: NSApplicationPresentationDefault];
}
static void zoom (id self, SEL, id sender)
{
if (NSViewComponentPeer* const owner = getOwner (self))
@@ -1865,7 +1887,7 @@ bool MouseInputSource::SourceList::addSource()
}
//==============================================================================
void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, bool allowMenusAndBars)
void Desktop::setKioskComponent (Component* kioskComp, bool shouldBeEnabled, bool allowMenusAndBars)
{
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
@@ -1876,13 +1898,15 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo
if (peer->hasNativeTitleBar()
&& [peer->window respondsToSelector: @selector (toggleFullScreen:)])
{
[peer->window performSelector: @selector (toggleFullScreen:)
withObject: [NSNumber numberWithBool: (BOOL) enableOrDisable]];
if (shouldBeEnabled && ! allowMenusAndBars)
[NSApp setPresentationOptions: NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar];
[peer->window performSelector: @selector (toggleFullScreen:) withObject: nil];
}
else
#endif
{
if (enableOrDisable)
if (shouldBeEnabled)
{
if (peer->hasNativeTitleBar())
[peer->window setStyleMask: NSBorderlessWindowMask];
@@ -1904,9 +1928,7 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo
}
}
#elif JUCE_SUPPORT_CARBON
(void) kioskComp; (void) enableOrDisable; (void) allowMenusAndBars;
if (enableOrDisable)
if (shouldBeEnabled)
{
SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0);
kioskComp->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea);
@@ -1916,7 +1938,7 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo
SetSystemUIMode (kUIModeNormal, 0);
}
#else
(void) kioskComp; (void) enableOrDisable; (void) allowMenusAndBars;
(void) kioskComp; (void) shouldBeEnabled; (void) allowMenusAndBars;
// If you're targeting OSes earlier than 10.6 and want to use this feature,
// you'll need to enable JUCE_SUPPORT_CARBON.
@@ -209,16 +209,16 @@ bool Desktop::canUseSemiTransparentWindows() noexcept
return true;
}
Point<int> MouseInputSource::getCurrentRawMousePosition()
Point<float> MouseInputSource::getCurrentRawMousePosition()
{
JUCE_AUTORELEASEPOOL
{
const NSPoint p ([NSEvent mouseLocation]);
return Point<int> (roundToInt (p.x), roundToInt (getMainScreenHeight() - p.y));
return Point<float> ((float) p.x, (float) (getMainScreenHeight() - p.y));
}
}
void MouseInputSource::setRawMousePosition (Point<int> newPosition)
void MouseInputSource::setRawMousePosition (Point<float> newPosition)
{
// this rubbish needs to be done around the warp call, to avoid causing a
// bizarre glitch..
@@ -354,6 +354,30 @@ static Rectangle<int> convertDisplayRect (NSRect r, CGFloat mainScreenBottom)
return convertToRectInt (r);
}
static Desktop::Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& mainScreenBottom, const float masterScale)
{
Desktop::Displays::Display d;
d.isMain = (mainScreenBottom == 0);
if (d.isMain)
mainScreenBottom = [s frame].size.height;
d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom) / masterScale;
d.totalArea = convertDisplayRect ([s frame], mainScreenBottom) / masterScale;
d.scale = masterScale;
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
if ([s respondsToSelector: @selector (backingScaleFactor)])
d.scale *= s.backingScaleFactor;
#endif
NSSize dpi = [[[s deviceDescription] objectForKey: NSDeviceResolution] sizeValue];
d.dpi = (dpi.width + dpi.height) / 2.0;
return d;
}
void Desktop::Displays::findDisplays (const float masterScale)
{
JUCE_AUTORELEASEPOOL
@@ -363,30 +387,7 @@ void Desktop::Displays::findDisplays (const float masterScale)
CGFloat mainScreenBottom = 0;
for (NSScreen* s in [NSScreen screens])
{
Display d;
d.isMain = false;
if (mainScreenBottom == 0)
{
mainScreenBottom = [s frame].size.height;
d.isMain = true;
}
d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom) / masterScale;
d.totalArea = convertDisplayRect ([s frame], mainScreenBottom) / masterScale;
d.scale = masterScale;
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
if ([s respondsToSelector: @selector (backingScaleFactor)])
d.scale *= s.backingScaleFactor;
#endif
NSSize dpi = [[[s deviceDescription] objectForKey: NSDeviceResolution] sizeValue];
d.dpi = (dpi.width + dpi.height) / 2.0;
displays.add (d);
}
displays.add (getDisplayFromScreen (s, mainScreenBottom, masterScale));
}
}
@@ -177,6 +177,7 @@ static void setWindowZOrder (HWND hwnd, HWND insertAfter)
//==============================================================================
static void setDPIAwareness()
{
#if ! JUCE_DISABLE_WIN32_DPI_AWARENESS
if (JUCEApplicationBase::isStandaloneApp())
{
if (setProcessDPIAwareness == nullptr)
@@ -203,6 +204,7 @@ static void setDPIAwareness()
}
}
}
#endif
}
static double getGlobalDPI()
@@ -704,8 +706,8 @@ public:
r.top + windowBorder.getTop());
}
Point<int> localToGlobal (Point<int> relativePosition) override { return relativePosition + getScreenPosition(); }
Point<int> globalToLocal (Point<int> screenPosition) override { return screenPosition - getScreenPosition(); }
Point<float> localToGlobal (Point<float> relativePosition) override { return relativePosition + getScreenPosition().toFloat(); }
Point<float> globalToLocal (Point<float> screenPosition) override { return screenPosition - getScreenPosition().toFloat(); }
void setAlpha (float newAlpha) override
{
@@ -763,7 +765,7 @@ public:
ShowWindow (hwnd, SW_SHOWNORMAL);
if (! boundsCopy.isEmpty())
setBounds (boundsCopy, false);
setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, boundsCopy), false);
}
else
{
@@ -845,7 +847,7 @@ public:
void toBehind (ComponentPeer* other) override
{
if (HWNDComponentPeer* const otherPeer = dynamic_cast <HWNDComponentPeer*> (other))
if (HWNDComponentPeer* const otherPeer = dynamic_cast<HWNDComponentPeer*> (other))
{
setMinimised (false);
@@ -877,7 +879,7 @@ public:
shouldDeactivateTitleBar = oldDeactivate;
}
void textInputRequired (const Point<int>&) override
void textInputRequired (Point<int>, TextInputTarget&) override
{
if (! hasCreatedCaret)
{
@@ -902,10 +904,15 @@ public:
void performAnyPendingRepaintsNow() override
{
MSG m;
if (component.isVisible()
&& (PeekMessage (&m, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE) || isUsingUpdateLayeredWindow()))
handlePaintMessage();
if (component.isVisible())
{
WeakReference<Component> localRef (&component);
MSG m;
if (isUsingUpdateLayeredWindow() || PeekMessage (&m, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE))
if (localRef != nullptr) // (the PeekMessage call can dispatch messages, which may delete this comp)
handlePaintMessage();
}
}
//==============================================================================
@@ -955,7 +962,7 @@ public:
static ModifierKeys modifiersAtLastCallback;
//==============================================================================
class JuceDropTarget : public ComBaseClassHelper <IDropTarget>
class JuceDropTarget : public ComBaseClassHelper<IDropTarget>
{
public:
JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {}
@@ -988,7 +995,7 @@ public:
if (ownerInfo == nullptr)
return S_FALSE;
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos);
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt();
const bool wasWanted = ownerInfo->owner.handleDragMove (ownerInfo->dragInfo);
*pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE;
return S_OK;
@@ -999,7 +1006,7 @@ public:
HRESULT hr = updateFileList (pDataObject);
if (SUCCEEDED (hr))
{
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos);
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt();
const bool wasWanted = ownerInfo->owner.handleDragDrop (ownerInfo->dragInfo);
*pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE;
hr = S_OK;
@@ -1013,9 +1020,10 @@ public:
{
OwnerInfo (HWNDComponentPeer& p) : owner (p) {}
Point<int> getMousePos (const POINTL& mousePos) const
Point<float> getMousePos (const POINTL& mousePos) const
{
return owner.globalToLocal (Point<int> (mousePos.x, mousePos.y));
return owner.globalToLocal (Point<float> (static_cast<float> (mousePos.x),
static_cast<float> (mousePos.y)));
}
template <typename CharType>
@@ -1093,13 +1101,13 @@ public:
if (SUCCEEDED (fileData.error))
{
const LPDROPFILES dropFiles = static_cast <const LPDROPFILES> (fileData.data);
const LPDROPFILES dropFiles = static_cast<const LPDROPFILES> (fileData.data);
const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES));
if (dropFiles->fWide)
ownerInfo->parseFileList (static_cast <const WCHAR*> (names), fileData.dataSize);
ownerInfo->parseFileList (static_cast<const WCHAR*> (names), fileData.dataSize);
else
ownerInfo->parseFileList (static_cast <const char*> (names), fileData.dataSize);
ownerInfo->parseFileList (static_cast<const char*> (names), fileData.dataSize);
}
else
{
@@ -1294,7 +1302,7 @@ private:
//==============================================================================
static void* createWindowCallback (void* userData)
{
static_cast <HWNDComponentPeer*> (userData)->createWindow();
static_cast<HWNDComponentPeer*> (userData)->createWindow();
return nullptr;
}
@@ -1522,10 +1530,14 @@ private:
// if something in a paint handler calls, e.g. a message box, this can become reentrant and
// corrupt the image it's using to paint into, so do a check here.
static bool reentrant = false;
if (! (reentrant || dontRepaint))
if (! reentrant)
{
const ScopedValueSetter<bool> setter (reentrant, true, false);
performPaint (dc, rgn, regionType, paintStruct);
if (dontRepaint)
component.handleCommandMessage (0); // (this triggers a repaint in the openGL context)
else
performPaint (dc, rgn, regionType, paintStruct);
}
DeleteObject (rgn);
@@ -1633,7 +1645,7 @@ private:
handlePaint (*context);
}
static_cast <WindowsBitmapImage*> (offscreenImage.getPixelData())
static_cast<WindowsBitmapImage*> (offscreenImage.getPixelData())
->blitToWindow (hwnd, dc, transparent, x, y, updateLayeredWindowAlpha);
}
@@ -1643,7 +1655,7 @@ private:
}
//==============================================================================
void doMouseEvent (Point<int> position)
void doMouseEvent (Point<float> position)
{
handleMouseEvent (0, position, currentModifiers, getMouseEventTime());
}
@@ -1694,7 +1706,7 @@ private:
return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP..
}
void doMouseMove (Point<int> position)
void doMouseMove (Point<float> position)
{
if (! isMouseOver)
{
@@ -1715,7 +1727,7 @@ private:
}
else if (! isDragging)
{
if (! contains (position, false))
if (! contains (position.roundToInt(), false))
return;
}
@@ -1730,7 +1742,7 @@ private:
}
}
void doMouseDown (Point<int> position, const WPARAM wParam)
void doMouseDown (Point<float> position, const WPARAM wParam)
{
if (GetCapture() != hwnd)
SetCapture (hwnd);
@@ -1743,7 +1755,7 @@ private:
doMouseEvent (position);
}
void doMouseUp (Point<int> position, const WPARAM wParam)
void doMouseUp (Point<float> position, const WPARAM wParam)
{
updateModifiersFromWParam (wParam);
const bool wasDragging = isDragging;
@@ -1779,9 +1791,9 @@ private:
doMouseEvent (getCurrentMousePos());
}
ComponentPeer* findPeerUnderMouse (Point<int>& localPos)
ComponentPeer* findPeerUnderMouse (Point<float>& localPos)
{
const Point<int> globalPos (getCurrentMousePosGlobal());
const Point<int> globalPos (getCurrentMousePosGlobal().roundToInt());
// Because Windows stupidly sends all wheel events to the window with the keyboard
// focus, we have to redirect them here according to the mouse pos..
@@ -1791,7 +1803,7 @@ private:
if (peer == nullptr)
peer = this;
localPos = peer->globalToLocal (globalPos);
localPos = peer->globalToLocal (globalPos.toFloat());
return peer;
}
@@ -1806,7 +1818,7 @@ private:
wheel.isReversed = false;
wheel.isSmooth = false;
Point<int> localPos;
Point<float> localPos;
if (ComponentPeer* const peer = findPeerUnderMouse (localPos))
peer->handleMouseWheel (0, localPos, getMouseEventTime(), wheel);
}
@@ -1820,7 +1832,7 @@ private:
if (getGestureInfo != nullptr && getGestureInfo ((HGESTUREINFO) lParam, &gi))
{
updateKeyModifiers();
Point<int> localPos;
Point<float> localPos;
if (ComponentPeer* const peer = findPeerUnderMouse (localPos))
{
@@ -1878,8 +1890,8 @@ private:
bool isCancel = false;
const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID);
const int64 time = getMouseEventTime();
const Point<int> pos (globalToLocal (Point<int> ((int) TOUCH_COORD_TO_PIXEL (touch.x),
(int) TOUCH_COORD_TO_PIXEL (touch.y))));
const Point<float> pos (globalToLocal (Point<float> (static_cast<float> (TOUCH_COORD_TO_PIXEL (touch.x)),
static_cast<float> (TOUCH_COORD_TO_PIXEL (touch.y)))));
ModifierKeys modsToSend (currentModifiers);
if (isDown)
@@ -1890,7 +1902,7 @@ private:
if (! isPrimary)
{
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before.
handleMouseEvent (touchIndex, pos, modsToSend.withoutMouseButtons(), time);
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend.withoutMouseButtons(), time);
if (! isValidPeer (this)) // (in case this component was deleted by the event)
return false;
}
@@ -1916,14 +1928,14 @@ private:
if (! isPrimary)
{
handleMouseEvent (touchIndex, pos, modsToSend, time);
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend, time);
if (! isValidPeer (this)) // (in case this component was deleted by the event)
return false;
}
if ((isUp || isCancel) && ! isPrimary)
{
handleMouseEvent (touchIndex, Point<int> (-10, -10), currentModifiers, time);
handleMouseEvent (touchIndex, Point<float> (-10.0f, -10.0f), currentModifiers, time);
if (! isValidPeer (this))
return false;
}
@@ -2203,6 +2215,22 @@ private:
return 0;
}
bool handlePositionChanged()
{
const Point<float> pos (getCurrentMousePos());
if (contains (pos.roundToInt(), false))
{
doMouseEvent (pos);
if (! isValidPeer (this))
return true;
}
handleMovedOrResized();
return ! dontRepaint; // to allow non-accelerated openGL windows to draw themselves correctly..
}
void handleAppActivation (const WPARAM wParam)
{
modifiersAtLastCallback = -1;
@@ -2213,7 +2241,7 @@ private:
component.repaint();
handleMovedOrResized();
if (! ComponentPeer::isValidPeer (this))
if (! isValidPeer (this))
return;
}
@@ -2235,6 +2263,24 @@ private:
}
}
void handlePowerBroadcast (WPARAM wParam)
{
if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
{
switch (wParam)
{
case PBT_APMSUSPEND: app->suspended(); break;
case PBT_APMQUERYSUSPENDFAILED:
case PBT_APMRESUMECRITICAL:
case PBT_APMRESUMESUSPEND:
case PBT_APMRESUMEAUTOMATIC: app->resumed(); break;
default: break;
}
}
}
void handleLeftClickInNCArea (WPARAM wParam)
{
if (! sendInputAttemptWhenModalMessage())
@@ -2283,7 +2329,7 @@ private:
{
Desktop& desktop = Desktop::getInstance();
const_cast <Desktop::Displays&> (desktop.getDisplays()).refresh();
const_cast<Desktop::Displays&> (desktop.getDisplays()).refresh();
if (fullScreen && ! isMinimised())
{
@@ -2321,17 +2367,18 @@ private:
return MessageManager::getInstance()->callFunctionOnMessageThread (callback, userData);
}
static Point<int> getPointFromLParam (LPARAM lParam) noexcept
static Point<float> getPointFromLParam (LPARAM lParam) noexcept
{
return Point<int> (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam));
return Point<float> (static_cast<float> (GET_X_LPARAM (lParam)),
static_cast<float> (GET_Y_LPARAM (lParam)));
}
static Point<int> getCurrentMousePosGlobal() noexcept
static Point<float> getCurrentMousePosGlobal() noexcept
{
return getPointFromLParam (GetMessagePos());
}
Point<int> getCurrentMousePos() noexcept
Point<float> getCurrentMousePos() noexcept
{
return globalToLocal (getCurrentMousePosGlobal());
}
@@ -2411,18 +2458,10 @@ private:
case WM_WINDOWPOSCHANGING: return handlePositionChanging (*(WINDOWPOS*) lParam);
case WM_WINDOWPOSCHANGED:
{
const Point<int> pos (getCurrentMousePos());
if (contains (pos, false))
doMouseEvent (pos);
}
if (handlePositionChanged())
return 0;
handleMovedOrResized();
if (dontRepaint)
break; // needed for non-accelerated openGL windows to draw themselves correctly..
return 0;
break;
//==============================================================================
case WM_KEYDOWN:
@@ -2531,6 +2570,10 @@ private:
}
return TRUE;
case WM_POWERBROADCAST:
handlePowerBroadcast (wParam);
break;
case WM_SYNCPAINT:
return 0;
@@ -2860,7 +2903,7 @@ private:
void moveCandidateWindowToLeftAlignWithSelection (HIMC hImc, ComponentPeer& peer, TextInputTarget* target) const
{
if (Component* const targetComp = dynamic_cast <Component*> (target))
if (Component* const targetComp = dynamic_cast<Component*> (target))
{
const Rectangle<int> area (peer.getComponent().getLocalArea (targetComp, target->getCaretRectangle()));
@@ -2881,18 +2924,15 @@ private:
ModifierKeys HWNDComponentPeer::currentModifiers;
ModifierKeys HWNDComponentPeer::modifiersAtLastCallback;
ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindowToAttachTo)
ComponentPeer* Component::createNewPeer (int styleFlags, void* parentHWND)
{
return new HWNDComponentPeer (*this, styleFlags,
(HWND) nativeWindowToAttachTo, false);
return new HWNDComponentPeer (*this, styleFlags, (HWND) parentHWND, false);
}
ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component* component, void* parent)
ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component& component, void* parentHWND)
{
jassert (component != nullptr);
return new HWNDComponentPeer (*component, ComponentPeer::windowIgnoresMouseClicks,
(HWND) parent, true);
return new HWNDComponentPeer (component, ComponentPeer::windowIgnoresMouseClicks,
(HWND) parentHWND, true);
}
@@ -2965,7 +3005,7 @@ bool JUCE_CALLTYPE Process::isForegroundProcess()
fg = GetAncestor (fg, GA_ROOT);
for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
if (HWNDComponentPeer* const wp = dynamic_cast <HWNDComponentPeer*> (ComponentPeer::getPeer (i)))
if (HWNDComponentPeer* const wp = dynamic_cast<HWNDComponentPeer*> (ComponentPeer::getPeer (i)))
if (wp->isInside (fg))
return true;
@@ -2991,7 +3031,7 @@ static BOOL CALLBACK enumAlwaysOnTopWindows (HWND hwnd, LPARAM lParam)
if (GetWindowInfo (hwnd, &info)
&& (info.dwExStyle & WS_EX_TOPMOST) != 0)
{
*reinterpret_cast <bool*> (lParam) = true;
*reinterpret_cast<bool*> (lParam) = true;
return FALSE;
}
}
@@ -3126,16 +3166,17 @@ bool MouseInputSource::SourceList::addSource()
return false;
}
Point<int> MouseInputSource::getCurrentRawMousePosition()
Point<float> MouseInputSource::getCurrentRawMousePosition()
{
POINT mousePos;
GetCursorPos (&mousePos);
return Point<int> (mousePos.x, mousePos.y);
return Point<float> ((float) mousePos.x, (float) mousePos.y);
}
void MouseInputSource::setRawMousePosition (Point<int> newPosition)
void MouseInputSource::setRawMousePosition (Point<float> newPosition)
{
SetCursorPos (newPosition.x, newPosition.y);
SetCursorPos (roundToInt (newPosition.x),
roundToInt (newPosition.y));
}
//==============================================================================
@@ -3195,7 +3236,7 @@ void SystemClipboard::copyTextToClipboard (const String& text)
{
if (HGLOBAL bufH = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, bytesNeeded + sizeof (WCHAR)))
{
if (WCHAR* const data = static_cast <WCHAR*> (GlobalLock (bufH)))
if (WCHAR* const data = static_cast<WCHAR*> (GlobalLock (bufH)))
{
text.copyToUTF16 (data, bytesNeeded);
GlobalUnlock (bufH);