gedit r6626 - in trunk: . gedit gedit/smclient



Author: jessevdk
Date: Wed Nov 26 20:04:28 2008
New Revision: 6626
URL: http://svn.gnome.org/viewvc/gedit?rev=6626&view=rev

Log:
	* configure.ac:
	* gedit/Makefile.am:
	* gedit/gedit.c:
	* gedit/smclient/eggsmclient-win32.c:
	* gedit/smclient/eggsmclient-osx.c:
	* gedit/smclient/Makefile.am:

	Fixed some small things to make gedit compile on OS X.


Added:
   trunk/gedit/smclient/eggsmclient-osx.c
   trunk/gedit/smclient/eggsmclient-win32.c
Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/gedit/Makefile.am
   trunk/gedit/gedit.c
   trunk/gedit/smclient/Makefile.am

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Wed Nov 26 20:04:28 2008
@@ -45,7 +45,7 @@
 AC_SUBST(ACLOCAL_AMFLAGS, "$ACLOCAL_FLAGS -I m4")
 
 dnl check for win32 platform
-AC_MSG_CHECKING([for some Win32 platform])
+AC_MSG_CHECKING([for Win32 platform])
 case "$host" in
   *-*-mingw*|*-*-cygwin*)
     platform_win32=yes
@@ -57,6 +57,23 @@
 AC_MSG_RESULT([$platform_win32])
 AM_CONDITIONAL(PLATFORM_WIN32, test "$platform_win32" = "yes")
 
+dnl check for osx platform
+AC_MSG_CHECKING([for Mac OS X platform])
+case "$host" in
+  *-*-darwin*)
+    platform_osx=yes
+    ;;
+  *)
+    platform_osx=no
+    ;;
+esac
+AC_MSG_RESULT([$platform_osx])
+AM_CONDITIONAL(PLATFORM_OSX, test "$platform_osx" = "yes")
+
+if test "$platform_osx" = "yes"; then
+	AC_DEFINE([PLATFORM_OSX],[1],[Defined if platform is Mac OSX])
+fi
+
 dnl ===============================================================
 dnl Expanded dirs
 dnl ===============================================================
