mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-29 02:40:05 +00:00
Linux: Improved XEmbed support
This commit makes some minor improvements to the XEmbedComponent class and adds support for embedding JUCE windows in other hosts using the XEmbed protocol. It also includes some minor fixes for X11 peers when they have a parent window.
This commit is contained in:
parent
fd76cbc70d
commit
f9dad9d608
3 changed files with 103 additions and 82 deletions
|
|
@ -139,4 +139,39 @@ struct GetXProperty
|
|||
int actualFormat;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
enum
|
||||
{
|
||||
maxXEmbedVersionToSupport = 0
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
XEMBED_MAPPED = (1<<0)
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
XEMBED_EMBEDDED_NOTIFY = 0,
|
||||
XEMBED_WINDOW_ACTIVATE = 1,
|
||||
XEMBED_WINDOW_DEACTIVATE = 2,
|
||||
XEMBED_REQUEST_FOCUS = 3,
|
||||
XEMBED_FOCUS_IN = 4,
|
||||
XEMBED_FOCUS_OUT = 5,
|
||||
XEMBED_FOCUS_NEXT = 6,
|
||||
XEMBED_FOCUS_PREV = 7,
|
||||
XEMBED_MODALITY_ON = 10,
|
||||
XEMBED_MODALITY_OFF = 11,
|
||||
XEMBED_REGISTER_ACCELERATOR = 12,
|
||||
XEMBED_UNREGISTER_ACCELERATOR = 13,
|
||||
XEMBED_ACTIVATE_ACCELERATOR = 14
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
XEMBED_FOCUS_CURRENT = 0,
|
||||
XEMBED_FOCUS_FIRST = 1,
|
||||
XEMBED_FOCUS_LAST = 2
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -1163,6 +1163,20 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void updateScaleFactorFromNewBounds (const Rectangle<int>& newBounds, bool isPhysical)
|
||||
{
|
||||
Point<int> translation = (parentWindow != 0 ? getScreenPosition (isPhysical) : Point<int>());
|
||||
|
||||
auto newScaleFactor = Desktop::getInstance().getDisplays().findDisplayForRect (newBounds.translated (translation.x, translation.y), isPhysical).scale
|
||||
/ Desktop::getInstance().getGlobalScaleFactor();
|
||||
|
||||
if (! approximatelyEqual (newScaleFactor, currentScaleFactor))
|
||||
{
|
||||
currentScaleFactor = newScaleFactor;
|
||||
scaleFactorListeners.call ([&] (ScaleFactorListener& l) { l.nativeScaleFactorChanged (currentScaleFactor); });
|
||||
}
|
||||
}
|
||||
|
||||
void setBounds (const Rectangle<int>& newBounds, bool isNowFullScreen) override
|
||||
{
|
||||
if (fullScreen && ! isNowFullScreen)
|
||||
|
|
@ -1200,16 +1214,10 @@ public:
|
|||
bounds = newBounds.withSize (jmax (1, newBounds.getWidth()),
|
||||
jmax (1, newBounds.getHeight()));
|
||||
|
||||
auto& displays = Desktop::getInstance().getDisplays();
|
||||
updateScaleFactorFromNewBounds (bounds, false);
|
||||
|
||||
auto newScaleFactor = displays.findDisplayForRect (bounds, true).scale / Desktop::getInstance().getGlobalScaleFactor();
|
||||
if (! approximatelyEqual (newScaleFactor, currentScaleFactor))
|
||||
{
|
||||
currentScaleFactor = newScaleFactor;
|
||||
scaleFactorListeners.call ([&] (ScaleFactorListener& l) { l.nativeScaleFactorChanged (currentScaleFactor); });
|
||||
}
|
||||
|
||||
auto physicalBounds = displays.logicalToPhysical (bounds);
|
||||
auto physicalBounds = (parentWindow == 0 ? Desktop::getInstance().getDisplays().logicalToPhysical (bounds)
|
||||
: bounds * currentScaleFactor);
|
||||
|
||||
WeakReference<Component> deletionChecker (&component);
|
||||
ScopedXLock xlock (display);
|
||||
|
|
@ -1245,21 +1253,21 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle<int> getBounds() const override { return bounds; }
|
||||
|
||||
Point<float> localToGlobal (Point<float> relativePosition) override
|
||||
Point<int> getScreenPosition (bool physical) const
|
||||
{
|
||||
return relativePosition + bounds.getPosition().toFloat();
|
||||
if (physical)
|
||||
return Desktop::getInstance().getDisplays().logicalToPhysical (bounds.getTopLeft());
|
||||
|
||||
return bounds.getTopLeft();
|
||||
}
|
||||
|
||||
Rectangle<int> getBounds() const override { return bounds; }
|
||||
|
||||
using ComponentPeer::localToGlobal;
|
||||
|
||||
Point<float> globalToLocal (Point<float> screenPosition) override
|
||||
{
|
||||
return screenPosition - bounds.getPosition().toFloat();
|
||||
}
|
||||
Point<float> localToGlobal (Point<float> relativePosition) override { return relativePosition + getScreenPosition (false).toFloat(); }
|
||||
|
||||
using ComponentPeer::globalToLocal;
|
||||
Point<float> globalToLocal (Point<float> screenPosition) override { return screenPosition - getScreenPosition (false).toFloat(); }
|
||||
|
||||
void setAlpha (float /* newAlpha */) override
|
||||
{
|
||||
|
|
@ -1624,7 +1632,7 @@ public:
|
|||
case ClientMessage: handleClientMessageEvent (event.xclient, event); break;
|
||||
case SelectionNotify: handleDragAndDropSelection (event); break;
|
||||
case ConfigureNotify: handleConfigureNotifyEvent (event.xconfigure); break;
|
||||
case ReparentNotify: handleReparentNotifyEvent(); break;
|
||||
case ReparentNotify:
|
||||
case GravityNotify: handleGravityNotify(); break;
|
||||
case SelectionClear: handleExternalSelectionClear(); break;
|
||||
case SelectionRequest: handleExternalSelectionRequest (event); break;
|
||||
|
|
@ -2012,24 +2020,6 @@ public:
|
|||
handleBroughtToFront();
|
||||
}
|
||||
|
||||
void handleReparentNotifyEvent()
|
||||
{
|
||||
parentWindow = 0;
|
||||
Window wRoot = 0;
|
||||
Window* wChild = nullptr;
|
||||
unsigned int numChildren;
|
||||
|
||||
{
|
||||
ScopedXLock xlock (display);
|
||||
XQueryTree (display, windowH, &wRoot, &parentWindow, &wChild, &numChildren);
|
||||
}
|
||||
|
||||
if (parentWindow == windowH || parentWindow == wRoot)
|
||||
parentWindow = 0;
|
||||
|
||||
handleGravityNotify();
|
||||
}
|
||||
|
||||
void handleGravityNotify()
|
||||
{
|
||||
updateWindowBounds();
|
||||
|
|
@ -2112,6 +2102,10 @@ public:
|
|||
{
|
||||
externalResetDragAndDrop();
|
||||
}
|
||||
else if (clientMsg.message_type == atoms->XembedMsgType && clientMsg.format == 32)
|
||||
{
|
||||
handleXEmbedMessage (clientMsg);
|
||||
}
|
||||
}
|
||||
|
||||
bool externalDragTextInit (const String& text, std::function<void()> cb)
|
||||
|
|
@ -2140,6 +2134,27 @@ public:
|
|||
return externalDragInit (false, uriList.joinIntoString ("\r\n"), cb);
|
||||
}
|
||||
|
||||
void handleXEmbedMessage (XClientMessageEvent& clientMsg)
|
||||
{
|
||||
switch (clientMsg.data.l[1])
|
||||
{
|
||||
case XEMBED_EMBEDDED_NOTIFY:
|
||||
parentWindow = (::Window) clientMsg.data.l[3];
|
||||
updateWindowBounds();
|
||||
component.setBounds (bounds);
|
||||
break;
|
||||
case XEMBED_FOCUS_IN:
|
||||
handleFocusInEvent();
|
||||
break;
|
||||
case XEMBED_FOCUS_OUT:
|
||||
handleFocusOutEvent();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void showMouseCursor (Cursor cursor) noexcept
|
||||
{
|
||||
|
|
@ -2714,6 +2729,9 @@ private:
|
|||
xchangeProperty (windowH, atoms->XdndActionDescription, XA_STRING, 8, "", 0);
|
||||
xchangeProperty (windowH, atoms->XdndAware, XA_ATOM, 32, &atoms->DndVersion, 1);
|
||||
|
||||
unsigned long info[2] = { 0, 1 };
|
||||
xchangeProperty (windowH, atoms->XembedInfo, atoms->XembedInfo, 32, (unsigned char*) info, 2);
|
||||
|
||||
initialisePointerMap();
|
||||
updateModifierMappings();
|
||||
}
|
||||
|
|
@ -2823,21 +2841,16 @@ private:
|
|||
|
||||
ScopedXLock xlock (display);
|
||||
|
||||
if (XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth))
|
||||
if (XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth) && parentWindow == 0)
|
||||
if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child))
|
||||
wx = wy = 0;
|
||||
|
||||
Rectangle<int> physicalBounds (wx, wy, (int) ww, (int) wh);
|
||||
auto& displays = Desktop::getInstance().getDisplays();
|
||||
|
||||
auto newScaleFactor = displays.findDisplayForRect (physicalBounds, true).scale / Desktop::getInstance().getGlobalScaleFactor();
|
||||
if (! approximatelyEqual (newScaleFactor, currentScaleFactor))
|
||||
{
|
||||
currentScaleFactor = newScaleFactor;
|
||||
scaleFactorListeners.call ([&] (ScaleFactorListener& l) { l.nativeScaleFactorChanged (currentScaleFactor); });
|
||||
}
|
||||
updateScaleFactorFromNewBounds (physicalBounds, true);
|
||||
|
||||
bounds = displays.physicalToLogical (physicalBounds);
|
||||
bounds = (parentWindow == 0 ? Desktop::getInstance().getDisplays().physicalToLogical (physicalBounds)
|
||||
: physicalBounds / currentScaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,40 +38,6 @@ void juce_deleteKeyProxyWindow (ComponentPeer*);
|
|||
class XEmbedComponent::Pimpl : private ComponentListener
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
maxXEmbedVersionToSupport = 0
|
||||
};
|
||||
|
||||
enum Flags
|
||||
{
|
||||
XEMBED_MAPPED = (1<<0)
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
XEMBED_EMBEDDED_NOTIFY = 0,
|
||||
XEMBED_WINDOW_ACTIVATE = 1,
|
||||
XEMBED_WINDOW_DEACTIVATE = 2,
|
||||
XEMBED_REQUEST_FOCUS = 3,
|
||||
XEMBED_FOCUS_IN = 4,
|
||||
XEMBED_FOCUS_OUT = 5,
|
||||
XEMBED_FOCUS_NEXT = 6,
|
||||
XEMBED_FOCUS_PREV = 7,
|
||||
XEMBED_MODALITY_ON = 10,
|
||||
XEMBED_MODALITY_OFF = 11,
|
||||
XEMBED_REGISTER_ACCELERATOR = 12,
|
||||
XEMBED_UNREGISTER_ACCELERATOR = 13,
|
||||
XEMBED_ACTIVATE_ACCELERATOR = 14
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
XEMBED_FOCUS_CURRENT = 0,
|
||||
XEMBED_FOCUS_FIRST = 1,
|
||||
XEMBED_FOCUS_LAST = 2
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct SharedKeyWindow : public ReferenceCountedObject
|
||||
{
|
||||
|
|
@ -201,7 +167,14 @@ public:
|
|||
static_cast<unsigned int> (newBounds.getHeight()));
|
||||
}
|
||||
|
||||
XSelectInput (dpy, client, StructureNotifyMask | PropertyChangeMask | FocusChangeMask);
|
||||
auto eventMask = StructureNotifyMask | PropertyChangeMask | FocusChangeMask;
|
||||
|
||||
XWindowAttributes clientAttr;
|
||||
XGetWindowAttributes (dpy, client, &clientAttr);
|
||||
|
||||
if ((eventMask & clientAttr.your_event_mask) != eventMask)
|
||||
XSelectInput (dpy, client, clientAttr.your_event_mask | eventMask);
|
||||
|
||||
getXEmbedMappedFlag();
|
||||
|
||||
if (shouldReparent)
|
||||
|
|
@ -365,7 +338,7 @@ private:
|
|||
|
||||
Window getParentX11Window()
|
||||
{
|
||||
if (auto peer = owner.getPeer())
|
||||
if (auto* peer = owner.getPeer())
|
||||
return reinterpret_cast<Window> (peer->getNativeHandle());
|
||||
|
||||
return {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue