Bring the window of an existing instance to front

This commit is contained in:
Zane U. Ji 2013-12-20 20:39:04 +08:00
parent bdd030850e
commit f8c21cb846
9 changed files with 306 additions and 87 deletions

View File

@ -222,6 +222,8 @@ ENCHANT_LIBS = @ENCHANT_LIBS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
GTK_CFLAGS = @GTK_CFLAGS@
GTK_LIBS = @GTK_LIBS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@

95
configure vendored
View File

@ -633,6 +633,8 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
GTK_LIBS
GTK_CFLAGS
ASPELL_LIBS
ENCHANT_LIBS
ENCHANT_CFLAGS
@ -791,7 +793,9 @@ PKG_CONFIG
PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
ENCHANT_CFLAGS
ENCHANT_LIBS'
ENCHANT_LIBS
GTK_CFLAGS
GTK_LIBS'
# Initialize some variables set by options.
@ -1455,6 +1459,8 @@ Some influential environment variables:
C compiler flags for ENCHANT, overriding pkg-config
ENCHANT_LIBS
linker flags for ENCHANT, overriding pkg-config
GTK_CFLAGS C compiler flags for GTK, overriding pkg-config
GTK_LIBS linker flags for GTK, overriding pkg-config
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@ -15561,6 +15567,86 @@ fi
# Check gtk
# This has to match the one wxWidgets linked with
# It is needed to make single-instance-check work
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5
$as_echo_n "checking for GTK... " >&6; }
if test -n "$GTK_CFLAGS"; then
pkg_cv_GTK_CFLAGS="$GTK_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0\""; } >&5
($PKG_CONFIG --exists --print-errors "gtk+-2.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$GTK_LIBS"; then
pkg_cv_GTK_LIBS="$GTK_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0\""; } >&5
($PKG_CONFIG --exists --print-errors "gtk+-2.0") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-2.0" 2>&1`
else
GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-2.0" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$GTK_PKG_ERRORS" >&5
CXXFLAGS="$CXXFLAGS -D__NO_GTK__"
#[PKG_CHECK_MODULES(GTK, [gtk+-3.0], [AC_MSG_RESULT([gtk+-3.0])])]
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CXXFLAGS="$CXXFLAGS -D__NO_GTK__"
#[PKG_CHECK_MODULES(GTK, [gtk+-3.0], [AC_MSG_RESULT([gtk+-3.0])])]
else
GTK_CFLAGS=$pkg_cv_GTK_CFLAGS
GTK_LIBS=$pkg_cv_GTK_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: gtk+-2.0" >&5
$as_echo "gtk+-2.0" >&6; }
fi
ac_config_files="$ac_config_files Makefile src/Makefile"
cat >confcache <<\_ACEOF
@ -18050,8 +18136,11 @@ echo "***************************************"
echo
if [ "$debugbuild" = "y" ]; then
echo "Debug Enabled"
echo "Debug Enabled"
else
echo "Debug Disabled"
echo "Debug Disabled"
fi
if [ "$GTK_LIBS" = "" ]; then
echo "GTK No. There will be problems when single instance is enabled."
fi

View File