@@ -176,7 +193,6 @@
 dnl ================================================================
 
 PKG_CHECK_MODULES(GEDIT, [
-	sm >= 1.0.0
 	libxml-2.0 >= 2.5.0
 	glib-2.0 >= 2.13.0
 	gthread-2.0 >= 2.13.0
@@ -189,6 +205,19 @@
 AC_SUBST(GEDIT_LIBS)
 AC_SUBST(GEDIT_CFLAGS)
 
+if test "$platform_osx" = "no"; then
+	PKG_CHECK_MODULES(EGG_SMCLIENT, [
+		sm >= 1.0.0
+	])
+	SM_LIBS="${EGG_SMCLIENT_LIBS}"
+else
+	EGG_SMCLIENT_CFLAGS=
+	EGG_SM_CLIENT_LIBS=
+fi
+
+AC_SUBST(EGG_SMCLIENT_CFLAGS)
+AC_SUBST(EGG_SMCLIENT_LIBS)
+
 dnl ================================================================
 dnl GConf related settings
 dnl ================================================================

Modified: trunk/gedit/Makefile.am
==============================================================================
--- trunk/gedit/Makefile.am	(original)
+++ trunk/gedit/Makefile.am	Wed Nov 26 20:04:28 2008
@@ -23,15 +23,18 @@
 gedit_SOURCES = \
 	gedit.c
 
-gedit_LDADD = libgedit.la $(GEDIT_LIBS)
+gedit_LDADD = libgedit.la $(GEDIT_LIBS) $(EGG_SMCLIENT_LIBS)
  
 if PLATFORM_WIN32
 gedit_LDFLAGS = -Wl,--export-all-symbols -Wl,--out-implib,libgedit-$(GEDIT_API_VERSION).a
 else
-
 gedit_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
 endif
 
+if PLATFORM_OSX
+gedit_LDFLAGS += -framework Carbon
+endif
+
 libgedit_la_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
 
 libgedit_la_LIBADD = \

Modified: trunk/gedit/gedit.c
==============================================================================
--- trunk/gedit/gedit.c	(original)
+++ trunk/gedit/gedit.c	Wed Nov 26 20:04:28 2008
@@ -39,7 +39,10 @@
 
 #include <glib/gi18n.h>
 #include <glib/goption.h>
+
+#ifndef PLATFORM_OSX
 #include <gdk/gdkx.h>
+#endif
 
 #include "gedit-app.h"
 #include "gedit-commands.h"
@@ -325,11 +328,13 @@
 	if (!GTK_WIDGET_REALIZED (window))
 		gtk_widget_realize (GTK_WIDGET (window));
 
+#ifdef GDK_WINDOWING_X11
 	if (startup_timestamp <= 0)
 		startup_timestamp = gdk_x11_get_server_time (GTK_WIDGET (window)->window);
 
 	gdk_x11_window_set_user_time (GTK_WIDGET (window)->window,
 				      startup_timestamp);
+#endif
 
 	gtk_window_present (GTK_WINDOW (window));
 
@@ -526,7 +531,9 @@
 					   GEDIT_ICONDIR);
 
 	/* Set the associated .desktop file */
+#ifndef PLATFORM_OSX
 	egg_set_desktop_file (DATADIR "/applications/gedit.desktop");
+#endif
 
 	/* Load user preferences */
 	gedit_debug_message (DEBUG_APP, "Init prefs manager");

Modified: trunk/gedit/smclient/Makefile.am
==============================================================================
--- trunk/gedit/smclient/Makefile.am	(original)
+++ trunk/gedit/smclient/Makefile.am	Wed Nov 26 20:04:28 2008
@@ -1,23 +1,36 @@
+if PLATFORM_WIN32
+platform_sources = eggsmclient-win32.c
+platform_logout_test_ldflags = -mwindows
+else
+if PLATFORM_OSX
+platform_defines = -xobjective-c
+platform_ldflags = -framework Carbon
+platform_sources = eggsmclient-osx.c
+else
 platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
-platform_ltlibraries = libeggdesktopfile.la
 platform_libs = libeggdesktopfile.la -lSM -lICE
+platform_ltlibraries = libeggdesktopfile.la
 platform_sources = eggsmclient-xsmp.c
-platform_app_ldflags =
-platform_programs = egg-launch
+endif
+endif
 
 INCLUDES =                               \
 	-DG_LOG_DOMAIN=\""EggSMClient"\" \
+	$(GEDIT_CFLAGS)			 \
 	$(platform_defines)              \
-	$(GEDIT_CFLAGS)
+	$(EGG_SMCLIENT_CFLAGS)
 
 noinst_LTLIBRARIES =                     \
 	libeggsmclient.la                \
 	$(platform_ltlibraries)
 
 libeggsmclient_la_LIBADD =               \
-	$(GEDIT_LIBS)                    \
+	$(EGG_SMCLIENT_LIBS)             \
 	$(platform_libs)
 
+libeggsmclient_la_LDFLAGS =              \
+	$(platform_ldflags)
+
 libeggsmclient_la_SOURCES =              \
 	eggsmclient.c                    \
 	eggsmclient.h                    \
@@ -25,11 +38,13 @@
 	$(platform_sources)
 
 libeggdesktopfile_la_LIBADD =            \
-	$(GEDIT_LIBS)
+	$(EGG_LIBS)
 
 libeggdesktopfile_la_SOURCES =           \
 	eggdesktopfile.c                 \
 	eggdesktopfile.h
 
 EXTRA_DIST =                             \
+	eggsmclient-osx.c                \
+	eggsmclient-win32.c              \
 	eggsmclient-xsmp.c

Added: trunk/gedit/smclient/eggsmclient-osx.c
==============================================================================
--- (empty file)
+++ trunk/gedit/smclient/eggsmclient-osx.c	Wed Nov 26 20:04:28 2008
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2007 Novell, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* EggSMClientOSX
+ *
+ * For details on the OS X logout process, see:
+ * http://developer.apple.com/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/BootProcess.html#//apple_ref/doc/uid/20002130-114618
+ *
+ * EggSMClientOSX registers for the kAEQuitApplication AppleEvent; the
+ * handler we register (quit_requested()) will be invoked from inside
+ * the quartz event-handling code (specifically, from inside
+ * [NSApplication nextEventMatchingMask]) when an AppleEvent arrives.
+ * We use AESuspendTheCurrentEvent() and AEResumeTheCurrentEvent() to
+ * allow asynchronous / non-main-loop-reentering processing of the
+ * quit request. (These are part of the Carbon framework; it doesn't
+ * seem to be possible to handle AppleEvents asynchronously from
+ * Cocoa.)
+ */
+
+#include "config.h"
+
+#include "eggsmclient-private.h"
+#include <gdk/gdkquartz.h>
+#include <Carbon/Carbon.h>
+#include <CoreServices/CoreServices.h>
+
+#define EGG_TYPE_SM_CLIENT_OSX            (egg_sm_client_osx_get_type ())
+#define EGG_SM_CLIENT_OSX(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_OSX, EggSMClientOSX))
+#define EGG_SM_CLIENT_OSX_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_OSX, EggSMClientOSXClass))
+#define EGG_IS_SM_CLIENT_OSX(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_OSX))
+#define EGG_IS_SM_CLIENT_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_OSX))
+#define EGG_SM_CLIENT_OSX_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_OSX, EggSMClientOSXClass))
+
+typedef struct _EggSMClientOSX        EggSMClientOSX;
+typedef struct _EggSMClientOSXClass   EggSMClientOSXClass;
+
+struct _EggSMClientOSX {
+  EggSMClient parent;
+
+  AppleEvent quit_event, quit_reply;
+  gboolean quit_requested, quitting;
+};
+
+struct _EggSMClientOSXClass
+{
+  EggSMClientClass parent_class;
+
+};
+
+static void     sm_client_osx_startup (EggSMClient *client,
+				       const char  *client_id);
+static void     sm_client_osx_will_quit (EggSMClient *client,
+					 gboolean     will_quit);
+static gboolean sm_client_osx_end_session (EggSMClient         *client,
+					   EggSMClientEndStyle  style,
+					   gboolean  request_confirmation);
+
+static pascal OSErr quit_requested (const AppleEvent *, AppleEvent *, long);
+
+G_DEFINE_TYPE (EggSMClientOSX, egg_sm_client_osx, EGG_TYPE_SM_CLIENT)
+
+static void
+egg_sm_client_osx_init (EggSMClientOSX *osx)
+{
+  ;
+}
+
+static void
+egg_sm_client_osx_class_init (EggSMClientOSXClass *klass)
+{
+  EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
+
+  sm_client_class->startup             = sm_client_osx_startup;
+  sm_client_class->will_quit           = sm_client_osx_will_quit;
+  sm_client_class->end_session         = sm_client_osx_end_session;
+}
+
+EggSMClient *
+egg_sm_client_osx_new (void)
+{
+  return g_object_new (EGG_TYPE_SM_CLIENT_OSX, NULL);
+}
+
+static void
+sm_client_osx_startup (EggSMClient *client,
+		       const char  *client_id)
+{
+  AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
+			 NewAEEventHandlerUPP (quit_requested),
+			 (long)GPOINTER_TO_SIZE (client), false);
+}
+
+static gboolean
+idle_quit_requested (gpointer client)
+{
+  egg_sm_client_quit_requested (client);
+  return FALSE;
+}
+
+static pascal OSErr
+quit_requested (const AppleEvent *aevt, AppleEvent *reply, long refcon)
+{
+  EggSMClient *client = GSIZE_TO_POINTER ((gsize)refcon);
+  EggSMClientOSX *osx = GSIZE_TO_POINTER ((gsize)refcon);
+
+  g_return_val_if_fail (!osx->quit_requested, userCanceledErr);
+    
+  /* FIXME AEInteractWithUser? */
+
+  osx->quit_requested = TRUE;
+  AEDuplicateDesc (aevt, &osx->quit_event);
+  AEDuplicateDesc (reply, &osx->quit_reply);
+  AESuspendTheCurrentEvent (aevt);
+
+  /* Don't emit the "quit_requested" signal immediately, since we're
+   * called from a weird point in the guts of gdkeventloop-quartz.c
+   */
+  g_idle_add (idle_quit_requested, client);
+  return noErr;
+}
+
+static pascal OSErr
+quit_requested_resumed (const AppleEvent *aevt, AppleEvent *reply, long refcon)
+{
+  EggSMClientOSX *osx = GSIZE_TO_POINTER ((gsize)refcon);
+
+  osx->quit_requested = FALSE;
+  return osx->quitting ? noErr : userCanceledErr;
+}
+
+static gboolean
+idle_will_quit (gpointer client)
+{
+  EggSMClientOSX *osx = (EggSMClientOSX *)client;
+
+  /* Resume the event with a new handler that will return a value to
+   * the system.
+   */
+  AEResumeTheCurrentEvent (&osx->quit_event, &osx->quit_reply,
+			   NewAEEventHandlerUPP (quit_requested_resumed),
+			   (long)GPOINTER_TO_SIZE (client));
+  AEDisposeDesc (&osx->quit_event);
+  AEDisposeDesc (&osx->quit_reply);
+
+  if (osx->quitting)
+    egg_sm_client_quit (client);
+  return FALSE;
+}
+
+static void
+sm_client_osx_will_quit (EggSMClient *client,
+			 gboolean     will_quit)
+{
+  EggSMClientOSX *osx = (EggSMClientOSX *)client;
+
+  g_return_if_fail (osx->quit_requested);
+
+  osx->quitting = will_quit;
+
+  /* Finish in an idle handler since the caller might have called
+   * egg_sm_client_will_quit() from inside the "quit_requested" signal
+   * handler, but may not expect the "quit" signal to arrive during
+   * the _will_quit() call.
+   */
+  g_idle_add (idle_will_quit, client);
+}
+
+static gboolean
+sm_client_osx_end_session (EggSMClient         *client,
+			   EggSMClientEndStyle  style,
+			   gboolean             request_confirmation)
+{
+  static const ProcessSerialNumber loginwindow_psn = { 0, kSystemProcess };
+  AppleEvent event = { typeNull, NULL }, reply = { typeNull, NULL };
+  AEAddressDesc target;
+  AEEventID id;
+  OSErr err;
+
+  switch (style)
+    {
+    case EGG_SM_CLIENT_END_SESSION_DEFAULT:
+    case EGG_SM_CLIENT_LOGOUT:
+      id = request_confirmation ? kAELogOut : kAEReallyLogOut;
+      break;
+    case EGG_SM_CLIENT_REBOOT:
+      id = request_confirmation ? kAEShowRestartDialog : kAERestart;
+      break;
+    case EGG_SM_CLIENT_SHUTDOWN:
+      id = request_confirmation ? kAEShowShutdownDialog : kAEShutDown;
+      break;
+    }
+
+  err = AECreateDesc (typeProcessSerialNumber, &loginwindow_psn, 
+		      sizeof (loginwindow_psn), &target);
+  if (err != noErr)
+    {
+      g_warning ("Could not create descriptor for loginwindow: %d", err);
+      return FALSE;
+    }
+
+  err = AECreateAppleEvent (kCoreEventClass, id, &target,
+			    kAutoGenerateReturnID, kAnyTransactionID,
+			    &event);
+  AEDisposeDesc (&target);
+  if (err != noErr)
+    {
+      g_warning ("Could not create logout AppleEvent: %d", err);
+      return FALSE;
+    }
+
+  err = AESend (&event, &reply, kAENoReply, kAENormalPriority,
+		kAEDefaultTimeout, NULL, NULL);
+  AEDisposeDesc (&event);
+  if (err == noErr)
+    AEDisposeDesc (&reply);
+
+  return err == noErr;
+}

