]> www.fi.muni.cz Git - evince.git/commitdiff
Make session manager code compile for w32. These changes have been taken
authorCarlos Garcia Campos <carlosgc@gnome.org>
Thu, 5 Feb 2009 09:44:50 +0000 (09:44 +0000)
committerCarlos Garcia Campos <carlosgc@src.gnome.org>
Thu, 5 Feb 2009 09:44:50 +0000 (09:44 +0000)
2009-02-05  Carlos Garcia Campos  <carlosgc@gnome.org>

* configure.ac:
* cut-n-paste/smclient/Makefile.am:
* cut-n-paste/smclient/eggdesktopfile.c:
* cut-n-paste/smclient/eggsmclient-win32.c:
* shell/main.c:

Make session manager code compile for w32. These changes have been
taken from upstream libegg. Based on patch by Hib Eris. See bug
#339172.

svn path=/trunk/; revision=3416

ChangeLog
configure.ac
cut-n-paste/smclient/Makefile.am
cut-n-paste/smclient/eggdesktopfile.c
cut-n-paste/smclient/eggsmclient-win32.c [new file with mode: 0644]
shell/main.c

index c6c21320395bed3d0fe9ce3658cdc9409231845a..24a0c27d7f5c88365169ed6ca912adc971ad8453 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,16 @@
-2009-02-05   Hib Eris  <hib@hiberis.nl>
+2009-02-05  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+       * configure.ac:
+       * cut-n-paste/smclient/Makefile.am:
+       * cut-n-paste/smclient/eggdesktopfile.c:
+       * cut-n-paste/smclient/eggsmclient-win32.c:
+       * shell/main.c:
+
+       Make session manager code compile for w32. These changes have been
+       taken from upstream libegg. Based on patch by Hib Eris. See bug
+       #339172.
+       
+2009-02-05  Hib Eris  <hib@hiberis.nl>
 
        * cut-n-paste/totem-screensaver/totem-scrsaver.c:
 
index c04a07b1c09f35e4d9bea06b37b99d4c4d6f0489..e66b125137cda24dd8ed97a04054b56c83cc5142 100644 (file)
@@ -72,6 +72,20 @@ AC_SUBST(GETTEXT_PACKAGE)
 AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[Gettext package])
 AM_GLIB_GNU_GETTEXT
 
+dnl check for win32 platform
+AC_MSG_CHECKING([for Win32 platform])
+case "$host" in
+  *-*-mingw*|*-*-cygwin*)
+    platform_win32=yes
+    AC_CHECK_TOOL(WINDRES, windres)
+    ;;
+  *)
+    platform_win32=no
+    ;;
+esac
+AC_MSG_RESULT([$platform_win32])
+AM_CONDITIONAL(PLATFORM_WIN32, test "$platform_win32" = "yes")
+
 dnl Check dependencies
 
 # LIB_CFLAGS       for helpers and generic widgets. (libdocument, cut-and-paste)
index c4ed73ada58a78c5610eb0a66f40652b96f25f13..7cc76bcbb864aea5771f5255476af5723b3afe47 100644 (file)
@@ -1,20 +1,36 @@
 noinst_LTLIBRARIES = libsmclient.la
 
-libsmclient_la_SOURCES =       \
+if PLATFORM_WIN32
+platform_sources = eggsmclient-win32.c
+else
+platform_libs = -lSM -lICE
+platform_sources =             \
+       eggsmclient-xsmp.c      \
        eggdesktopfile.c        \
-       eggdesktopfile.h        \
+       eggdesktopfile.h
+platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
+endif
+
+libsmclient_la_SOURCES =       \
        eggsmclient.c           \
        eggsmclient.h           \
        eggsmclient-private.h   \
-       eggsmclient-xsmp.c
+       $(platform_sources)
 
 libsmclient_la_CFLAGS =                                \
        -DG_LOG_DOMAIN=\""EggSMClient"\"        \
-       -DEGG_SM_CLIENT_BACKEND_XSMP            \
+       $(platform_defines)                     \
        $(SMCLIENT_CFLAGS)                      \
        $(WARNING_CFLAGS)                       \
        $(DISABLE_DEPRECATED)
 
 libsmclient_la_LIBADD =        \
        $(SMCLIENT_LIBS)        \
-       -lSM -lICE
+       $(platform_libs)
+
+EXTRA_DIST =                   \
+       eggsmclient-win32.c     \
+       eggsmclient-xsmp.c      \
+       eggdesktopfile.c        \
+       eggdesktopfile.h
+
index e88930597bf873b50fbab09df36500d467bb4b7f..1a20e96a55f5c60cb50e4f9ced713eeb976dda68 100644 (file)
@@ -987,7 +987,7 @@ end_startup_notification (GdkDisplay *display,
                                             NULL);
 }
 
-#define EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH (30 /* seconds */ * 1000)
+#define EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH (30 /* seconds */)
 
 typedef struct {
   GdkDisplay *display;
@@ -1017,8 +1017,8 @@ set_startup_notification_timeout (GdkDisplay *display,
   sn_data->display = g_object_ref (display);
   sn_data->startup_id = g_strdup (startup_id);
 
-  g_timeout_add (EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH,
-                startup_notification_timeout, sn_data);
+  g_timeout_add_seconds (EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH,
+                        startup_notification_timeout, sn_data);
 }
 #endif /* GTK 2.12 */
 
diff --git a/cut-n-paste/smclient/eggsmclient-win32.c b/cut-n-paste/smclient/eggsmclient-win32.c
new file mode 100644 (file)
index 0000000..91a2571
--- /dev/null
@@ -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);
+}
index 5348469fce27c9c9b13b1a0654eb252cb9af6bae..17e0f647f9fa9f95041982c9a942f4ea49d46dfb 100644 (file)
@@ -37,7 +37,9 @@
 #include "ev-file-helpers.h"
 #include "ev-stock-icons.h"
 #include "eggsmclient.h"
+#ifndef G_OS_WIN32
 #include "eggdesktopfile.h"
+#endif
 
 static gchar   *ev_page_label;
 static gchar   *ev_find_string;
@@ -374,8 +376,14 @@ main (int argc, char *argv[])
                 return 1;
 
        ev_stock_icons_init ();
-       
+
+#ifdef G_OS_WIN32
+       /* Manually set name and icon in win32 */
+       g_set_application_name (_("Evince"));
+       gtk_window_set_default_icon_name ("evince");
+#else
        egg_set_desktop_file (GNOMEDATADIR "/applications/evince.desktop");
+#endif /* G_OS_WIN32 */
 
        if (!ev_application_load_session (EV_APP))
                load_files (file_arguments, args);