@ -138,6 +138,14 @@ PKG_CHECK_MODULES(ENCHANT, [enchant], [CXXFLAGS="$CXXFLAGS -DUSE_ENCHANT"],
AC_SUBST(ASPELL_LIBS)
# Check gtk
# This has to match the one wxWidgets linked with
# It is needed to make single-instance-check work
PKG_CHECK_MODULES(GTK, [gtk+-2.0], [AC_MSG_RESULT([gtk+-2.0])],
[CXXFLAGS="$CXXFLAGS -D__NO_GTK__"]
#[PKG_CHECK_MODULES(GTK, [gtk+-3.0], [AC_MSG_RESULT([gtk+-3.0])])]
)
AC_OUTPUT(Makefile src/Makefile)
dnl Summarized output
@ -146,8 +154,11 @@ echo "***************************************"
echo
if [[ "$debugbuild" = "y" ]]; then
echo "Debug Enabled"
echo "Debug Enabled"
else
echo "Debug Disabled"
echo "Debug Disabled"
fi
if [[ "$GTK_LIBS" = "" ]]; then
echo "GTK No. There will be problems when single instance is enabled."
fi

View File

@ -33,7 +33,7 @@ xmlcopyeditor_SOURCES = xmlcopyeditor.cpp associatedialog.cpp casehandler.cpp \
xmlcopyeditor.desktop
xmlcopyeditor_LDFLAGS = $(WX_LIBS) \
-lexpat -lxslt -lxml2 -lpcre -lxerces-c $(ASPELL_LIBS) $(ENCHANT_LIBS)
-lexpat -lxslt -lxml2 -lpcre -lxerces-c $(ASPELL_LIBS) $(ENCHANT_LIBS) $(GTK_LIBS)
nobase_dist_xmlcopyeditor_DATA = $(srcdir)/catalog/catalog \
$(srcdir)/copying/*.txt \
@ -82,5 +82,5 @@ pixmap_DATA = xmlcopyeditor.png
applications_DATA = xmlcopyeditor.desktop
AM_CPPFLAGS = -I/usr/include/libxml2 $(ENCHANT_CFLAGS)
AM_CPPFLAGS = -I/usr/include/libxml2 $(ENCHANT_CFLAGS) $(GTK_CFLAGS)

View File

@ -258,6 +258,8 @@ ENCHANT_LIBS = @ENCHANT_LIBS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
GTK_CFLAGS = @GTK_CFLAGS@
GTK_LIBS = @GTK_LIBS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@ -379,7 +381,7 @@ xmlcopyeditor_SOURCES = xmlcopyeditor.cpp associatedialog.cpp casehandler.cpp \
xmlcopyeditor.desktop
xmlcopyeditor_LDFLAGS = $(WX_LIBS) \
-lexpat -lxslt -lxml2 -lpcre -lxerces-c $(ASPELL_LIBS) $(ENCHANT_LIBS)
-lexpat -lxslt -lxml2 -lpcre -lxerces-c $(ASPELL_LIBS) $(ENCHANT_LIBS) $(GTK_LIBS)
nobase_dist_xmlcopyeditor_DATA = $(srcdir)/catalog/catalog \
$(srcdir)/copying/*.txt \
@ -426,7 +428,7 @@ nobase_dist_xmlcopyeditor_DATA = $(srcdir)/catalog/catalog \
pixmap_DATA = xmlcopyeditor.png
applications_DATA = xmlcopyeditor.desktop
AM_CPPFLAGS = -I/usr/include/libxml2 $(ENCHANT_CFLAGS)
AM_CPPFLAGS = -I/usr/include/libxml2 $(ENCHANT_CFLAGS) $(GTK_CFLAGS)
all: all-am
.SUFFIXES:
@ -440,9 +442,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu src/Makefile
$(AUTOMAKE) --foreign src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \

View File

@ -19,6 +19,17 @@
#include "myipc.h"
#include "xmlcopyeditor.h"
#include "pathresolver.h"
#if defined ( __WXGTK__ ) && !defined ( __NO_GTK__ )
#include <gtk/gtk.h>
guint32 XTimeNow()
{
struct timespec ts;
clock_gettime ( CLOCK_MONOTONIC, &ts );
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}
#endif // __WXGTK__
MyServerConnection *server_connection = 0;
MyClientConnection *client_connection = 0;
@ -32,7 +43,9 @@ wxConnectionBase *MyServer::OnAcceptConnection ( const wxString& topic )
return NULL;
}
MyServerConnection::MyServerConnection() : wxConnection()
MyServerConnection::MyServerConnection()
: wxConnection()
, mFrameWnd ( ( wxIntPtr ) NULL )
{
server_connection = this;
}
@ -48,13 +61,8 @@ MyServerConnection::~MyServerConnection()
bool MyServerConnection::OnPoke (
const wxString& WXUNUSED ( topic )
, const wxString& item
#if wxCHECK_VERSION(2,9,0)
, const void *data
, size_t size
#else
, wxChar *data
, int size
#endif
, IPCData *data
, IPCSize_t size
, wxIPCFormat WXUNUSED ( format )
)
{
@ -78,10 +86,63 @@ bool MyServerConnection::OnPoke (
frame->openFile ( ( wxString& ) item );
//frame->addToFileQueue ( ( wxString& ) item ); // prevent event loop problems
}
#ifndef __WXMSW__
#if defined ( __WXGTK__ ) && !defined ( __NO_GTK__ )
// Processes mostly cannot raise theire own windows.
// http://osdir.com/ml/gnome.gaim.devel/2004-12/msg00077.html
GtkWidget *widget = frame->GetHandle();
GdkWindow *window = gtk_widget_get_window ( widget );
gdk_x11_window_set_user_time ( window,
//XTimeNow() ); // This works too.
gdk_x11_get_server_time ( window ) );
//gdk_window_show ( window );
//gdk_window_raise ( window );
//gtk_window_present ( GTK_WINDOW ( widget ) );
#endif // __WXGTK__ && !__NO_GTK__
frame->Show();
frame->Raise();
#endif // __WXMSW__
return true;
}
IPCData *MyServerConnection::OnRequest
( const wxString& WXUNUSED ( topic )
, const wxString& item
, IPCSize_t *size
, wxIPCFormat WXUNUSED ( format ) /*= wxIPC_PRIVATE */
)
{
if ( size == NULL )
return NULL;
if ( item == IPC_FRAME_WND )
{
if ( !mFrameWnd )
{
wxWindow *window = wxTheApp->GetTopWindow();
if ( window )
{
#if defined ( __WXGTK__ ) && !defined ( __NO_GTK__ )
GtkWidget *wnd = window->GetHandle();
if ( wnd )
{
GdkWindow *gwnd = gtk_widget_get_window ( wnd );
if ( gwnd )
mFrameWnd = GDK_WINDOW_XID ( gwnd );
}
#else
mFrameWnd = window->GetHandle();
#endif
}
}
*size = sizeof mFrameWnd;
return ( IPCData * ) &mFrameWnd;
}
*size = 0;
return NULL;
}
bool MyServerConnection::OnStartAdvise ( const wxString& WXUNUSED ( topic ),
const wxString& WXUNUSED ( item ) )
{
@ -89,7 +150,8 @@ bool MyServerConnection::OnStartAdvise ( const wxString& WXUNUSED ( topic ),
}
MyClientConnection::MyClientConnection()
{}
{
}
wxConnectionBase *MyClient::OnMakeConnection()
{
@ -99,13 +161,8 @@ wxConnectionBase *MyClient::OnMakeConnection()
bool MyClientConnection::OnAdvise (
const wxString& WXUNUSED ( topic )
, const wxString& WXUNUSED ( item )
#if wxCHECK_VERSION(2,9,0)
, const void * WXUNUSED ( data )
, size_t WXUNUSED ( size )
#else
, wxChar * WXUNUSED ( data )
, int WXUNUSED ( size )
#endif
, IPCData * WXUNUSED ( data )
, IPCSize_t WXUNUSED ( size )
, wxIPCFormat WXUNUSED ( format )
)
{
@ -119,7 +176,74 @@ bool MyClientConnection::OnDisconnect()
}
MyServer::MyServer()
{ }
{
}
MyClient::MyClient()
{ }
{
}
bool MyClient::talkToServer ( int argc, const wxChar * const *argv )
{
MyClientConnection *connection = ( MyClientConnection * )
MakeConnection ( _T ( "localhost" ), IPC_SERVICE, IPC_TOPIC );
if ( !connection || !connection->StartAdvise ( IPC_ADVISE_NAME ) )
return false;
wxString argument;
// wxConnectionBase::Poke expects something other than NULL in debug
// version
#ifdef __WXDEBUG__
static wxChar whatBuffer[] = _T ( "Data" );
#else
static wxChar whatBuffer[0];
#endif
if ( argc <= 1 )
{
connection->Poke ( IPC_NO_FILE, whatBuffer );
}
else for ( int i = 1; i < argc; i++ )
{
argument = argv[i];
argument = PathResolver::run ( argument );
if ( ! connection->Poke ( argument, whatBuffer ) )
break;
}
// Bring the window to front
IPCSize_t size;
const void *data = connection->Request ( IPC_FRAME_WND, &size );
if ( !data )
return false;
#ifdef __WXMSW__
if ( size == sizeof ( HWND ) )
{
HWND hwnd = * ( const HWND * )data;
if ( ::IsIconic ( hwnd ) )
::ShowWindow ( hwnd, SW_RESTORE );
else
::SetForegroundWindow ( hwnd );
}
#elif defined ( __WXGTK__x ) // It doesn't work
if ( size == sizeof ( GdkNativeWindow ) )
{
GdkNativeWindow xWnd = * ( GdkNativeWindow * ) data;
GdkWindow *window = gdk_window_foreign_new ( xWnd );
if ( window )
{
gdk_x11_window_set_user_time ( window,
XTimeNow() );
//gdk_x11_get_server_time ( window ) );
gdk_window_show ( window );
gdk_window_raise ( window );
gdk_window_unref ( window );
//GtkWidget *widget;
//gdk_window_get_user_data(window, (void**)&widget);
//printf ("widget: %p\n",widget);
//gtk_window_present ( GTK_WINDOW ( widget ) );
}
}
#endif // __WXMSW__
return true;
}

View File

@ -25,11 +25,30 @@
#include <wx/wx.h>
#include <wx/ipc.h>
#if defined ( __WXGTK__ ) && !defined ( __NO_GTK__ )
#if wxCHECK_VERSION(2,9,0) // GSocket is defined in wxWidgets 2.8
#include <gdk/gdkx.h>
#else // wxCHECK_VERSION(2,9,0)
#define GSocket GlibGSocket
#include <gdk/gdkx.h>
#undef GSocket
#endif // wxCHECK_VERSION(2,9,0)
#endif // __WXGTK__ && !__NO_GTK__
#define IPC_SERVICE _T("4242")
#define IPC_TOPIC _T("IPC TEST")
#define IPC_ADVISE_NAME _T("Item")
#define IPC_FRAME_WND _T("FrameWnd")
#define IPC_NO_FILE _T("[nofile]")
#if wxCHECK_VERSION(2,9,0)
typedef const void IPCData;
typedef size_t IPCSize_t;
#else
typedef wxChar IPCData;
typedef int IPCSize_t;
#endif
class MyServerConnection;
class MyClientConnection;
extern MyServerConnection *server_connection;
@ -42,16 +61,20 @@ class MyServerConnection : public wxConnection
~MyServerConnection();
bool OnPoke ( const wxString& topic
, const wxString& item
#if wxCHECK_VERSION(2,9,0)
, const void *data
, size_t size
#else
, wxChar *data
, int size
#endif
, IPCData *data
, IPCSize_t size
, wxIPCFormat format
);
bool OnStartAdvise ( const wxString& topic, const wxString& item );
IPCData *OnRequest(const wxString& topic, const wxString& item,
IPCSize_t *size, wxIPCFormat format = wxIPC_PRIVATE );
protected:
#if defined ( __WXGTK__ ) && !defined ( __NO_GTK__ )
GdkNativeWindow mFrameWnd;
#else
WXWidget mFrameWnd;
#endif
};
class MyClientConnection: public wxConnection
@ -60,13 +83,8 @@ class MyClientConnection: public wxConnection
MyClientConnection();
bool OnAdvise ( const wxString& topic
, const wxString& item
#if wxCHECK_VERSION(2,9,0)
, const void *data
, size_t size
#else
, wxChar *data
, int size
#endif
, IPCData *data
, IPCSize_t size
, wxIPCFormat format );
bool OnDisconnect();
};
@ -76,6 +94,7 @@ class MyClient: public wxClient
public:
MyClient();
wxConnectionBase *OnMakeConnection();
bool talkToServer ( int argc, const wxChar * const *argv );
};
class MyServer: public wxServer
@ -86,3 +105,4 @@ class MyServer: public wxServer
};
#endif

