Browse Source

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.

tags/2021-05-28
jules 13 years ago
parent
commit
49870de020
7 changed files with 158 additions and 150 deletions
  1. +8
    -3
      modules/juce_core/misc/juce_WindowsRegistry.h
  2. +18
    -17
      modules/juce_core/native/juce_win32_Registry.cpp
  3. +37
    -57
      modules/juce_graphics/geometry/juce_Rectangle.h
  4. +12
    -8
      modules/juce_gui_basics/native/juce_linux_FileChooser.cpp
  5. +61
    -47
      modules/juce_gui_basics/native/juce_linux_Windowing.cpp
  6. +3
    -3
      modules/juce_gui_extra/embedding/juce_NSViewComponent.h
  7. +19
    -15
      modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm

+ 8
- 3
modules/juce_core/misc/juce_WindowsRegistry.h View File

@@ -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();


+ 18
- 17
modules/juce_core/native/juce_win32_Registry.cpp View File

@@ -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)));
}

+ 37
- 57
modules/juce_graphics/geometry/juce_Rectangle.h View File

@@ -140,19 +140,13 @@ public:
//==============================================================================
/** Returns the rectangle's top-left position as a Point. */
const Point<ValueType>& getPosition() const noexcept { return pos; }
inline const Point<ValueType>& getPosition() const noexcept { return pos; }
/** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */
void setPosition (const Point<ValueType>& newPos) noexcept { pos = newPos; }
inline void setPosition (const Point<ValueType>& 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<ValueType>& 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<ValueType>& 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<ValueType>& 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<ValueType> pos;
ValueType w, h;
static int parseIntAfterSpace (const String& s) noexcept
{ return s.getCharPointer().findEndOfWhitespace().getIntValue32(); }
};


+ 12
- 8
modules/juce_gui_basics/native/juce_linux_FileChooser.cpp View File

@@ -58,16 +58,20 @@ void FileChooser::showPlatformDialog (Array<File>& 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);
}


+ 61
- 47
modules/juce_gui_basics/native/juce_linux_Windowing.cpp View File

@@ -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<Component> 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<Component> 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<int> getBounds() const { return Rectangle<int> (wx, wy, ww, wh); }
Point<int> getScreenPosition() const { return Point<int> (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<int> getBounds() const { return bounds; }
Point<int> getScreenPosition() const { return bounds.getPosition(); }
Point<int> localToGlobal (const Point<int>& relativePosition)
{
@@ -998,7 +1022,7 @@ public:
bool contains (const Point<int>& 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<int> (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<int> getFrameSize() const
@@ -1821,7 +1838,7 @@ private:
friend class LinuxRepaintManager;
Window windowH, parentWindow;
int wx, wy, ww, wh;
Rectangle<int> 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);
}
}


+ 3
- 3
modules/juce_gui_extra/embedding/juce_NSViewComponent.h View File

@@ -74,11 +74,11 @@ public:
/** @internal */
void paint (Graphics& g);
/** @internal */
static ReferenceCountedObject* attachViewToComponent (Component&, void*);
private:
class Pimpl;
friend class Pimpl;
ScopedPointer<Pimpl> pimpl;
ReferenceCountedObjectPtr<ReferenceCountedObject> attachment;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NSViewComponent);
};


+ 19
- 15
modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm View File

@@ -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<int> getViewBounds() const
{
NSRect r = [view frame];
return Rectangle<int> ((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 <NSViewAttachment*> (attachment.getObject())->view
: nullptr;
}
void NSViewComponent::resizeToFitView()
{
if (pimpl != nullptr)
setBounds (pimpl->getViewBounds());
if (attachment != nullptr)
{
NSRect r = [static_cast <NSViewAttachment*> (attachment.getObject())->view frame];
setBounds (Rectangle<int> ((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);
}

Loading…
Cancel
Save