libegg r906 - trunk/libegg/smclient
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libegg r906 - trunk/libegg/smclient
- Date: Sun, 5 Oct 2008 20:03:34 +0000 (UTC)
Author: danw
Date: Sun Oct 5 20:03:33 2008
New Revision: 906
URL: http://svn.gnome.org/viewvc/libegg?rev=906&view=rev
Log:
* eggsmclient-win32.c: Redo using native Windows thread methods so
we don't require g_thread_init() on Windows only.
* egg-session-end.c (main):
* logout-test.c (main): Remove g_thread_init()
Modified:
trunk/libegg/smclient/ChangeLog
trunk/libegg/smclient/egg-session-end.c
trunk/libegg/smclient/eggsmclient-win32.c
trunk/libegg/smclient/logout-test.c
Modified: trunk/libegg/smclient/egg-session-end.c
==============================================================================
--- trunk/libegg/smclient/egg-session-end.c (original)
+++ trunk/libegg/smclient/egg-session-end.c Sun Oct 5 20:03:33 2008
@@ -73,7 +73,6 @@
GError *err = NULL;
g_type_init ();
- g_thread_init (NULL);
goption_context = g_option_context_new (_("- End the current session"));
g_option_context_add_main_entries (goption_context, options, NULL);
Modified: trunk/libegg/smclient/eggsmclient-win32.c
==============================================================================
--- trunk/libegg/smclient/eggsmclient-win32.c (original)
+++ trunk/libegg/smclient/eggsmclient-win32.c Sun Oct 5 20:03:33 2008
@@ -17,6 +17,35 @@
* 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"
@@ -25,6 +54,7 @@
#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))
@@ -39,7 +69,10 @@
struct _EggSMClientWin32 {
EggSMClient parent;
- GAsyncQueue *msg_queue;
+ HANDLE message_event, response_event;
+
+ volatile GSourceFunc event;
+ volatile gboolean will_quit;
};
struct _EggSMClientWin32Class
@@ -56,7 +89,10 @@
EggSMClientEndStyle style,
gboolean request_confirmation);
-static gpointer sm_client_thread (gpointer data);
+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)
@@ -88,9 +124,10 @@
{
EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
- /* spawn another thread to listen for logout signals on */
- win32->msg_queue = g_async_queue_new ();
- g_thread_create (sm_client_thread, client, FALSE, NULL);
+ 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
@@ -99,8 +136,8 @@
{
EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
- /* Can't push NULL onto a GAsyncQueue, so we add 1 to the value... */
- g_async_queue_push (win32->msg_queue, GINT_TO_POINTER (will_quit + 1));
+ win32->will_quit = will_quit;
+ SetEvent (win32->response_event);
}
static gboolean
@@ -159,7 +196,7 @@
egg_sm_client_quit (smclient);
gdk_threads_leave ();
- g_async_queue_push (win32->msg_queue, GINT_TO_POINTER (1));
+ SetEvent (win32->response_event);
return FALSE;
}
@@ -172,25 +209,80 @@
egg_sm_client_quit_cancelled (smclient);
gdk_threads_leave ();
- g_async_queue_push (win32->msg_queue, GINT_TO_POINTER (1));
+ SetEvent (win32->response_event);
return FALSE;
}
+static gboolean
+got_message (gpointer smclient)
+{
+ EggSMClientWin32 *win32 = smclient;
+
+ win32->event (win32);
+ return TRUE;
+}
-/* logout-listener thread */
+/* 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)
+{
+ ;
+}
-static int
-async_emit (EggSMClientWin32 *win32, GSourceFunc emitter)
+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)
{
- /* ensure message queue is empty */
- while (g_async_queue_try_pop (win32->msg_queue))
- ;
-
- /* Emit signal in the main thread and wait for a response */
- g_idle_add (emitter, win32);
- return GPOINTER_TO_INT (g_async_queue_pop (win32->msg_queue)) - 1;
+ 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,
@@ -203,19 +295,27 @@
switch (message)
{
case WM_QUERYENDSESSION:
- return async_emit (win32, emit_quit_requested);
+ 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 */
- async_emit (win32, emit_quit);
+ win32->event = emit_quit;
}
else
{
/* Nope, the session *isn't* ending */
- async_emit (win32, emit_quit_cancelled);
+ win32->event = emit_quit_cancelled;
}
+
+ SetEvent (win32->message_event);
+ WaitForSingleObject (win32->response_event, INFINITE);
+
return 0;
default:
@@ -223,7 +323,7 @@
}
}
-static gpointer
+static void
sm_client_thread (gpointer smclient)
{
HINSTANCE instance;
@@ -250,6 +350,4 @@
/* main loop */
while (GetMessage (&msg, NULL, 0, 0))
DispatchMessage (&msg);
-
- return NULL;
}
Modified: trunk/libegg/smclient/logout-test.c
==============================================================================
--- trunk/libegg/smclient/logout-test.c (original)
+++ trunk/libegg/smclient/logout-test.c Sun Oct 5 20:03:33 2008
@@ -102,7 +102,6 @@
GtkWidget *label;
g_type_init ();
- g_thread_init (NULL);
goption_context = g_option_context_new (_("- Test logout functionality"));
g_option_context_add_group (goption_context, gtk_get_option_group (TRUE));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]