mirror of
https://github.com/itay-grudev/SingleApplication.git
synced 2024-11-15 12:15:43 +08:00
Primary PID support (#36)
* Added the ability to bring the primary application window to the foreground on Windows systems by adding an option flag. THis option can only be used in Windows development and in applications derived from QApplication with a QMainWindow object. Because the primary application needs to be instructed to go to the foreground, the option SecondaryNotification must also be set to use this functionality * Changed the ability to bring the primary application window to the front as discussed in itay-grudev/SingleApplication#31. Now the process ID of the primary application get stored and is accessible for other instances of the application. It is to the developer to bring the applications windows to the front. For convenience the accompanying readme now contains a paragraph with example of how to do this on Windows systems. * v3.0.9 Added SingleApplicationPrivate::primaryPid()
This commit is contained in:
parent
6fbf6bffc8
commit
4f03651072
@ -1,6 +1,15 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
__3.0.9__
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Added SingleApplicationPrivate::primaryPid() as a solution to allow
|
||||||
|
bringing the primary window of an application to the foreground on
|
||||||
|
Windows.
|
||||||
|
|
||||||
|
_Eelco van Dam from Peacs BV_
|
||||||
|
|
||||||
__3.0.8__
|
__3.0.8__
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
15
README.md
15
README.md
@ -80,6 +80,11 @@ Using `SingleApplication::instance()` is a neat way to get the
|
|||||||
`SingleApplication` instance for binding to it's signals anywhere in your
|
`SingleApplication` instance for binding to it's signals anywhere in your
|
||||||
program.
|
program.
|
||||||
|
|
||||||
|
__Note:__ On Windows the ability to bring the application windows to the
|
||||||
|
foreground is restricted. See [Windows specific implementations](Windows.md)
|
||||||
|
for a workaround and an example implementation.
|
||||||
|
|
||||||
|
|
||||||
Secondary Instances
|
Secondary Instances
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -177,7 +182,15 @@ Returns if the instance is a secondary instance.
|
|||||||
quint32 SingleApplication::instanceId()
|
quint32 SingleApplication::instanceId()
|
||||||
```
|
```
|
||||||
|
|
||||||
Returns a unique identifier for the current instance
|
Returns a unique identifier for the current instance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
qint64 SingleApplication::primaryPid()
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the process ID (PID) of the primary instance.
|
||||||
|
|
||||||
### Signals
|
### Signals
|
||||||
|
|
||||||
|
46
Windows.md
Normal file
46
Windows.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
Windows Specific Implementations
|
||||||
|
================================
|
||||||
|
|
||||||
|
Setting the foreground window
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
In the `instanceStarted()` example in the `README` we demonstrated how an
|
||||||
|
application can bring it's primary instance window whenever a second copy
|
||||||
|
of the application is started.
|
||||||
|
|
||||||
|
On Windows the ability to bring the application windows to the foreground is
|
||||||
|
restricted, see [`AllowSetForegroundWindow()`][AllowSetForegroundWindow] for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
The background process (the primary instance) can bring its windows to the
|
||||||
|
foreground if it is allowed by the current foreground process (the secondary
|
||||||
|
instance). To bypass this `SingleApplication` must be initialized with the
|
||||||
|
`allowSecondary` parameter set to `true` and the `options` parameter must
|
||||||
|
include `Mode::SecondaryNotification`, See `SingleApplication::Mode` for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
Here is an example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if( app.isSecondary() ) {
|
||||||
|
// This API requires LIBS += User32.lib to be added to the project
|
||||||
|
AllowSetForegroundWindow( DWORD( app.getPrimaryPid() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( app.isPrimary() ) {
|
||||||
|
QObject::connect(
|
||||||
|
&app,
|
||||||
|
&SingleApplication::instanceStarted,
|
||||||
|
this,
|
||||||
|
&App::instanceStarted
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void App::instanceStarted() {
|
||||||
|
QApplication::setActiveWindow( [window/widget to set to the foreground] );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[AllowSetForegroundWindow]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632668.aspx
|
@ -45,6 +45,7 @@
|
|||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
#include "singleapplication_p.h"
|
#include "singleapplication_p.h"
|
||||||
|
|
||||||
|
|
||||||
static const char NewInstance = 'N';
|
static const char NewInstance = 'N';
|
||||||
static const char SecondaryInstance = 'S';
|
static const char SecondaryInstance = 'S';
|
||||||
static const char Reconnect = 'R';
|
static const char Reconnect = 'R';
|
||||||
@ -61,14 +62,17 @@ SingleApplicationPrivate::~SingleApplicationPrivate()
|
|||||||
socket->close();
|
socket->close();
|
||||||
delete socket;
|
delete socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory->lock();
|
memory->lock();
|
||||||
InstancesInfo* inst = (InstancesInfo*)memory->data();
|
InstancesInfo* inst = (InstancesInfo*)memory->data();
|
||||||
if( server != nullptr ) {
|
if( server != nullptr ) {
|
||||||
server->close();
|
server->close();
|
||||||
delete server;
|
delete server;
|
||||||
inst->primary = false;
|
inst->primary = false;
|
||||||
|
inst->primaryPid = -1;
|
||||||
}
|
}
|
||||||
memory->unlock();
|
memory->unlock();
|
||||||
|
|
||||||
delete memory;
|
delete memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +132,8 @@ void SingleApplicationPrivate::genBlockServerName( int timeout )
|
|||||||
|
|
||||||
void SingleApplicationPrivate::startPrimary( bool resetMemory )
|
void SingleApplicationPrivate::startPrimary( bool resetMemory )
|
||||||
{
|
{
|
||||||
|
Q_Q(SingleApplication);
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
// Handle any further termination signals to ensure the
|
// Handle any further termination signals to ensure the
|
||||||
// QSharedMemory block is deleted even if the process crashes
|
// QSharedMemory block is deleted even if the process crashes
|
||||||
@ -158,13 +164,13 @@ void SingleApplicationPrivate::startPrimary( bool resetMemory )
|
|||||||
memory->lock();
|
memory->lock();
|
||||||
InstancesInfo* inst = (InstancesInfo*)memory->data();
|
InstancesInfo* inst = (InstancesInfo*)memory->data();
|
||||||
|
|
||||||
if( resetMemory ){
|
if( resetMemory ) {
|
||||||
inst->primary = true;
|
|
||||||
inst->secondary = 0;
|
inst->secondary = 0;
|
||||||
} else {
|
|
||||||
inst->primary = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inst->primary = true;
|
||||||
|
inst->primaryPid = q->applicationPid();
|
||||||
|
|
||||||
memory->unlock();
|
memory->unlock();
|
||||||
|
|
||||||
instanceNumber = 0;
|
instanceNumber = 0;
|
||||||
@ -217,6 +223,18 @@ void SingleApplicationPrivate::connectToPrimary( int msecs, char connectionType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint64 SingleApplicationPrivate::primaryPid()
|
||||||
|
{
|
||||||
|
qint64 pid;
|
||||||
|
|
||||||
|
memory->lock();
|
||||||
|
InstancesInfo* inst = (InstancesInfo*)memory->data();
|
||||||
|
pid = inst->primaryPid;
|
||||||
|
memory->unlock();
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
void SingleApplicationPrivate::crashHandler()
|
void SingleApplicationPrivate::crashHandler()
|
||||||
{
|
{
|
||||||
@ -433,6 +451,12 @@ quint32 SingleApplication::instanceId()
|
|||||||
return d->instanceNumber;
|
return d->instanceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint64 SingleApplication::primaryPid()
|
||||||
|
{
|
||||||
|
Q_D(SingleApplication);
|
||||||
|
return d->primaryPid();
|
||||||
|
}
|
||||||
|
|
||||||
bool SingleApplication::sendMessage( QByteArray message, int timeout )
|
bool SingleApplication::sendMessage( QByteArray message, int timeout )
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
Q_D(SingleApplication);
|
||||||
|
@ -102,10 +102,16 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a unique identifier for the current instance
|
* @brief Returns a unique identifier for the current instance
|
||||||
* @returns {int}
|
* @returns {qint32}
|
||||||
*/
|
*/
|
||||||
quint32 instanceId();
|
quint32 instanceId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the process ID (PID) of the primary instance
|
||||||
|
* @returns {qint64}
|
||||||
|
*/
|
||||||
|
qint64 primaryPid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends a message to the primary instance. Returns true on success.
|
* @brief Sends a message to the primary instance. Returns true on success.
|
||||||
* @param {int} timeout - Timeout for connecting
|
* @param {int} timeout - Timeout for connecting
|
||||||
|
@ -11,3 +11,8 @@ win32 {
|
|||||||
msvc:LIBS += Advapi32.lib
|
msvc:LIBS += Advapi32.lib
|
||||||
gcc:LIBS += -lAdvapi32
|
gcc:LIBS += -lAdvapi32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DISTFILES += \
|
||||||
|
$$PWD/README.md \
|
||||||
|
$$PWD/CHANGELOG.md \
|
||||||
|
$$PWD/Windows.md
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
struct InstancesInfo {
|
struct InstancesInfo {
|
||||||
bool primary;
|
bool primary;
|
||||||
quint32 secondary;
|
quint32 secondary;
|
||||||
|
qint64 primaryPid;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SingleApplicationPrivate : public QObject {
|
class SingleApplicationPrivate : public QObject {
|
||||||
@ -54,6 +55,7 @@ public:
|
|||||||
void startPrimary( bool resetMemory );
|
void startPrimary( bool resetMemory );
|
||||||
void startSecondary();
|
void startSecondary();
|
||||||
void connectToPrimary( int msecs, char connectionType );
|
void connectToPrimary( int msecs, char connectionType );
|
||||||
|
qint64 primaryPid();
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
void crashHandler();
|
void crashHandler();
|
||||||
|
Loading…
Reference in New Issue
Block a user