modules/jdk.packager/src/main/native/library/common/LinuxPlatform.cpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates.
  * All rights reserved. Use is subject to license terms.
  *
  * This file is available and licensed under the following license:
  *
  * Redistribution and use in source and binary forms, with or without

@@ -40,10 +40,18 @@
 #include "PlatformString.h"
 
 
 #include <stdlib.h>
 #include <pwd.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#define LINUX_PACKAGER_TMP_DIR "/.java/packager/tmp"
 
 
 TString GetEnv(const TString &name) {
     TString result;
 

@@ -193,10 +201,25 @@
 bool LinuxPlatform::IsMainThread() {
     bool result = (FMainThread == pthread_self());
     return result;
 }
 
+const char* LinuxPlatform::getTmpDirString() {
+    return LINUX_PACKAGER_TMP_DIR;
+}
+
+void LinuxPlatform::reactivateAnotherInstance() {
+    if (singleInstanceProcessId == 0) {
+        printf("Unable to reactivate another instance, PID is undefined");
+        return;
+    } 
+    Display* dsp = XOpenDisplay(NULL);
+    ProcessReactivator processReactivator(dsp, singleInstanceProcessId);
+    processReactivator.reactivateProcess();
+    XCloseDisplay(dsp);
+}
+
 TPlatformNumber LinuxPlatform::GetMemorySize() {
     long pages = sysconf(_SC_PHYS_PAGES);
     long page_size = sysconf(_SC_PAGE_SIZE);
     TPlatformNumber result = pages * page_size;
     result = result / 1048576; // Convert from bytes to megabytes.

@@ -1101,8 +1124,70 @@
     }
 
     return result;
 }
 
+ProcessReactivator::ProcessReactivator(Display* display, pid_t pid):
+   _pid(pid), _display(display) {
+
+   _atomPid = XInternAtom(display, "_NET_WM_PID", True);
+
+   if (_atomPid == None) {
+       return;
+   }
+   searchWindowHelper(XDefaultRootWindow(display));
+}
+
+void ProcessReactivator::searchWindowHelper(Window w) {
+    Atom type;
+    int format;
+    unsigned long  num, bytesAfter;
+    unsigned char* propPid = 0;
+    if (Success == XGetWindowProperty(_display, w, _atomPid, 0, 1, False, XA_CARDINAL,
+                                     &type, &format, &num, &bytesAfter, &propPid)) {
+        if (propPid != 0) {
+            if (_pid == *((pid_t *)propPid)) {
+                _result.push_back(w);
+            }
+            XFree(propPid);
+        }
+    }
+
+    Window root, parent;
+    Window* child;
+    unsigned int numChildren;
+    if (0 != XQueryTree(_display, w, &root, &parent, &child, &numChildren)) {
+        for (unsigned int i = 0; i < numChildren; i++) {
+            searchWindowHelper(child[i]);
+        }
+    }
+}
+
+void ProcessReactivator::reactivateProcess() {
+    for (std::list<Window>::const_iterator it = _result.begin(); it != _result.end(); it++) {
+        // try sending an event to activate window,
+        // after that we can try to raise it.
+        XEvent xev;
+        Atom atom = XInternAtom (_display, "_NET_ACTIVE_WINDOW", False);
+        xev.xclient.type = ClientMessage;
+        xev.xclient.serial = 0;
+        xev.xclient.send_event = True;
+        xev.xclient.display = _display;
+        xev.xclient.window = *it;
+        xev.xclient.message_type = atom;
+        xev.xclient.format = 32;
+        xev.xclient.data.l[0] = 2;
+        xev.xclient.data.l[1] = 0;
+        xev.xclient.data.l[2] = 0;
+        xev.xclient.data.l[3] = 0;
+        xev.xclient.data.l[4] = 0;
+        XWindowAttributes attr;
+        XGetWindowAttributes(_display, *it, &attr);
+        XSendEvent(_display, attr.root, False,
+            SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+        XRaiseWindow(_display, *it);
+    }
+}
+
 //--------------------------------------------------------------------------------------------------
 
 #endif // LINUX