diff --git a/modules/juce_gui_basics/native/juce_linux_X11.h b/modules/juce_gui_basics/native/juce_linux_X11.h index f5c5cdd98e..a6a5b4f371 100644 --- a/modules/juce_gui_basics/native/juce_linux_X11.h +++ b/modules/juce_gui_basics/native/juce_linux_X11.h @@ -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 diff --git a/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp index 500d5d6442..ba562dd8bd 100644 --- a/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp @@ -1163,6 +1163,20 @@ public: } } + void updateScaleFactorFromNewBounds (const Rectangle& newBounds, bool isPhysical) + { + Point translation = (parentWindow != 0 ? getScreenPosition (isPhysical) : Point()); + + 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& 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 deletionChecker (&component); ScopedXLock xlock (display); @@ -1245,21 +1253,21 @@ public: } } - Rectangle getBounds() const override { return bounds; } - - Point localToGlobal (Point relativePosition) override + Point getScreenPosition (bool physical) const { - return relativePosition + bounds.getPosition().toFloat(); + if (physical) + return Desktop::getInstance().getDisplays().logicalToPhysical (bounds.getTopLeft()); + + return bounds.getTopLeft(); } + Rectangle getBounds() const override { return bounds; } + using ComponentPeer::localToGlobal; - - Point globalToLocal (Point screenPosition) override - { - return screenPosition - bounds.getPosition().toFloat(); - } + Point localToGlobal (Point relativePosition) override { return relativePosition + getScreenPosition (false).toFloat(); } using ComponentPeer::globalToLocal; + Point globalToLocal (Point 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 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 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); } } diff --git a/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp b/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp index 3a1f34d84f..d1c0ae7151 100644 --- a/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp +++ b/modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp @@ -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 (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 (peer->getNativeHandle()); return {};