Browse Source

Linux: Fixed some issues with headless builds and don't terminate process when no X server is running

tags/2021-05-28
ed 5 years ago
parent
commit
0f6cdd8457
5 changed files with 74 additions and 65 deletions
  1. +1
    -6
      modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h
  2. +59
    -48
      modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp
  3. +5
    -4
      modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h
  4. +8
    -6
      modules/juce_gui_extra/native/juce_linux_X11_SystemTrayIcon.cpp
  5. +1
    -1
      modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp

+ 1
- 6
modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h View File

@@ -39,7 +39,7 @@ class JUCE_API X11Symbols
{
public:
//==============================================================================
bool areXFunctionsAvailable() { return functionsAreAvailable; }
bool loadAllSymbols();
//==============================================================================
JUCE_GENERATE_FUNCTION_WITH_DEFAULT (XAllocSizeHints, xAllocSizeHints,
@@ -570,9 +570,6 @@ private:
clearSingletonInstance();
}
//==============================================================================
bool loadAllSymbols();
//==============================================================================
DynamicLibrary xLib { "libX11.so" }, xextLib { "libXext.so" };
@@ -589,8 +586,6 @@ private:
DynamicLibrary xrandrLib { "libXrandr.so" };
#endif
const bool functionsAreAvailable = loadAllSymbols();
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (X11Symbols)
};


+ 59
- 48
modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp View File

@@ -1225,13 +1225,10 @@ static std::unordered_map<LinuxComponentPeer<::Window>*, X11DragState> dragAndDr
XWindowSystem::XWindowSystem()
{
xIsAvailable = X11Symbols::getInstance()->areXFunctionsAvailable();
xIsAvailable = X11Symbols::getInstance()->loadAllSymbols();
if (! xIsAvailable)
{
X11Symbols::deleteInstance();
return;
}
if (JUCEApplicationBase::isStandaloneApp())
{
@@ -1255,7 +1252,14 @@ XWindowSystem::XWindowSystem()
X11ErrorHandling::installXErrorHandlers();
}
initialiseXDisplay();
if (! initialiseXDisplay())
{
if (JUCEApplicationBase::isStandaloneApp())
X11ErrorHandling::removeXErrorHandlers();
X11Symbols::deleteInstance();
xIsAvailable = false;
}
}
XWindowSystem::~XWindowSystem()
@@ -1266,10 +1270,9 @@ XWindowSystem::~XWindowSystem()
if (JUCEApplicationBase::isStandaloneApp())
X11ErrorHandling::removeXErrorHandlers();
X11Symbols::deleteInstance();
}
X11Symbols::deleteInstance();
clearSingletonInstance();
}
@@ -1284,10 +1287,14 @@ static int getAllEventsMask (bool ignoresMouseClicks)
::Window XWindowSystem::createWindow (::Window parentToAddTo, LinuxComponentPeer<::Window>* peer) const
{
auto styleFlags = peer->getStyleFlags();
if (! xIsAvailable)
{
// can't open a window on a system that doesn't have X11 installed!
jassertfalse;
return 0;
}
// can't open a window on a system that doesn't have X11 installed!
jassert (X11Symbols::getInstance()->areXFunctionsAvailable());
auto styleFlags = peer->getStyleFlags();
XWindowSystemUtilities::ScopedXLock xLock;
@@ -1338,21 +1345,21 @@ static int getAllEventsMask (bool ignoresMouseClicks)
// Associate the PID, allowing to be shut down when something goes wrong
auto pid = (unsigned long) 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));
xchangeProperty (windowH, atoms->XdndActionList, XA_ATOM, 32, atoms->allowedActions, numElementsInArray (atoms->allowedActions));
xchangeProperty (windowH, atoms->XdndActionDescription, XA_STRING, 8, "", 0);
xchangeProperty (windowH, atoms.XdndTypeList, XA_ATOM, 32, atoms.allowedMimeTypes, numElementsInArray (atoms.allowedMimeTypes));
xchangeProperty (windowH, atoms.XdndActionList, XA_ATOM, 32, atoms.allowedActions, numElementsInArray (atoms.allowedActions));
xchangeProperty (windowH, atoms.XdndActionDescription, XA_STRING, 8, "", 0);
auto dndVersion = XWindowSystemUtilities::Atoms::DndVersion;
xchangeProperty (windowH, atoms->XdndAware, XA_ATOM, 32, &dndVersion, 1);
xchangeProperty (windowH, atoms.XdndAware, XA_ATOM, 32, &dndVersion, 1);
unsigned long info[2] = { 0, 1 };
xchangeProperty (windowH, atoms->XembedInfo, atoms->XembedInfo, 32, (unsigned char*) info, 2);
xchangeProperty (windowH, atoms.XembedInfo, atoms.XembedInfo, 32, (unsigned char*) info, 2);
return windowH;
}
@@ -1360,7 +1367,12 @@ static int getAllEventsMask (bool ignoresMouseClicks)
void XWindowSystem::destroyWindow (::Window windowH)
{
auto* peer = dynamic_cast<LinuxComponentPeer<::Window>*> (getPeerFor (windowH));
jassert (peer != nullptr);
if (peer == nullptr)
{
jassertfalse;
return;
}
#if JUCE_X11_SUPPORTS_XEMBED
juce_handleXEmbedEvent (peer, nullptr);
@@ -1480,7 +1492,7 @@ void XWindowSystem::setBounds (::Window windowH, Rectangle<int> newBounds, bool
clientMsg.window = windowH;
clientMsg.type = ClientMessage;
clientMsg.format = 32;
clientMsg.message_type = atoms->windowState;
clientMsg.message_type = atoms.windowState;
clientMsg.data.l[0] = 0; // Remove
clientMsg.data.l[1] = (long) fs;
clientMsg.data.l[2] = 0;
@@ -1613,7 +1625,7 @@ void XWindowSystem::setMinimised (::Window windowH, bool shouldBeMinimised) cons
clientMsg.window = windowH;
clientMsg.type = ClientMessage;
clientMsg.format = 32;
clientMsg.message_type = atoms->changeState;
clientMsg.message_type = atoms.changeState;
clientMsg.data.l[0] = IconicState;
XWindowSystemUtilities::ScopedXLock xLock;
@@ -1626,9 +1638,9 @@ bool XWindowSystem::isMinimised (::Window windowH) const
jassert (windowH != 0);
XWindowSystemUtilities::ScopedXLock xLock;
XWindowSystemUtilities::GetXProperty prop (windowH, atoms->state, 0, 64, false, atoms->state);
XWindowSystemUtilities::GetXProperty prop (windowH, atoms.state, 0, 64, false, atoms.state);
if (prop.success && prop.actualType == atoms->state
if (prop.success && prop.actualType == atoms.state
&& prop.actualFormat == 32 && prop.numItems > 0)
{
unsigned long state;
@@ -1649,7 +1661,7 @@ void XWindowSystem::toFront (::Window windowH, bool) const
ev.xclient.type = ClientMessage;
ev.xclient.serial = 0;
ev.xclient.send_event = True;
ev.xclient.message_type = atoms->activeWin;
ev.xclient.message_type = atoms.activeWin;
ev.xclient.window = windowH;
ev.xclient.format = 32;
ev.xclient.data.l[0] = 2;
@@ -2324,7 +2336,7 @@ void XWindowSystem::copyTextToClipboard (const String& clipText)
localClipboardContent = clipText;
X11Symbols::getInstance()->xSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime);
X11Symbols::getInstance()->xSetSelectionOwner (display, atoms->clipboard, juce_messageWindowHandle, CurrentTime);
X11Symbols::getInstance()->xSetSelectionOwner (display, atoms.clipboard, juce_messageWindowHandle, CurrentTime);
}
String XWindowSystem::getTextFromClipboard() const
@@ -2345,7 +2357,7 @@ String XWindowSystem::getTextFromClipboard() const
if ((selectionOwner = X11Symbols::getInstance()->xGetSelectionOwner (display, selection)) == None)
{
selection = atoms->clipboard;
selection = atoms.clipboard;
selectionOwner = X11Symbols::getInstance()->xGetSelectionOwner (display, selection);
}
@@ -2353,7 +2365,7 @@ String XWindowSystem::getTextFromClipboard() const
{
if (selectionOwner == juce_messageWindowHandle)
content = localClipboardContent;
else if (! ClipboardHelpers::requestSelectionContent (display, content, selection, atoms->utf8String))
else if (! ClipboardHelpers::requestSelectionContent (display, content, selection, atoms.utf8String))
ClipboardHelpers::requestSelectionContent (display, content, selection, XA_STRING);
}
@@ -2468,7 +2480,7 @@ void XWindowSystem::removeWindowDecorations (::Window windowH) const
if (hints != None)
{
XWindowSystemUtilities::ScopedXLock xLock;
xchangeProperty (windowH, atoms->windowType, XA_ATOM, 32, &hints, 1);
xchangeProperty (windowH, atoms.windowType, XA_ATOM, 32, &hints, 1);
}
}
@@ -2548,7 +2560,7 @@ void XWindowSystem::setWindowType (::Window windowH, int styleFlags) const
else
netHints [0] = XWindowSystemUtilities::Atoms::getIfExists (display, "_NET_WM_WINDOW_TYPE_NORMAL");
xchangeProperty (windowH, atoms->windowType, XA_ATOM, 32, &netHints, 1);
xchangeProperty (windowH, atoms.windowType, XA_ATOM, 32, &netHints, 1);
int numHints = 0;
@@ -2559,7 +2571,7 @@ void XWindowSystem::setWindowType (::Window windowH, int styleFlags) const
netHints [numHints++] = XWindowSystemUtilities::Atoms::getIfExists (display, "_NET_WM_STATE_ABOVE");
if (numHints > 0)
xchangeProperty (windowH, atoms->windowState, XA_ATOM, 32, &netHints, numHints);
xchangeProperty (windowH, atoms.windowState, XA_ATOM, 32, &netHints, numHints);
}
void XWindowSystem::initialisePointerMap()
@@ -2644,7 +2656,7 @@ long XWindowSystem::getUserTime (::Window windowH) const
{
jassert (windowH != 0);
XWindowSystemUtilities::GetXProperty prop (windowH, atoms->userTime, 0, 65536, false, XA_CARDINAL);
XWindowSystemUtilities::GetXProperty prop (windowH, atoms.userTime, 0, 65536, false, XA_CARDINAL);
if (! prop.success)
return 0;
@@ -2656,7 +2668,7 @@ long XWindowSystem::getUserTime (::Window windowH) const
}
//==============================================================================
void XWindowSystem::initialiseXDisplay()
bool XWindowSystem::initialiseXDisplay()
{
jassert (display == nullptr);
@@ -2675,12 +2687,9 @@ void XWindowSystem::initialiseXDisplay()
break;
}
// This is fatal! Print error and closedown
// No X Server running
if (display == nullptr)
{
Logger::outputDebugString ("Failed to connect to the X Server.");
Process::terminate();
}
return false;
// Create a context to store user data associated with Windows we create
windowHandleXContext = (XContext) X11Symbols::getInstance()->xrmUniqueQuark();
@@ -2698,7 +2707,7 @@ void XWindowSystem::initialiseXDisplay()
X11Symbols::getInstance()->xSync (display, False);
atoms = std::make_unique<XWindowSystemUtilities::Atoms> (display);
atoms = XWindowSystemUtilities::Atoms (display);
// Get defaults for various properties
auto root = X11Symbols::getInstance()->xRootWindow (display, screen);
@@ -2754,6 +2763,8 @@ void XWindowSystem::initialiseXDisplay()
} while (display != nullptr);
});
return true;
}
void XWindowSystem::destroyXDisplay()
@@ -3235,11 +3246,11 @@ void XWindowSystem::handleMappingNotify (XMappingEvent& mappingEvent) const
void XWindowSystem::handleClientMessageEvent (LinuxComponentPeer<::Window>* peer, XClientMessageEvent& clientMsg, XEvent& event) const
{
if (clientMsg.message_type == atoms->protocols && clientMsg.format == 32)
if (clientMsg.message_type == atoms.protocols && clientMsg.format == 32)
{
auto atom = (Atom) clientMsg.data.l[0];
if (atom == atoms->protocolList [XWindowSystemUtilities::Atoms::PING])
if (atom == atoms.protocolList [XWindowSystemUtilities::Atoms::PING])
{
auto root = X11Symbols::getInstance()->xRootWindow (display, X11Symbols::getInstance()->xDefaultScreen (display));
@@ -3248,7 +3259,7 @@ void XWindowSystem::handleClientMessageEvent (LinuxComponentPeer<::Window>* peer
X11Symbols::getInstance()->xSendEvent (display, root, False, NoEventMask, &event);
X11Symbols::getInstance()->xFlush (display);
}
else if (atom == atoms->protocolList [XWindowSystemUtilities::Atoms::TAKE_FOCUS])
else if (atom == atoms.protocolList [XWindowSystemUtilities::Atoms::TAKE_FOCUS])
{
if ((peer->getStyleFlags() & ComponentPeer::windowIgnoresKeyPresses) == 0)
{
@@ -3269,37 +3280,37 @@ void XWindowSystem::handleClientMessageEvent (LinuxComponentPeer<::Window>* peer
}
}
}
else if (atom == atoms->protocolList [XWindowSystemUtilities::Atoms::DELETE_WINDOW])
else if (atom == atoms.protocolList [XWindowSystemUtilities::Atoms::DELETE_WINDOW])
{
peer->handleUserClosingWindow();
}
}
else if (clientMsg.message_type == atoms->XdndEnter)
else if (clientMsg.message_type == atoms.XdndEnter)
{
dragAndDropStateMap[peer].handleDragAndDropEnter (clientMsg, peer);
}
else if (clientMsg.message_type == atoms->XdndLeave)
else if (clientMsg.message_type == atoms.XdndLeave)
{
dragAndDropStateMap[peer].handleDragAndDropExit();
dragAndDropStateMap.erase (peer);
}
else if (clientMsg.message_type == atoms->XdndPosition)
else if (clientMsg.message_type == atoms.XdndPosition)
{
dragAndDropStateMap[peer].handleDragAndDropPosition (clientMsg, peer);
}
else if (clientMsg.message_type == atoms->XdndDrop)
else if (clientMsg.message_type == atoms.XdndDrop)
{
dragAndDropStateMap[peer].handleDragAndDropDrop (clientMsg, peer);
}
else if (clientMsg.message_type == atoms->XdndStatus)
else if (clientMsg.message_type == atoms.XdndStatus)
{
dragAndDropStateMap[peer].handleExternalDragAndDropStatus (clientMsg);
}
else if (clientMsg.message_type == atoms->XdndFinished)
else if (clientMsg.message_type == atoms.XdndFinished)
{
dragAndDropStateMap[peer].externalResetDragAndDrop();
}
else if (clientMsg.message_type == atoms->XembedMsgType && clientMsg.format == 32)
else if (clientMsg.message_type == atoms.XembedMsgType && clientMsg.format == 32)
{
handleXEmbedMessage (peer, clientMsg);
}


+ 5
- 4
modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h View File

@@ -67,7 +67,8 @@ namespace XWindowSystemUtilities
PING = 2
};
Atoms (::Display*);
Atoms() = default;
explicit Atoms (::Display*);
static Atom getIfExists (::Display*, const char* name);
static Atom getCreating (::Display*, const char* name);
@@ -150,7 +151,7 @@ public:
String getLocalClipboardContent() const { return localClipboardContent; }
::Display* getDisplay() { return display; }
XWindowSystemUtilities::Atoms& getAtoms() { jassert (atoms.get() != nullptr); return *atoms; }
XWindowSystemUtilities::Atoms& getAtoms() { return atoms; }
//==============================================================================
void handleWindowMessage (LinuxComponentPeer<::Window>* peer, XEvent& event) const;
@@ -163,7 +164,7 @@ private:
~XWindowSystem();
//==============================================================================
void initialiseXDisplay();
bool initialiseXDisplay();
void destroyXDisplay();
//==============================================================================
@@ -207,7 +208,7 @@ private:
//==============================================================================
bool xIsAvailable = false;
std::unique_ptr<XWindowSystemUtilities::Atoms> atoms;
XWindowSystemUtilities::Atoms atoms;
::Display* display = nullptr;
Colormap colormap = {};
Visual* visual = nullptr;


+ 8
- 6
modules/juce_gui_extra/native/juce_linux_X11_SystemTrayIcon.cpp View File

@@ -73,12 +73,14 @@ public:
32, PropModeReplace, (unsigned char*) &windowH, 1);
// A minimum size must be specified for GNOME and Xfce, otherwise the icon is displayed with a width of 1
auto* hints = X11Symbols::getInstance()->xAllocSizeHints();
hints->flags = PMinSize;
hints->min_width = 22;
hints->min_height = 22;
X11Symbols::getInstance()->xSetWMNormalHints (display, windowH, hints);
X11Symbols::getInstance()->xFree (hints);
if (auto* hints = X11Symbols::getInstance()->xAllocSizeHints())
{
hints->flags = PMinSize;
hints->min_width = 22;
hints->min_height = 22;
X11Symbols::getInstance()->xSetWMNormalHints (display, windowH, hints);
X11Symbols::getInstance()->xFree (hints);
}
}
Image image;


+ 1
- 1
modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp View File

@@ -24,7 +24,7 @@ class WebKitSymbols : public DeletedAtShutdown
{
public:
//==============================================================================
bool isWebKitAvailable() { return webKitIsAvailable; }
bool isWebKitAvailable() const noexcept { return webKitIsAvailable; }
//==============================================================================
JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_settings_new, juce_webkit_settings_new,


Loading…
Cancel
Save