Added: trunk/gedit/smclient/eggsmclient-win32.c
==============================================================================
--- (empty file)
+++ trunk/gedit/smclient/eggsmclient-win32.c	Wed Nov 26 20:04:28 2008
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* EggSMClientWin32
+ *
+ * For details on the Windows XP logout process, see:
+ * http://msdn.microsoft.com/en-us/library/aa376876.aspx.
+ *
+ * Vista adds some new APIs which EggSMClient does not make use of; see
+ * http://msdn.microsoft.com/en-us/library/ms700677(VS.85).aspx
+ *
+ * When shutting down, Windows sends every top-level window a
+ * WM_QUERYENDSESSION event, which the application must respond to
+ * synchronously, saying whether or not it will quit. To avoid main
+ * loop re-entrancy problems (and to avoid having to muck about too
+ * much with the guts of the gdk-win32 main loop), we watch for this
+ * event in a separate thread, which then signals the main thread and
+ * waits for the main thread to handle the event. Since we don't want
+ * to require g_thread_init() to be called, we do this all using
+ * Windows-specific thread methods.
+ *
+ * After the application handles the WM_QUERYENDSESSION event,
+ * Windows then sends it a WM_ENDSESSION event with a TRUE or FALSE
+ * parameter indicating whether the session is or is not actually
+ * going to end now. We handle this from the other thread as well.
+ *
+ * As mentioned above, Vista introduces several additional new APIs
+ * that don't fit into the (current) EggSMClient API. Windows also has
+ * an entirely separate shutdown-notification scheme for non-GUI apps,
+ * which we also don't handle here.
+ */
+
+#include "config.h"
+
+#include "eggsmclient-private.h"
+#include <gdk/gdk.h>
+
+#define WIN32_LEAN_AND_MEAN
+#define UNICODE
+#include <windows.h>
+#include <process.h>
+
+#define EGG_TYPE_SM_CLIENT_WIN32            (egg_sm_client_win32_get_type ())
+#define EGG_SM_CLIENT_WIN32(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32))
+#define EGG_SM_CLIENT_WIN32_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32Class))
+#define EGG_IS_SM_CLIENT_WIN32(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_WIN32))
+#define EGG_IS_SM_CLIENT_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_WIN32))
+#define EGG_SM_CLIENT_WIN32_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32Class))
+
+typedef struct _EggSMClientWin32        EggSMClientWin32;
+typedef struct _EggSMClientWin32Class   EggSMClientWin32Class;
+
+struct _EggSMClientWin32 {
+  EggSMClient parent;
+
+  HANDLE message_event, response_event;
+
+  volatile GSourceFunc event;
+  volatile gboolean will_quit;
+};
+
+struct _EggSMClientWin32Class
+{
+  EggSMClientClass parent_class;
+
+};
+
+static void     sm_client_win32_startup (EggSMClient *client,
+					 const char  *client_id);
+static void     sm_client_win32_will_quit (EggSMClient *client,
+					   gboolean     will_quit);
+static gboolean sm_client_win32_end_session (EggSMClient         *client,
+					     EggSMClientEndStyle  style,
+					     gboolean  request_confirmation);
+
+static GSource *g_win32_handle_source_add (HANDLE handle, GSourceFunc callback,
+					gpointer user_data);
+static gboolean got_message (gpointer user_data);
+static void sm_client_thread (gpointer data);
+
+G_DEFINE_TYPE (EggSMClientWin32, egg_sm_client_win32, EGG_TYPE_SM_CLIENT)
+
+static void
+egg_sm_client_win32_init (EggSMClientWin32 *win32)
+{
+  ;
+}
+
+static void
+egg_sm_client_win32_class_init (EggSMClientWin32Class *klass)
+{
+  EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
+
+  sm_client_class->startup             = sm_client_win32_startup;
+  sm_client_class->will_quit           = sm_client_win32_will_quit;
+  sm_client_class->end_session         = sm_client_win32_end_session;
+}
+
+EggSMClient *
+egg_sm_client_win32_new (void)
+{
+  return g_object_new (EGG_TYPE_SM_CLIENT_WIN32, NULL);
+}
+
+static void
+sm_client_win32_startup (EggSMClient *client,
+			 const char  *client_id)
+{
+  EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
+
+  win32->message_event = CreateEvent (NULL, FALSE, FALSE, NULL);
+  win32->response_event = CreateEvent (NULL, FALSE, FALSE, NULL);
+  g_win32_handle_source_add (win32->message_event, got_message, win32);  
+  _beginthread (sm_client_thread, 0, client);
+}
+
+static void
+sm_client_win32_will_quit (EggSMClient *client,
+			   gboolean     will_quit)
+{
+  EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
+
+  win32->will_quit = will_quit;
+  SetEvent (win32->response_event);
+}
+
+static gboolean
+sm_client_win32_end_session (EggSMClient         *client,
+			     EggSMClientEndStyle  style,
+			     gboolean             request_confirmation)
+{
+  UINT uFlags = EWX_LOGOFF;
+
+  switch (style)
+    {
+    case EGG_SM_CLIENT_END_SESSION_DEFAULT:
+    case EGG_SM_CLIENT_LOGOUT:
+      uFlags = EWX_LOGOFF;
+      break;
+    case EGG_SM_CLIENT_REBOOT:
+      uFlags = EWX_REBOOT;
+      break;
+    case EGG_SM_CLIENT_SHUTDOWN:
+      uFlags = EWX_POWEROFF;
+      break;
+    }
+
+  /* There's no way to make ExitWindowsEx() show a logout dialog, so
+   * we ignore @request_confirmation.
+   */
+
+#ifdef SHTDN_REASON_FLAG_PLANNED
+  ExitWindowsEx (uFlags, SHTDN_REASON_FLAG_PLANNED);
+#else
+  ExitWindowsEx (uFlags, 0);
+#endif
+
+  return TRUE;
+}
+
+
+/* callbacks from logout-listener thread */
+
+static gboolean
+emit_quit_requested (gpointer smclient)
+{
+  gdk_threads_enter ();
+  egg_sm_client_quit_requested (smclient);
+  gdk_threads_leave ();
+
+  return FALSE;
+}
+
+static gboolean
+emit_quit (gpointer smclient)
+{
+  EggSMClientWin32 *win32 = smclient;
+
+  gdk_threads_enter ();
+  egg_sm_client_quit (smclient);
+  gdk_threads_leave ();
+
+  SetEvent (win32->response_event);
+  return FALSE;
+}
+
+static gboolean
+emit_quit_cancelled (gpointer smclient)
+{
+  EggSMClientWin32 *win32 = smclient;
+
+  gdk_threads_enter ();
+  egg_sm_client_quit_cancelled (smclient);
+  gdk_threads_leave ();
+
+  SetEvent (win32->response_event);
+  return FALSE;
+}
+
+static gboolean
+got_message (gpointer smclient)
+{
+  EggSMClientWin32 *win32 = smclient;
+
+  win32->event (win32);
+  return TRUE;
+}
+
+/* Windows HANDLE GSource */
+
+typedef struct {
+  GSource source;
+  GPollFD pollfd;
+} GWin32HandleSource;
+
+static gboolean
+g_win32_handle_source_prepare (GSource *source, gint *timeout)
+{
+  *timeout = -1;
+  return FALSE;
+}
+
+static gboolean
+g_win32_handle_source_check (GSource *source)
+{
+  GWin32HandleSource *hsource = (GWin32HandleSource *)source;
+
+  return hsource->pollfd.revents;
+}
+
+static gboolean
+g_win32_handle_source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
+{
+  return (*callback) (user_data);
+}
+
+static void
+g_win32_handle_source_finalize (GSource *source)
+{
+  ;
+}
+
+GSourceFuncs g_win32_handle_source_funcs = {
+  g_win32_handle_source_prepare,
+  g_win32_handle_source_check,
+  g_win32_handle_source_dispatch,
+  g_win32_handle_source_finalize
+};
+
+static GSource *
+g_win32_handle_source_add (HANDLE handle, GSourceFunc callback, gpointer user_data)
+{
+  GWin32HandleSource *hsource;
+  GSource *source;
+
+  source = g_source_new (&g_win32_handle_source_funcs, sizeof (GWin32HandleSource));
+  hsource = (GWin32HandleSource *)source;
+  hsource->pollfd.fd = (int)handle;
+  hsource->pollfd.events = G_IO_IN;
+  hsource->pollfd.revents = 0;
+  g_source_add_poll (source, &hsource->pollfd);
+
+  g_source_set_callback (source, callback, user_data, NULL);
+  g_source_attach (source, NULL);
+  return source;
+}
+
+/* logout-listener thread */
+
+LRESULT CALLBACK
+sm_client_win32_window_procedure (HWND   hwnd,
+				  UINT   message,
+				  WPARAM wParam,
+				  LPARAM lParam)
+{
+  EggSMClientWin32 *win32 =
+    (EggSMClientWin32 *)GetWindowLongPtr (hwnd, GWLP_USERDATA);
+
+  switch (message)
+    {
+    case WM_QUERYENDSESSION:
+      win32->event = emit_quit_requested;
+      SetEvent (win32->message_event);
+
+      WaitForSingleObject (win32->response_event, INFINITE);
+      return win32->will_quit;
+
+    case WM_ENDSESSION:
+      if (wParam)
+	{
+	  /* The session is ending */
+	  win32->event = emit_quit;
+	}
+      else
+	{
+	  /* Nope, the session *isn't* ending */
+	  win32->event = emit_quit_cancelled;
+	}
+
+      SetEvent (win32->message_event);
+      WaitForSingleObject (win32->response_event, INFINITE);
+
+      return 0;
+
+    default:
+      return DefWindowProc (hwnd, message, wParam, lParam);
+    }
+}
+
+static void
+sm_client_thread (gpointer smclient)
+{
+  HINSTANCE instance;
+  WNDCLASSEXW wcl; 
+  ATOM klass;
+  HWND window;
+  MSG msg;
+
+  instance = GetModuleHandle (NULL);
+
+  memset (&wcl, 0, sizeof (WNDCLASSEX));
+  wcl.cbSize = sizeof (WNDCLASSEX);
+  wcl.lpfnWndProc = sm_client_win32_window_procedure;
+  wcl.hInstance = instance;
+  wcl.lpszClassName = L"EggSmClientWindow";
+  klass = RegisterClassEx (&wcl);
+
+  window = CreateWindowEx (0, MAKEINTRESOURCE (klass),
+			   L"EggSmClientWindow", 0,
+			   10, 10, 50, 50, GetDesktopWindow (),
+			   NULL, instance, NULL);
+  SetWindowLongPtr (window, GWLP_USERDATA, (LONG_PTR)smclient);
+
+  /* main loop */
+  while (GetMessage (&msg, NULL, 0, 0))
+    DispatchMessage (&msg);
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]