View File

@ -64,6 +64,7 @@
#include "threadreaper.h"
#include <wx/wupdlock.h>
#include "dtd2schema.h"
#include "myipc.h"
#define ngettext wxGetTranslation
@ -304,68 +305,37 @@ bool MyApp::OnInit()
break;
}
#ifdef __WXMSW__
singleInstanceCheck = true;
#else
singleInstanceCheck = false;
#endif
if ( config.get() )
{
#ifdef __WXMSW__
singleInstanceCheck = config->Read ( _T ( "singleInstanceCheck" ), true );
#else
long longFalse = 0;
singleInstanceCheck = config->Read ( _T ( "singleInstanceCheck" ), longFalse );
#endif
singleInstanceCheck = config->Read ( _T ( "singleInstanceCheck" ),
singleInstanceCheck );
lang = config->Read ( _T ( "lang" ), systemLocale );
}
else
{
lang = systemLocale;
#ifdef __WXMSW__
singleInstanceCheck = true;
#else
singleInstanceCheck = false;
#endif
}
wxString name, service, hostName;
name.Printf ( _T ( "xmlcopyeditor-%s" ), wxGetUserId().c_str() );
service = IPC_SERVICE;
hostName = _T ( "localhost" );
if ( singleInstanceCheck )
{
wxString name;
name.Printf ( _T ( "xmlcopyeditor-%s" ), wxGetUserId().c_str() );
checker = new wxSingleInstanceChecker ( name );
while ( checker->IsAnotherRunning() )
if ( checker->IsAnotherRunning() )
{
// attempt calling server
MyClient client;
MyClientConnection *connection = ( MyClientConnection * )
client.MakeConnection ( hostName, service, IPC_TOPIC );
if ( !connection || !connection->StartAdvise ( IPC_ADVISE_NAME ) )
break;
else
{
wxString argument;
wxChar whatBuffer[] = _T ( "Data" );
if ( this->argc > 1 )
{
for ( int i = 1; i < this->argc; i++ )
{
argument = ( wxString ) this->argv[i];
argument = PathResolver::run ( argument );
if ( ! connection->Poke ( argument, whatBuffer ) )
break;
}
}
else
{
argument = ( wxString ) IPC_NO_FILE;
connection->Poke ( argument, whatBuffer );
}
if ( client.talkToServer ( argc, argv ) )
return false;
}
}
}
server = new MyServer;
server->Create ( service );
server->Create ( IPC_SERVICE );
myLocale.Init ( lang, wxLOCALE_LOAD_DEFAULT );

View File

@ -52,7 +52,6 @@
#include "xmldoc.h"
#include "myhtmlpane.h"
#include "xmlencodinghandler.h"
#include "myipc.h"
#include <wx/aui/framemanager.h>
enum
@ -167,6 +166,8 @@ enum
CONST_QUESTION
};
class MyServer;
class MyApp : public wxApp
{
public: