Alexandre Julliard : server: Support for closing the desktop window.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Mar 6 15:28:01 CST 2006


Module: wine
Branch: refs/heads/master
Commit: f978f615d8d89f5e3dc7056cfff7b34e1f174295
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=f978f615d8d89f5e3dc7056cfff7b34e1f174295

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Mar  6 21:02:24 2006 +0100

server: Support for closing the desktop window.

If a thread is owning the desktop window, when all other users of the
desktop have exited, signal the owner to close the desktop (with a 1
second delay).

---

 server/process.c    |    1 +
 server/user.h       |   17 +++++++++++------
 server/window.c     |   15 +++++++++++++++
 server/winstation.c |   41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 68 insertions(+), 6 deletions(-)

diff --git a/server/process.c b/server/process.c
index cc88c5f..824f9b3 100644
--- a/server/process.c
+++ b/server/process.c
@@ -570,6 +570,7 @@ static void process_killed( struct proce
 
     assert( list_empty( &process->thread_list ));
     gettimeofday( &process->end_time, NULL );
+    close_process_desktop( process );
     handles = process->handles;
     process->handles = NULL;
     if (handles) release_object( handles );
diff --git a/server/user.h b/server/user.h
index 7a64a4d..a70c6fc 100644
--- a/server/user.h
+++ b/server/user.h
@@ -52,12 +52,14 @@ struct winstation
 
 struct desktop
 {
-    struct object      obj;           /* object header */
-    unsigned int       flags;         /* desktop flags */
-    struct winstation *winstation;    /* winstation this desktop belongs to */
-    struct list        entry;         /* entry in winstation list of desktops */
-    struct window     *top_window;    /* desktop window for this desktop */
-    struct hook_table *global_hooks;  /* table of global hooks on this desktop */
+    struct object        obj;            /* object header */
+    unsigned int         flags;          /* desktop flags */
+    struct winstation   *winstation;     /* winstation this desktop belongs to */
+    struct list          entry;          /* entry in winstation list of desktops */
+    struct window       *top_window;     /* desktop window for this desktop */
+    struct hook_table   *global_hooks;   /* table of global hooks on this desktop */
+    struct timeout_user *close_timeout;  /* timeout before closing the desktop */
+    unsigned int         users;          /* processes and threads using this desktop */
 };
 
 /* user handles functions */
@@ -123,6 +125,8 @@ extern int rect_in_region( struct region
 
 /* window functions */
 
+extern struct process *get_top_window_owner( struct desktop *desktop );
+extern void close_desktop_window( struct desktop *desktop );
 extern void destroy_window( struct window *win );
 extern void destroy_thread_windows( struct thread *thread );
 extern int is_child_window( user_handle_t parent, user_handle_t child );
@@ -150,6 +154,7 @@ extern struct winstation *get_process_wi
 extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access );
 extern void connect_process_winstation( struct process *process, const struct unicode_str *name );
 extern void connect_process_desktop( struct process *process, const struct unicode_str *name );
+extern void close_process_desktop( struct process *process );
 extern void close_thread_desktop( struct thread *thread );
 
 #endif  /* __WINE_SERVER_USER_H */
diff --git a/server/window.c b/server/window.c
index 812ecee..8b7af20 100644
--- a/server/window.c
+++ b/server/window.c
@@ -351,6 +351,21 @@ void destroy_window( struct window *win 
     free( win );
 }
 
+/* get the process owning the top window of a given desktop */
+struct process *get_top_window_owner( struct desktop *desktop )
+{
+    struct window *win = desktop->top_window;
+    if (!win || !win->thread) return NULL;
+    return win->thread->process;
+}
+
+/* attempt to close the desktop window when the last process using it is gone */
+void close_desktop_window( struct desktop *desktop )
+{
+    struct window *win = desktop->top_window;
+    if (win && win->thread) post_message( win->handle, WM_SYSCOMMAND, SC_CLOSE, 0 );
+}
+
 /* create a new window structure (note: the window is not linked in the window tree) */
 static struct window *create_window( struct window *parent, struct window *owner,
                                      atom_t atom, void *instance )
diff --git a/server/winstation.c b/server/winstation.c
index da24be4..1239298 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -36,6 +36,7 @@
 #include "request.h"
 #include "process.h"
 #include "user.h"
+#include "file.h"
 #include "wine/unicode.h"
 
 
@@ -199,6 +200,8 @@ static struct desktop *create_desktop( c
             desktop->winstation = (struct winstation *)grab_object( winstation );
             desktop->top_window = NULL;
             desktop->global_hooks = NULL;
+            desktop->close_timeout = NULL;
+            desktop->users = 0;
             list_add_tail( &winstation->desktops, &desktop->entry );
         }
     }
@@ -233,6 +236,7 @@ static void desktop_destroy( struct obje
 
     if (desktop->top_window) destroy_window( desktop->top_window );
     if (desktop->global_hooks) release_object( desktop->global_hooks );
+    if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout );
     list_remove( &desktop->entry );
     release_object( desktop->winstation );
 }
@@ -293,6 +297,12 @@ void connect_process_desktop( struct pro
         if ((desktop = create_desktop( name, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0, winstation )))
         {
             process->desktop = alloc_handle( process, desktop, DESKTOP_ALL_ACCESS, 0 );
+            desktop->users++;
+            if (desktop->close_timeout)
+            {
+                remove_timeout_user( desktop->close_timeout );
+                desktop->close_timeout = NULL;
+            }
             release_object( desktop );
         }
         release_object( winstation );
@@ -300,6 +310,37 @@ void connect_process_desktop( struct pro
     clear_error();  /* ignore errors */
 }
 
+static void close_desktop_timeout( void *private )
+{
+    struct desktop *desktop = private;
+
+    desktop->close_timeout = NULL;
+    unlink_named_object( &desktop->obj );  /* make sure no other process can open it */
+    close_desktop_window( desktop );  /* and signal the owner to quit */
+}
+
+/* close the desktop of a given process */
+void close_process_desktop( struct process *process )
+{
+    struct desktop *desktop;
+
+    if (process->desktop && (desktop = get_desktop_obj( process, process->desktop, 0 )))
+    {
+        assert( desktop->users > 0 );
+        desktop->users--;
+        /* if we have one remaining user, it has to be the manager of the desktop window */
+        if (desktop->users == 1 && get_top_window_owner( desktop ))
+        {
+            struct timeval when;
+            gettimeofday( &when, NULL );
+            add_timeout( &when, 1000 );
+            desktop->close_timeout = add_timeout_user( &when, close_desktop_timeout, desktop );
+        }
+        release_object( desktop );
+    }
+    clear_error();  /* ignore errors */
+}
+
 /* close the desktop of a given thread */
 void close_thread_desktop( struct thread *thread )
 {




More information about the wine-cvs mailing list