From 49870de0206ec6256a535745fc427b99f43f76ce Mon Sep 17 00:00:00 2001 From: jules Date: Sun, 18 Mar 2012 16:41:03 +0000 Subject: [PATCH] Added a bit of extra functionality to WindowsRegistry. Linux: couple of fixes for fullscreen, file chooser, and a bit of tidying up. Internal refactoring in NSViewComponent. --- modules/juce_core/misc/juce_WindowsRegistry.h | 11 +- .../juce_core/native/juce_win32_Registry.cpp | 35 +++--- .../juce_graphics/geometry/juce_Rectangle.h | 94 ++++++--------- .../native/juce_linux_FileChooser.cpp | 20 ++-- .../native/juce_linux_Windowing.cpp | 108 ++++++++++-------- .../embedding/juce_NSViewComponent.h | 6 +- .../native/juce_mac_NSViewComponent.mm | 34 +++--- 7 files changed, 158 insertions(+), 150 deletions(-) diff --git a/modules/juce_core/misc/juce_WindowsRegistry.h b/modules/juce_core/misc/juce_WindowsRegistry.h index 25fa78c7f2..8528f875ab 100644 --- a/modules/juce_core/misc/juce_WindowsRegistry.h +++ b/modules/juce_core/misc/juce_WindowsRegistry.h @@ -49,7 +49,7 @@ public: This will take care of creating any groups needed to get to the given registry value. */ - static void setValue (const String& regValuePath, + static bool setValue (const String& regValuePath, const String& value); /** Returns true if the given value exists in the registry. */ @@ -72,12 +72,17 @@ public: @param iconResourceNumber the icon that gets displayed for the file type will be found by looking up this resource number in the executable. Pass 0 here to not use an icon + @param registerForCurrentUserOnly if false, this will try to register the association + for all users (you might not have permission to do this + unless running in an installer). If true, it will register the + association in HKEY_CURRENT_USER. */ - static void registerFileAssociation (const String& fileExtension, + static bool registerFileAssociation (const String& fileExtension, const String& symbolicDescription, const String& fullDescription, const File& targetExecutable, - int iconResourceNumber); + int iconResourceNumber, + bool registerForCurrentUserOnly); private: WindowsRegistry(); diff --git a/modules/juce_core/native/juce_win32_Registry.cpp b/modules/juce_core/native/juce_win32_Registry.cpp index fba4d451b7..b315481bfc 100644 --- a/modules/juce_core/native/juce_win32_Registry.cpp +++ b/modules/juce_core/native/juce_win32_Registry.cpp @@ -89,14 +89,14 @@ String WindowsRegistry::getValue (const String& regValuePath, const String& defa return defaultValue; } -void WindowsRegistry::setValue (const String& regValuePath, const String& value) +bool WindowsRegistry::setValue (const String& regValuePath, const String& value) { const RegistryKeyWrapper key (regValuePath, true); - if (key.key != 0) - RegSetValueEx (key.key, key.wideCharValueName, 0, REG_SZ, - (const BYTE*) value.toWideCharPointer(), - (DWORD) CharPointer_UTF16::getBytesRequiredFor (value.getCharPointer())); + return key.key != 0 + && RegSetValueEx (key.key, key.wideCharValueName, 0, REG_SZ, + (const BYTE*) value.toWideCharPointer(), + (DWORD) CharPointer_UTF16::getBytesRequiredFor (value.getCharPointer())) == ERROR_SUCCESS; } bool WindowsRegistry::valueExists (const String& regValuePath) @@ -130,20 +130,21 @@ void WindowsRegistry::deleteKey (const String& regKeyPath) RegDeleteKey (key.key, key.wideCharValueName); } -void WindowsRegistry::registerFileAssociation (const String& fileExtension, +bool WindowsRegistry::registerFileAssociation (const String& fileExtension, const String& symbolicDescription, const String& fullDescription, const File& targetExecutable, - int iconResourceNumber) + const int iconResourceNumber, + const bool registerForCurrentUserOnly) { - setValue ("HKEY_CLASSES_ROOT\\" + fileExtension + "\\", symbolicDescription); - - const String key ("HKEY_CLASSES_ROOT\\" + symbolicDescription); - - if (iconResourceNumber != 0) - setValue (key + "\\DefaultIcon\\", - targetExecutable.getFullPathName() + "," + String (-iconResourceNumber)); - - setValue (key + "\\", fullDescription); - setValue (key + "\\shell\\open\\command\\", targetExecutable.getFullPathName() + " %1"); + const char* const root = registerForCurrentUserOnly ? "HKEY_CURRENT_USER\\Software\\Classes\\" + : "HKEY_CLASSES_ROOT\\"; + const String key (root + symbolicDescription); + + return setValue (root + fileExtension + "\\", symbolicDescription) + && setValue (key + "\\", fullDescription) + && setValue (key + "\\shell\\open\\command\\", targetExecutable.getFullPathName() + " \"%1\"") + && (iconResourceNumber == 0 + || setValue (key + "\\DefaultIcon\\", + targetExecutable.getFullPathName() + "," + String (-iconResourceNumber))); } diff --git a/modules/juce_graphics/geometry/juce_Rectangle.h b/modules/juce_graphics/geometry/juce_Rectangle.h index ba5fe06b49..9972c35b30 100644 --- a/modules/juce_graphics/geometry/juce_Rectangle.h +++ b/modules/juce_graphics/geometry/juce_Rectangle.h @@ -140,19 +140,13 @@ public: //============================================================================== /** Returns the rectangle's top-left position as a Point. */ - const Point& getPosition() const noexcept { return pos; } + inline const Point& getPosition() const noexcept { return pos; } /** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */ - void setPosition (const Point& newPos) noexcept { pos = newPos; } + inline void setPosition (const Point& newPos) noexcept { pos = newPos; } /** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */ - void setPosition (const ValueType newX, const ValueType newY) noexcept { pos.setXY (newX, newY); } - - /** Returns a rectangle with the same size as this one, but a new position. */ - Rectangle withPosition (const ValueType newX, const ValueType newY) const noexcept { return Rectangle (newX, newY, w, h); } - - /** Returns a rectangle with the same size as this one, but a new position. */ - Rectangle withPosition (const Point& newPos) const noexcept { return Rectangle (newPos.x, newPos.y, w, h); } + inline void setPosition (const ValueType newX, const ValueType newY) noexcept { pos.setXY (newX, newY); } /** Returns the rectangle's top-left position as a Point. */ const Point& getTopLeft() const noexcept { return pos; } @@ -169,49 +163,51 @@ public: /** Changes the rectangle's size, leaving the position of its top-left corner unchanged. */ void setSize (const ValueType newWidth, const ValueType newHeight) noexcept { w = newWidth; h = newHeight; } - /** Returns a rectangle with the same position as this one, but a new size. */ - Rectangle withSize (const ValueType newWidth, const ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, newWidth, newHeight); } - /** Changes all the rectangle's co-ordinates. */ void setBounds (const ValueType newX, const ValueType newY, - const ValueType newWidth, const ValueType newHeight) noexcept - { - pos.x = newX; pos.y = newY; w = newWidth; h = newHeight; - } + const ValueType newWidth, const ValueType newHeight) noexcept { pos.x = newX; pos.y = newY; w = newWidth; h = newHeight; } /** Changes the rectangle's X coordinate */ - void setX (const ValueType newX) noexcept { pos.x = newX; } + inline void setX (const ValueType newX) noexcept { pos.x = newX; } /** Changes the rectangle's Y coordinate */ - void setY (const ValueType newY) noexcept { pos.y = newY; } + inline void setY (const ValueType newY) noexcept { pos.y = newY; } /** Changes the rectangle's width */ - void setWidth (const ValueType newWidth) noexcept { w = newWidth; } + inline void setWidth (const ValueType newWidth) noexcept { w = newWidth; } /** Changes the rectangle's height */ - void setHeight (const ValueType newHeight) noexcept { h = newHeight; } + inline void setHeight (const ValueType newHeight) noexcept { h = newHeight; } /** Returns a rectangle which has the same size and y-position as this one, but with a different x-position. */ - Rectangle withX (const ValueType newX) const noexcept { return Rectangle (newX, pos.y, w, h); } + Rectangle withX (const ValueType newX) const noexcept { return Rectangle (newX, pos.y, w, h); } /** Returns a rectangle which has the same size and x-position as this one, but with a different y-position. */ - Rectangle withY (const ValueType newY) const noexcept { return Rectangle (pos.x, newY, w, h); } + Rectangle withY (const ValueType newY) const noexcept { return Rectangle (pos.x, newY, w, h); } + + /** Returns a rectangle with the same size as this one, but a new position. */ + Rectangle withPosition (const ValueType newX, const ValueType newY) const noexcept { return Rectangle (newX, newY, w, h); } + + /** Returns a rectangle with the same size as this one, but a new position. */ + Rectangle withPosition (const Point& newPos) const noexcept { return Rectangle (newPos.x, newPos.y, w, h); } + + /** Returns a rectangle whose size is the same as this one, but whose top-left position is (0, 0). */ + Rectangle withZeroOrigin() const noexcept { return Rectangle (w, h); } /** Returns a rectangle which has the same position and height as this one, but with a different width. */ - Rectangle withWidth (const ValueType newWidth) const noexcept { return Rectangle (pos.x, pos.y, newWidth, h); } + Rectangle withWidth (const ValueType newWidth) const noexcept { return Rectangle (pos.x, pos.y, newWidth, h); } /** Returns a rectangle which has the same position and width as this one, but with a different height. */ - Rectangle withHeight (const ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, w, newHeight); } + Rectangle withHeight (const ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, w, newHeight); } + + /** Returns a rectangle with the same position as this one, but a new size. */ + Rectangle withSize (const ValueType newWidth, const ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, newWidth, newHeight); } /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place. If the x is moved to be on the right of the current right-hand edge, the width will be set to zero. @see withLeft */ - void setLeft (const ValueType newLeft) noexcept - { - w = jmax (ValueType(), pos.x + w - newLeft); - pos.x = newLeft; - } + void setLeft (const ValueType newLeft) noexcept { w = jmax (ValueType(), pos.x + w - newLeft); pos.x = newLeft; } /** Returns a new rectangle with a different x position, but the same right-hand edge as this one. If the new x is beyond the right of the current right-hand edge, the width will be set to zero. @@ -223,11 +219,7 @@ public: If the y is moved to be below the current bottom edge, the height will be set to zero. @see withTop */ - void setTop (const ValueType newTop) noexcept - { - h = jmax (ValueType(), pos.y + h - newTop); - pos.y = newTop; - } + void setTop (const ValueType newTop) noexcept { h = jmax (ValueType(), pos.y + h - newTop); pos.y = newTop; } /** Returns a new rectangle with a different y position, but the same bottom edge as this one. If the new y is beyond the bottom of the current rectangle, the height will be set to zero. @@ -239,11 +231,7 @@ public: If the new right is below the current X value, the X will be pushed down to match it. @see getRight, withRight */ - void setRight (const ValueType newRight) noexcept - { - pos.x = jmin (pos.x, newRight); - w = newRight - pos.x; - } + void setRight (const ValueType newRight) noexcept { pos.x = jmin (pos.x, newRight); w = newRight - pos.x; } /** Returns a new rectangle with a different right-hand edge position, but the same left-hand edge as this one. If the new right edge is below the current left-hand edge, the width will be set to zero. @@ -255,11 +243,7 @@ public: If the new bottom is lower than the current Y value, the Y will be pushed down to match it. @see getBottom, withBottom */ - void setBottom (const ValueType newBottom) noexcept - { - pos.y = jmin (pos.y, newBottom); - h = newBottom - pos.y; - } + void setBottom (const ValueType newBottom) noexcept { pos.y = jmin (pos.y, newBottom); h = newBottom - pos.y; } /** Returns a new rectangle with a different bottom edge position, but the same top edge as this one. If the new y is beyond the bottom of the current rectangle, the height will be set to zero. @@ -425,16 +409,10 @@ public: //============================================================================== /** Returns true if the two rectangles are identical. */ - bool operator== (const Rectangle& other) const noexcept - { - return pos == other.pos && w == other.w && h == other.h; - } + bool operator== (const Rectangle& other) const noexcept { return pos == other.pos && w == other.w && h == other.h; } /** Returns true if the two rectangles are not identical. */ - bool operator!= (const Rectangle& other) const noexcept - { - return pos != other.pos || w != other.w || h != other.h; - } + bool operator!= (const Rectangle& other) const noexcept { return pos != other.pos || w != other.w || h != other.h; } /** Returns true if this co-ordinate is inside the rectangle. */ bool contains (const ValueType xCoord, const ValueType yCoord) const noexcept @@ -473,7 +451,6 @@ public: } /** Returns the region that is the overlap between this and another rectangle. - If the two rectangles don't overlap, the rectangle returned will be empty. */ Rectangle getIntersection (const Rectangle& other) const noexcept @@ -716,16 +693,19 @@ public: StringArray toks; toks.addTokens (stringVersion.trim(), ",; \t\r\n", String::empty); - return Rectangle (toks[0].trim().getIntValue(), - toks[1].trim().getIntValue(), - toks[2].trim().getIntValue(), - toks[3].trim().getIntValue()); + return Rectangle (parseIntAfterSpace (toks[0]), + parseIntAfterSpace (toks[1]), + parseIntAfterSpace (toks[2]), + parseIntAfterSpace (toks[3])); } private: friend class RectangleList; Point pos; ValueType w, h; + + static int parseIntAfterSpace (const String& s) noexcept + { return s.getCharPointer().findEndOfWhitespace().getIntValue32(); } }; diff --git a/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp b/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp index 320cfd3ab8..39da8630b2 100644 --- a/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp +++ b/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp @@ -58,16 +58,20 @@ void FileChooser::showPlatformDialog (Array& results, ChildProcess child; if (child.start (command)) { - const String result (child.readAllProcessOutput()); - StringArray tokens; + const String result (child.readAllProcessOutput().trim()); - if (selectMultipleFiles) - tokens.addTokens (result, separator, "\""); - else - tokens.add (result); + if (result.isNotEmpty()) + { + StringArray tokens; - for (int i = 0; i < tokens.size(); i++) - results.add (File (tokens[i])); + if (selectMultipleFiles) + tokens.addTokens (result, separator, "\""); + else + tokens.add (result); + + for (int i = 0; i < tokens.size(); i++) + results.add (File (tokens[i])); + } child.waitForProcessToFinish (60 * 1000); } diff --git a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index d43bc1b347..a45bfb4474 100644 --- a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -744,7 +744,6 @@ public: LinuxComponentPeer (Component* const component, const int windowStyleFlags, Window parentToAddTo) : ComponentPeer (component, windowStyleFlags), windowH (0), parentWindow (0), - wx (0), wy (0), ww (0), wh (0), fullScreen (false), mapped (false), visual (0), depth (0) { @@ -814,26 +813,49 @@ public: void setBounds (int x, int y, int w, int h, bool isNowFullScreen) { + if (fullScreen && ! isNowFullScreen) + { + // When transitioning back from fullscreen, we might need to remove + // the FULLSCREEN window property + Atom fs = Atoms::getIfExists ("_NET_WM_STATE_FULLSCREEN"); + + if (fs != None) + { + Window root = RootWindow (display, DefaultScreen (display)); + + XClientMessageEvent clientMsg; + clientMsg.display = display; + clientMsg.window = windowH; + clientMsg.type = ClientMessage; + clientMsg.format = 32; + clientMsg.message_type = Atoms::WindowState; + clientMsg.data.l[0] = 0; // Remove + clientMsg.data.l[1] = fs; + clientMsg.data.l[2] = 0; + clientMsg.data.l[3] = 1; // Normal Source + + ScopedXLock xlock; + XSendEvent (display, root, false, + SubstructureRedirectMask | SubstructureNotifyMask, + (XEvent*) &clientMsg); + } + } + fullScreen = isNowFullScreen; if (windowH != 0) { - WeakReference deletionChecker (component); - - wx = x; - wy = y; - ww = jmax (1, w); - wh = jmax (1, h); + bounds.setBounds (x, y, jmax (1, w), jmax (1, h)); + WeakReference deletionChecker (component); ScopedXLock xlock; - // Make sure the Window manager does what we want - XSizeHints* hints = XAllocSizeHints(); - hints->flags = USSize | USPosition; - hints->width = ww; - hints->height = wh; - hints->x = wx; - hints->y = wy; + XSizeHints* const hints = XAllocSizeHints(); + hints->flags = USSize | USPosition; + hints->x = bounds.getX(); + hints->y = bounds.getY(); + hints->width = bounds.getWidth(); + hints->height = bounds.getHeight(); if ((getStyleFlags() & (windowHasTitleBar | windowIsResizable)) == windowHasTitleBar) { @@ -846,10 +868,12 @@ public: XFree (hints); XMoveResizeWindow (display, windowH, - wx - windowBorder.getLeft(), - wy - windowBorder.getTop(), ww, wh); + bounds.getX() - windowBorder.getLeft(), + bounds.getY() - windowBorder.getTop(), + bounds.getWidth(), + bounds.getHeight()); - if (deletionChecker != 0) + if (deletionChecker != nullptr) { updateBorderSize(); handleMovedOrResized(); @@ -857,10 +881,10 @@ public: } } - void setPosition (int x, int y) { setBounds (x, y, ww, wh, false); } - void setSize (int w, int h) { setBounds (wx, wy, w, h, false); } - Rectangle getBounds() const { return Rectangle (wx, wy, ww, wh); } - Point getScreenPosition() const { return Point (wx, wy); } + void setPosition (int x, int y) { setBounds (x, y, bounds.getWidth(), bounds.getHeight(), false); } + void setSize (int w, int h) { setBounds (bounds.getX(), bounds.getY(), w, h, false); } + Rectangle getBounds() const { return bounds; } + Point getScreenPosition() const { return bounds.getPosition(); } Point localToGlobal (const Point& relativePosition) { @@ -998,7 +1022,7 @@ public: bool contains (const Point& position, bool trueIfInAChildWindow) const { - if (! (isPositiveAndBelow (position.getX(), ww) && isPositiveAndBelow (position.getY(), wh))) + if (! bounds.withZeroOrigin().contains (position)) return false; for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) @@ -1008,7 +1032,7 @@ public: if (c == getComponent()) break; - if (c->contains (position + Point (wx, wy) - c->getScreenPosition())) + if (c->contains (position + bounds.getPosition() - c->getScreenPosition())) return false; } @@ -1016,21 +1040,14 @@ public: return true; ::Window root, child; - unsigned int bw, depth; - int wx, wy, w, h; + int wx, wy; + unsigned int ww, wh, bw, depth; ScopedXLock xlock; - if (! XGetGeometry (display, (::Drawable) windowH, &root, - &wx, &wy, (unsigned int*) &w, (unsigned int*) &h, - &bw, &depth)) - { - return false; - } - - if (! XTranslateCoordinates (display, windowH, windowH, position.getX(), position.getY(), &wx, &wy, &child)) - return false; - return child == None; + return XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &depth) + && XTranslateCoordinates (display, windowH, windowH, position.getX(), position.getY(), &wx, &wy, &child) + && child == None; } BorderSize getFrameSize() const @@ -1821,7 +1838,7 @@ private: friend class LinuxRepaintManager; Window windowH, parentWindow; - int wx, wy, ww, wh; + Rectangle bounds; Image taskbarImage; bool fullScreen, mapped; Visual* visual; @@ -2230,19 +2247,16 @@ private: if (windowH != 0) { Window root, child; - unsigned int bw, depth; + int wx = 0, wy = 0; + unsigned int ww = 0, wh = 0, bw, depth; + ScopedXLock xlock; - if (! XGetGeometry (display, (::Drawable) windowH, &root, - &wx, &wy, (unsigned int*) &ww, (unsigned int*) &wh, - &bw, &depth)) - { - wx = wy = ww = wh = 0; - } - else if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child)) - { - wx = wy = 0; - } + if (XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &depth)) + if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child)) + wx = wy = 0; + + bounds.setBounds (wx, wy, ww, wh); } } diff --git a/modules/juce_gui_extra/embedding/juce_NSViewComponent.h b/modules/juce_gui_extra/embedding/juce_NSViewComponent.h index 8a1d6ec334..fdad4bdb68 100644 --- a/modules/juce_gui_extra/embedding/juce_NSViewComponent.h +++ b/modules/juce_gui_extra/embedding/juce_NSViewComponent.h @@ -74,11 +74,11 @@ public: /** @internal */ void paint (Graphics& g); + /** @internal */ + static ReferenceCountedObject* attachViewToComponent (Component&, void*); private: - class Pimpl; - friend class Pimpl; - ScopedPointer pimpl; + ReferenceCountedObjectPtr attachment; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewComponent); }; diff --git a/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm b/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm index 9e7baf122e..6824265fc5 100644 --- a/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm +++ b/modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm @@ -23,10 +23,11 @@ ============================================================================== */ -class NSViewComponent::Pimpl : public ComponentMovementWatcher +class NSViewAttachment : public ReferenceCountedObject, + public ComponentMovementWatcher { public: - Pimpl (NSView* const view_, Component& owner_) + NSViewAttachment (NSView* const view_, Component& owner_) : ComponentMovementWatcher (&owner_), view (view_), owner (owner_), @@ -38,7 +39,7 @@ public: componentPeerChanged(); } - ~Pimpl() + ~NSViewAttachment() { removeFromParent(); [view release]; @@ -96,12 +97,6 @@ public: componentPeerChanged(); } - Rectangle getViewBounds() const - { - NSRect r = [view frame]; - return Rectangle ((int) r.size.width, (int) r.size.height); - } - NSView* const view; private: @@ -115,7 +110,7 @@ private: // override the call and use it as a sign that they're being deleted, which breaks everything.. } - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewAttachment); }; //============================================================================== @@ -126,22 +121,31 @@ void NSViewComponent::setView (void* const view) { if (view != getView()) { - pimpl = nullptr; + attachment = nullptr; if (view != nullptr) - pimpl = new Pimpl ((NSView*) view, *this); + attachment = attachViewToComponent (*this, view); } } void* NSViewComponent::getView() const { - return pimpl == nullptr ? nullptr : pimpl->view; + return attachment != nullptr ? static_cast (attachment.getObject())->view + : nullptr; } void NSViewComponent::resizeToFitView() { - if (pimpl != nullptr) - setBounds (pimpl->getViewBounds()); + if (attachment != nullptr) + { + NSRect r = [static_cast (attachment.getObject())->view frame]; + setBounds (Rectangle ((int) r.size.width, (int) r.size.height)); + } } void NSViewComponent::paint (Graphics&) {} + +ReferenceCountedObject* NSViewComponent::attachViewToComponent (Component& comp, void* const view) +{ + return new NSViewAttachment ((NSView*) view, comp); +}