From 3d516079eb4d535326dbf6752088d5dfeb46ed31 Mon Sep 17 00:00:00 2001 From: thoughtjigs Date: Sun, 17 Jun 2018 01:41:07 -0700 Subject: [PATCH] Provide Xorg/net wm process ID (#7445) Adding support for _NET_WM_PID as defined in Extended Window Manager Hints Move verbose messaging to setupXorgTopLevelWindow method as Xorg messages should only occur when running in Xorg env. Irrlicht returns the XDisplay as a void* and XWindow as an unsigned long so reinterpret those as the appropriate type. Also fixed a spaces for tab formating issue --- src/client/clientlauncher.cpp | 8 +-- src/client/renderingengine.cpp | 111 ++++++++++++++++++++++++++++++--- src/client/renderingengine.h | 4 +- 3 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 051e4c242..85063ff86 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -96,15 +96,13 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) return true; } - video::IVideoDriver *video_driver = RenderingEngine::get_video_driver(); - if (video_driver == NULL) { + if (RenderingEngine::get_video_driver() == NULL) { errorstream << "Could not initialize video driver." << std::endl; return false; } - RenderingEngine::setXorgClassHint(video_driver->getExposedVideoData(), PROJECT_NAME_C); - RenderingEngine::get_instance()->setWindowIcon(); - + RenderingEngine::get_instance()->setupTopLevelWindow(PROJECT_NAME_C); + /* This changes the minimum allowed number of vertices in a VBO. Default is 500. diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index 72c1ccfbd..82d1411d6 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifdef XORG_USED #include #include +#include #endif #ifdef __ANDROID__ @@ -186,23 +187,119 @@ bool RenderingEngine::print_video_modes() return videomode_list != NULL; } -void RenderingEngine::setXorgClassHint( - const video::SExposedVideoData &video_data, const std::string &name) +bool RenderingEngine::setupTopLevelWindow(const std::string &name) +{ + // FIXME: It would make more sense for there to be a switch of some + // sort here that would call the correct toplevel setup methods for + // the environment Minetest is running in but for now not deviating + // from the original pattern. + + /* Setting Xorg properties for the top level window */ + setupTopLevelXorgWindow(name); + /* Done with Xorg properties */ + + /* Setting general properties for the top level window */ + verbosestream << "Client: Configuring general top level" + << " window properties" + << std::endl; + + bool result = setWindowIcon(); + + verbosestream << "Client: Finished configuring general top level" + << " window properties" + << std::endl; + /* Done with general properties */ + + // FIXME: setWindowIcon returns a bool result but it is unused. + // For now continue to return this result. + return result; +} + +void RenderingEngine::setupTopLevelXorgWindow(const std::string &name) { #ifdef XORG_USED - if (video_data.OpenGLLinux.X11Display == NULL) + const video::SExposedVideoData exposedData = driver->getExposedVideoData(); + + Display *x11_dpl = reinterpret_cast(exposedData.OpenGLLinux.X11Display); + if (x11_dpl == NULL) { + warningstream << "Client: Could not find X11 Display in ExposedVideoData" + << std::endl; return; + } + + verbosestream << "Client: Configuring Xorg specific top level" + << " window properties" + << std::endl; + + Window x11_win = reinterpret_cast(exposedData.OpenGLLinux.X11Window); + + // Set application name and class hints. For now name and class are the same. XClassHint *classhint = XAllocClassHint(); - classhint->res_name = (char *)name.c_str(); - classhint->res_class = (char *)name.c_str(); + classhint->res_name = const_cast(name.c_str()); + classhint->res_class = const_cast(name.c_str()); - XSetClassHint((Display *)video_data.OpenGLLinux.X11Display, - video_data.OpenGLLinux.X11Window, classhint); + XSetClassHint(x11_dpl, x11_win, classhint); XFree(classhint); + + // FIXME: In the future WMNormalHints should be set ... e.g see the + // gtk/gdk code (gdk/x11/gdksurface-x11.c) for the setup_top_level + // method. But for now (as it would require some significant changes) + // leave the code as is. + + // The following is borrowed from the above gdk source for setting top + // level windows. The source indicates and the Xlib docs suggest that + // this will set the WM_CLIENT_MACHINE and WM_LOCAL_NAME. This will not + // set the WM_CLIENT_MACHINE to a Fully Qualified Domain Name (FQDN) which is + // required by the Extended Window Manager Hints (EWMH) spec when setting + // the _NET_WM_PID (see further down) but running Minetest in an env + // where the window manager is on another machine from Minetest (therefore + // making the PID useless) is not expected to be a problem. Further + // more, using gtk/gdk as the model it would seem that not using a FQDN is + // not an issue for modern Xorg window managers. + + verbosestream << "Client: Setting Xorg window manager Properties" + << std::endl; + + XSetWMProperties (x11_dpl, x11_win, NULL, NULL, NULL, 0, NULL, NULL, NULL); + + // Set the _NET_WM_PID window property according to the EWMH spec. _NET_WM_PID + // (in conjunction with WM_CLIENT_MACHINE) can be used by window managers to + // force a shutdown of an application if it doesn't respond to the destroy + // window message. + + verbosestream << "Client: Setting Xorg _NET_WM_PID extened window manager property" + << std::endl; + + Atom NET_WM_PID = XInternAtom(x11_dpl, "_NET_WM_PID", false); + + pid_t pid = getpid(); + infostream << "Client: PID is '" << static_cast(pid) << "'" + << std::endl; + + XChangeProperty(x11_dpl, x11_win, NET_WM_PID, + XA_CARDINAL, 32, PropModeReplace, + reinterpret_cast(&pid),1); + + // Set the WM_CLIENT_LEADER window property here. Minetest has only one + // window and that window will always be the leader. + + verbosestream << "Client: Setting Xorg WM_CLIENT_LEADER property" + << std::endl; + + Atom WM_CLIENT_LEADER = XInternAtom(x11_dpl, "WM_CLIENT_LEADER", false); + + XChangeProperty (x11_dpl, x11_win, WM_CLIENT_LEADER, + XA_WINDOW, 32, PropModeReplace, + reinterpret_cast(&x11_win), 1); + + verbosestream << "Client: Finished configuring Xorg specific top level" + << " window properties" + << std::endl; #endif } + bool RenderingEngine::setWindowIcon() { #if defined(XORG_USED) diff --git a/src/client/renderingengine.h b/src/client/renderingengine.h index 8728363d2..34cc60630 100644 --- a/src/client/renderingengine.h +++ b/src/client/renderingengine.h @@ -51,8 +51,8 @@ public: static float getDisplayDensity(); static v2u32 getDisplaySize(); - static void setXorgClassHint(const video::SExposedVideoData &video_data, - const std::string &name); + bool setupTopLevelWindow(const std::string &name); + void setupTopLevelXorgWindow(const std::string &name); bool setWindowIcon(); bool setXorgWindowIconFromPath(const std::string &icon_file); static bool print_video_modes(); -- 2.25.1