dotgnu-pnet-commits
[Top][All Lists]
Advanced

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

[Dotgnu-pnet-commits] pnetlib/Xsharp EmbeddedApplication.cs, NONE, 1.1 D


From: Rhys Weatherley <address@hidden>
Subject: [Dotgnu-pnet-commits] pnetlib/Xsharp EmbeddedApplication.cs, NONE, 1.1 Display.cs, 1.10, 1.11 Xlib.cs.in, 1.14, 1.15 Xsharp.build, 1.3, 1.4 XsharpSupport.c, 1.17, 1.18
Date: Fri, 31 Oct 2003 06:44:37 +0000

Update of /cvsroot/dotgnu-pnet/pnetlib/Xsharp
In directory subversions:/tmp/cvs-serv17812/Xsharp

Modified Files:
        Display.cs Xlib.cs.in Xsharp.build XsharpSupport.c 
Added Files:
        EmbeddedApplication.cs 
Log Message:


add support to Xsharp to embed third party X applications inside a
child widget using XC-APPGROUP.


Index: Xsharp.build
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Xsharp.build,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** Xsharp.build        1 Oct 2003 23:50:03 -0000       1.3
--- Xsharp.build        31 Oct 2003 06:44:35 -0000      1.4
***************
*** 20,23 ****
--- 20,25 ----
  
                        <references>
+                               <file name="../System/first/System.dll"/>
+                               <file name="../DotGNU.SSL/DotGNU.SSL.dll"/>
                                <file 
name="../DotGNU.Images/DotGNU.Images.dll"/>
                                <file name="../runtime/mscorlib.dll"/>

--- NEW FILE: EmbeddedApplication.cs ---
/*
 * EmbeddedApplication.cs - Widget handling for embedding X apps in each other.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace Xsharp
{

// We need "extended diagnostics" to get the process launch capabilities.
#if CONFIG_EXTENDED_DIAGNOSTICS

using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Xsharp.Types;
using Xsharp.Events;

/// <summary>
/// <para>The <see cref="T:Xsharp.EmbeddedApplication"/> class manages
/// embedding a foreign X application as a child of this application's
/// widget tree.</para>
/// </summary>
///
/// <remarks>
/// <para>This class uses the <c>XC-APPGROUP</c> extension that is present
/// in common X servers to force a child application to embed itself
/// in our widget tree.</para>
///
/// <para>If the extension is not present, or it cannot
/// be properly initialized for some reason, then the child application
/// will be displayed in its own top-level window rather than being
/// embedded.</para>
///
/// <para>The <c>CanEmbed</c> method can be used to determine if
/// a display supports embedding.</para>
///
/// <para>If the parent application is executed within an ssh account,
/// with X11 forwarding enabled, then the <c>XREALDISPLAY</c> environment
/// variable must be set to indicate the real display server.  This is
/// needed because ssh does not support proxying of <c>XC-APPGROUP</c>
/// requests.</para>
/// </remarks>
public class EmbeddedApplication : InputOutputWidget
{
        // Internal state.
        private String program;
        private String args;
        private Process process;
        private String redirectDisplay;
        private String authorityFile;
        private Xlib.XAppGroup group;
        private AppGroupWidget groupWrapper;
        private Xlib.Window child;
        private bool closeNotifySent;
        private static bool errorReported;
        private static bool displayProbed;
        private static bool displayExists;

        /// <summary>
        /// <para>Constructs a new <see cref="T:Xsharp.EmbeddedApplication"/>
        /// instance.</para>
        /// </summary>
        ///
        /// <param name="parent">
        /// <para>The parent of the new widget.</para>
        /// </param>
        ///
        /// <param name="x">
        /// <para>The X co-ordinate of the top-left corner of
        /// the new widget.</para>
        /// </param>
        ///
        /// <param name="y">
        /// <para>The Y co-ordinate of the top-left corner of
        /// the new widget.</para>
        /// </param>
        ///
        /// <param name="width">
        /// <para>The width of the new window.</para>
        /// </param>
        ///
        /// <param name="height">
        /// <para>The height of the new window.</para>
        /// </param>
        ///
        /// <exception cref="T:System.ArgumentNullException">
        /// <para>Raised if <paramref name="parent"/> is <see langword="null"/>.
        /// </para>
        /// </exception>
        ///
        /// <exception cref="T:Xsharp.XException">
        /// <para>Raised if <paramref name="x"/>, <paramref name="y"/>,
        /// <paramref name="width"/>, or <paramref name="height"/> are
        /// out of range.</para>
        /// </exception>
        ///
        /// <exception cref="T.Xsharp.XInvalidOperationException">
        /// <para>Raised if <paramref name="parent"/> is disposed, the
        /// root window, or an input-only window.</para>
        /// </exception>
        public EmbeddedApplication(Widget parent, int x, int y,
                                                           int width, int 
height)
                        : this(parent, x, y, width, height, null, null)
                        {
                                // Nothing to do here.
                        }

        /// <summary>
        /// <para>Constructs a new <see cref="T:Xsharp.EmbeddedApplication"/>
        /// instance.</para>
        /// </summary>
        ///
        /// <param name="parent">
        /// <para>The parent of the new widget.</para>
        /// </param>
        ///
        /// <param name="x">
        /// <para>The X co-ordinate of the top-left corner of
        /// the new widget.</para>
        /// </param>
        ///
        /// <param name="y">
        /// <para>The Y co-ordinate of the top-left corner of
        /// the new widget.</para>
        /// </param>
        ///
        /// <param name="width">
        /// <para>The width of the new window.</para>
        /// </param>
        ///
        /// <param name="height">
        /// <para>The height of the new window.</para>
        /// </param>
        ///
        /// <param name="program">
        /// <para>The name of the program to execute.</para>
        /// </param>
        ///
        /// <param name="args">
        /// <para>The command-line arguments to pass to the program.</para>
        /// </param>
        ///
        /// <exception cref="T:System.ArgumentNullException">
        /// <para>Raised if <paramref name="parent"/> is <see langword="null"/>.
        /// </para>
        /// </exception>
        ///
        /// <exception cref="T:Xsharp.XException">
        /// <para>Raised if <paramref name="x"/>, <paramref name="y"/>,
        /// <paramref name="width"/>, or <paramref name="height"/> are
        /// out of range.</para>
        /// </exception>
        ///
        /// <exception cref="T.Xsharp.XInvalidOperationException">
        /// <para>Raised if <paramref name="parent"/> is disposed, the
        /// root window, or an input-only window.</para>
        /// </exception>
        public EmbeddedApplication(Widget parent, int x, int y,
                                                           int width, int 
height,
                                                           String program, 
String args)
                        : base(parent, x, y, width, height)
                        {
                                this.program = program;
                                this.args = args;
                                SelectInput(EventMask.SubstructureNotifyMask);
                        }

        /// <summary>
        /// <para>Get or set the name of the program to be executed.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>The name of the program to be executed.</para>
        /// </value>
        public String Program
                        {
                                get
                                {
                                        return program;
                                }
                                set
                                {
                                        program = value;
                                }
                        }

        /// <summary>
        /// <para>Get or set the command-line arguments for the program to
        /// be executed.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>The command-line arguments for the program to be 
executed.</para>
        /// </value>
        public String Arguments
                        {
                                get
                                {
                                        return args;
                                }
                                set
                                {
                                        args = value;
                                }
                        }

        /// <summary>
        /// <para>Get the process object for the embedded application.</para>
        /// </summary>
        ///
        /// <value>
        /// <para>The process object, or <see langword="null"/> if the
        /// application has not been launched yet.</para>
        /// </value>
        public Process Process
                        {
                                get
                                {
                                        return process;
                                }
                        }

        // Called when the child window is destroyed.
        private void ChildDestroyed()
                        {
                                child = Xlib.Window.Zero;
                                if(!(process.HasExited))
                                {
                                        process.WaitForExit();
                                }
                                if(authorityFile != null)
                                {
                                        File.Delete(authorityFile);
                                        authorityFile = null;
                                }
                                if(!closeNotifySent)
                                {
                                        closeNotifySent = true;
                                        OnClose();
                                }
                        }

        /// <summary>
        /// <para>Destroy this widget if it is currently active.</para>
        /// </summary>
        public override void Destroy()
                        {
                                try
                                {
                                        IntPtr d = dpy.Lock();
                                        if(group != Xlib.XAppGroup.Zero)
                                        {
                                                
Xlib.XagDestroyApplicationGroup(d, group);
                                                group = Xlib.XAppGroup.Zero;
                                        }
                                }
                                finally
                                {
                                        dpy.Unlock();
                                }
                                ChildDestroyed();
                                base.Destroy();
                        }

        /// <summary>
        /// <para>Close an embedded application.</para>
        /// </summary>
        ///
        /// <remarks>
        /// <para>This sends a <c>WM_DELETE_WINDOW</c> event to the embedded
        /// application, or an <c>XKillClient</c> if the embedded application
        /// does not support <c>WM_DELETE_WINDOW</c>.</para>
        ///
        /// <para>This is the recommended way to shut down an embedded
        /// application.  If the close fails, then <c>Terminate</c> will
        /// perform a hard shutdown of the child process.</para>
        /// </remarks>
        public void Close()
                        {
                                try
                                {
                                        IntPtr display = dpy.Lock();
                                        if(child != Xlib.Window.Zero)
                                        {
                                                Xlib.XSharpSendClose(display, 
child);
                                        }
                                }
                                finally
                                {
                                        dpy.Unlock();
                                }
                        }

        /// <summary>
        /// <para>This method is called when the client application window
        /// closes and the application is no longer running.</para>
        /// </summary>
        protected virtual void OnClose()
                        {
                                // Nothing to do here: normally overridden in 
subclasses.
                        }

        /// <summary>
        /// <para>Terminate an embedded application.</para>
        /// </summary>
        ///
        /// <remarks>
        /// <para>This sends a KILL signal to the child process, terminating it
        /// abruptly.</para>
        /// </remarks>
        public void Terminate()
                        {
                                if(process != null && !(process.HasExited))
                                {
                                        process.Kill();
                                        ChildDestroyed();
                                }
                        }

        /// <summary>
        /// <para>Launch the embedded application.</para>
        /// </summary>
        public void Launch()
                        {
                                // Bail out if the application was already 
launched.
                                if(process != null)
                                {
                                        return;
                                }

                                // Create an application group in the X server, 
which is
                                // used to redirect window create requests away 
from the
                                // window manager and to us instead.
                                CreateApplicationGroup();

                                // Create a new process object.
                                Process process = new Process();

                                // Build the process start information.
                                ProcessStartInfo info = process.StartInfo;
                                if(program != null)
                                {
                                        info.FileName = program;
                                }
                                if(args != null)
                                {
                                        info.Arguments = args;
                                }
                                if(redirectDisplay != null)
                                {
                                        info.EnvironmentVariables["DISPLAY"] = 
redirectDisplay;
                                }
                                if(authorityFile != null)
                                {
                                        info.EnvironmentVariables["XAUTHORITY"] 
= authorityFile;
                                }
                                ModifyProcessStartInfo(info);

                                // Launch the child process.
                                process.Start();

                                // Set the local process copy - we do this last 
just
                                // in case "Start()" throws an exception.
                                this.process = process;
                        }

        /// <summary>
        /// <para>Modify the process start information just before 
launch.</para>
        /// </summary>
        ///
        /// <param name="info">
        /// <para>The process start information to be modified.</para>
        /// </param>
        ///
        /// <remarks>
        /// <para>This method is called from <c>Launch</c> just before the
        /// child process is started.  It gives subclasses a chance to modify
        /// the environment, redirect stdin/stdout, etc.</para>
        /// </remarks>
        protected virtual void ModifyProcessStartInfo(ProcessStartInfo info)
                        {
                                // Nothing to do here: overridden by subclasses.
                        }

        /// <summary>
        /// <para>Determine if the X server can support embedding.</para>
        /// </summary>
        ///
        /// <param name="dpy">
        /// <para>The display to check.</para>
        /// </param>
        ///
        /// <returns>
        /// <para>Returns <see langword="true"/> if he display supports
        /// embedding, or <see langword="false"/> otherwise.</para>
        /// </returns>
        ///
        /// <remarks>
        /// <para>If this method returns <see langword="false"/>, then
        /// calling <c>Launch</c> will cause the child application to be
        /// displayed in its own top-level window, rather than being
        /// embedded directly as a child widget.</para>
        /// </remarks>
        public static bool CanEmbed(Display dpy)
                        {
                                String displayName;
                                if(dpy == null)
                                {
                                        return false;
                                }
                                return CanEmbed(dpy, false, out displayName);
                        }

        // Determine if the X server supports embedding - inner version.
        // "displayName" will be set to a non-null value if it is necessary
        // to redirect the DISPLAY environment variable elsewhere.
        private static bool CanEmbed(Display display, bool reportErrors,
                                                                 out String 
displayName)
                        {
                                IntPtr dpy;
                                Xlib.Xint major, minor;
                                displayName = null;
                                try
                                {
                                        dpy = display.Lock();

                                        // See if the X server supports 
XC-APPGROUP and SECURITY.
                                        if(Xlib.XagQueryVersion(dpy, out major, 
out minor)
                                                        == Xlib.Bool.False)
                                        {
                                                if(reportErrors && 
!errorReported)
                                                {
                                                        Console.Error.WriteLine
                                                                ("The X server 
`{0}' does not support the " +
                                                                 "XC-APPGROUP 
extension, which is required",
                                                                 
display.displayName);
                                                        Console.Error.WriteLine
                                                                ("for 
application embedding.");
                                                        errorReported = true;
                                                }
                                                return false;
                                        }
                                        if(Xlib.XSecurityQueryExtension(dpy, 
out major, out minor)
                                                        == Xlib.Bool.False)
                                        {
                                                if(reportErrors && 
!errorReported)
                                                {
                                                        Console.Error.WriteLine
                                                                ("The X server 
`{0}' does not support the " +
                                                                 "SECURITY 
extension, which is required",
                                                                 
display.displayName);
                                                        Console.Error.WriteLine
                                                                ("for 
application embedding.");
                                                        errorReported = true;
                                                }
                                                return false;
                                        }

                                        // If we are in an ssh shell account, 
then we cannot
                                        // connect via ssh's X11 forwarding 
mechanism as it
                                        // does not know how to proxy appgroup 
security tokens.
                                        
if(Environment.GetEnvironmentVariable("SSH_ASKPASS")
                                                        != null ||
                                           
Environment.GetEnvironmentVariable("SSH_TTY") != null)
                                        {
                                                displayName = 
Environment.GetEnvironmentVariable
                                                        ("XREALDISPLAY");
                                                if(displayName == null || 
displayName.Length == 0)
                                                {
                                                        if(reportErrors && 
!errorReported)
                                                        {
                                                                
Console.Error.WriteLine
                                                                        ("You 
must set the XREALDISPLAY " +
                                                                         
"environment variable when using");
                                                                
Console.Error.WriteLine
                                                                        ("an 
ssh account and X11 forwarding.");
                                                                errorReported = 
true;
                                                        }
                                                        displayName = null;
                                                        return false;
                                                }
                                                if(!displayProbed)
                                                {
                                                        // Probe the 
XREALDISPLAY to see if it can be used.
                                                        displayProbed = true;
                                                        IntPtr probe = 
Xlib.XOpenDisplay(displayName);
                                                        if(probe == IntPtr.Zero)
                                                        {
                                                                if(reportErrors 
&& !errorReported)
                                                                {
                                                                        
Console.Error.WriteLine
                                                                                
("The X server at `{0}' is not " +
                                                                                
 "accessible.  You may need to use " +
                                                                                
 "`xhost +' to permit access.",
                                                                                
 displayName);
                                                                        
errorReported = true;
                                                                }
                                                                displayName = 
null;
                                                                return false;
                                                        }
                                                        
Xlib.XCloseDisplay(probe);
                                                        displayExists = true;
                                                }
                                                else if(!displayExists)
                                                {
                                                        return false;
                                                }
                                        }
                                }
                                catch(MissingMethodException)
                                {
                                        return false;
                                }
                                catch(DllNotFoundException)
                                {
                                        return false;
                                }
                                catch(EntryPointNotFoundException)
                                {
                                        return false;
                                }
                                finally
                                {
                                        display.Unlock();
                                }
                                return true;
                        }

        // Create a new application group for embedding a child application.
        private unsafe void CreateApplicationGroup()
                        {
                                String displayName;
                                Xauth *auth;
                                Xauth *authReturn;
                                XSecurityAuthorizationAttributes xsa;
                                Xlib.XSecurityAuthorization xs;

                                // Check that we can create application groups.
                                if(!CanEmbed(dpy, true, out displayName))
                                {
                                        return;
                                }
                                try
                                {
                                        // Lock down the display while we do 
this.
                                        IntPtr display = dpy.Lock();

                                        // Create the application group 
identifier.
                                        
if(Xlib.XagCreateEmbeddedApplicationGroup
                                                        (display, 
Xlib.VisualID.Zero,
                                                         
Xlib.XDefaultColormapOfScreen(screen.screen),
                                                         
Xlib.XBlackPixelOfScreen(screen.screen),
                                                         
Xlib.XWhitePixelOfScreen(screen.screen),
                                                         out group) == 
Xlib.Status.Zero)
                                        {
                                                return;
                                        }

                                        // Generate an authentication token for 
the group.
                                        auth = Xlib.XSecurityAllocXauth();
                                        if(auth == null)
                                        {
                                                return;
                                        }
                                        auth->name = Marshal.StringToHGlobalAnsi
                                                ("MIT-MAGIC-COOKIE-1");
                                        auth->name_length = 18;
                                        xsa = new 
XSecurityAuthorizationAttributes();
                                        xsa.timeout = 300;
                                        xsa.trust_level = 0;    // 
XSecurityClientTrusted
                                        xsa.group = (Xlib.XID)group;
                                        xsa.event_mask = 0;
                                        authReturn = 
Xlib.XSecurityGenerateAuthorization
                                                (display, auth,
                                                 
(uint)(XSecurityAttributeMask.XSecurityTimeout |
                                                            
XSecurityAttributeMask.XSecurityTrustLevel |
                                                            
XSecurityAttributeMask.XSecurityGroup),
                                                 ref xsa, out xs);
                                        if(authReturn == null)
                                        {
                                                Xlib.XSecurityFreeXauth(auth);
                                                return;
                                        }

                                        // Write the credentials to a temporary 
X authority file.
                                        String authFile = 
Path.GetTempFileName();
                                        FileStream stream = new FileStream
                                                (authFile, FileMode.Create, 
FileAccess.Write);
                                        WriteShort(stream, 65535);      // 
family = FamilyWild
                                        WriteShort(stream, 0);          // 
address_length
                                        WriteShort(stream, 0);          // 
number_length
                                        WriteShort(stream, 
authReturn->name_length);
                                        WriteBytes(stream, authReturn->name,
                                                           
authReturn->name_length);
                                        WriteShort(stream, 
authReturn->data_length);
                                        WriteBytes(stream, authReturn->data,
                                                           
authReturn->data_length);
                                        stream.Close();

                                        // Free the Xauth structures that we 
don't need any more.
                                        Xlib.XSecurityFreeXauth(auth);
                                        Xlib.XSecurityFreeXauth(authReturn);

                                        // Record the app group information.
                                        redirectDisplay = displayName;
                                        authorityFile = authFile;

                                        // Create a wrapper around the appgroup 
to get events.
                                        groupWrapper = new AppGroupWidget(dpy, 
screen, group, this);
                                }
                                catch(MissingMethodException)
                                {
                                        return;
                                }
                                catch(DllNotFoundException)
                                {
                                        return;
                                }
                                catch(EntryPointNotFoundException)
                                {
                                        return;
                                }
                                finally
                                {
                                        dpy.Unlock();
                                }
                        }

        // Write a 16-bit short value to a stream.
        private static void WriteShort(Stream stream, int value)
                        {
                                stream.WriteByte((byte)(value >> 8));
                                stream.WriteByte((byte)value);
                        }

        // Write a buffer of data to a stream.
        private static void WriteBytes(Stream stream, IntPtr data, int len)
                        {
                                int offset;
                                for(offset = 0; offset < len; ++offset)
                                {
                                        stream.WriteByte(Marshal.ReadByte(data, 
offset));
                                }
                        }

        // Dispatch an event to this widget.
        internal override void DispatchEvent(ref XEvent xevent)
                        {
                                if(xevent.type == EventType.DestroyNotify &&
                                   xevent.xdestroywindow.window == child)
                                {
                                        // The child window has been destroyed.
                                        ChildDestroyed();
                                }
                                base.DispatchEvent(ref xevent);
                        }

        /// <summary>
        /// <para>Method that is called when the widget is resized to a
        /// new size.</para>
        /// </summary>
        ///
        /// <param name="width">
        /// <para>The new width for the widget.</para>
        /// </param>
        ///
        /// <param name="height">
        /// <para>The new width for the widget.</para>
        /// </param>
        protected override void OnResize(int width, int height)
                        {
                                if(child != Xlib.Window.Zero)
                                {
                                        // Resize the embedded child window to 
match the
                                        // dimensions of the embedding parent 
window.
                                        try
                                        {
                                                IntPtr display = dpy.Lock();
                                                Xlib.XResizeWindow
                                                        (display, child, 
(uint)width, (uint)height);
                                        }
                                        finally
                                        {
                                                dpy.Unlock();
                                        }
                                }
                        }

        // Simple widget handler for intercepting events from an app group.
        // Whenever a top-level window operation occurs in the embedded
        // application, it first sends the event to us, and then to the root
        // window if we didn't want it.
        private sealed class AppGroupWidget : Widget
        {
                // Internal state.
                private EmbeddedApplication embedParent;

                // Constructor.
                public AppGroupWidget(Display dpy, Screen screen, 
Xlib.XAppGroup group,
                                                          EmbeddedApplication 
parent)
                                : base(dpy, screen, DrawableKind.Widget, null)
                                {
                                        embedParent = parent;
                                        handle = (Xlib.Drawable)group;
                                        dpy.handleMap[(int)handle] = this;
                                }

                // Determine if we want a particular widget in a map request.
                private bool WantThisWindow(IntPtr dpy, Xlib.Window window)
                                {
                                        // Bail out if the parent already has 
an embedded child.
                                        if(embedParent.child != 
Xlib.Window.Zero)
                                        {
                                                return false;
                                        }

                                        // Ignore the window if it is a 
transient, because
                                        // we don't want dialog boxes that are 
displayed before
                                        // the main window to get accidentally 
reparented.
                                        Xlib.Window transientFor;
                                        if(Xlib.XGetTransientForHint(dpy, 
window, out transientFor)
                                                        != Xlib.Status.Zero)
                                        {
                                                return false;
                                        }

                                        // We want this widget.
                                        return true;
                                }

                // Dispatch an event to this widget.
                internal override void DispatchEvent(ref XEvent xevent)
                                {
                                        IntPtr display;
                                        Xlib.Window child;
                                        if(xevent.type == EventType.MapRequest)
                                        {
                                                // This may be notification of 
a new window
                                                // that we need to take control 
of.
                                                try
                                                {
                                                        display = dpy.Lock();
                                                        child = 
xevent.xmaprequest.window;
                                                        
if(WantThisWindow(display, child))
                                                        {
                                                                // This is the 
top-level child window that
                                                                // we have been 
waiting for.
                                                                XWindowChanges 
wc = new XWindowChanges();
                                                                wc.width = 
embedParent.Width;
                                                                wc.height = 
embedParent.Height;
                                                                wc.border_width 
= 0;
                                                                
Xlib.XConfigureWindow
                                                                        
(display, child,
                                                                         
(int)(ConfigureWindowMask.CWWidth |
                                                                                
   ConfigureWindowMask.CWHeight |
                                                                                
   ConfigureWindowMask.CWBorderWidth),
                                                                         ref 
wc);
                                                                
Xlib.XReparentWindow
                                                                        
(display, child,
                                                                         
embedParent.GetWidgetHandle(), 0, 0);
                                                                
Xlib.XMapWindow(display, child);
                                                                
embedParent.child = child;
                                                        }
                                                        else
                                                        {
                                                                // We don't 
want this window, or we already
                                                                // know about 
it, so replay the map request.
                                                                
Xlib.XMapWindow(display, child);
                                                        }
                                                }
                                                finally
                                                {
                                                        dpy.Unlock();
                                                }
                                        }
                                        else if(xevent.type == 
EventType.ConfigureRequest)
                                        {
                                                // Replay the configure event 
direct to the X server.
                                                XWindowChanges wc = new 
XWindowChanges();
                                                wc.x = 
xevent.xconfigurerequest.x;
                                                wc.y = 
xevent.xconfigurerequest.y;
                                                wc.width = 
xevent.xconfigurerequest.width;
                                                wc.height = 
xevent.xconfigurerequest.height;
                                                wc.border_width = 
xevent.xconfigurerequest.border_width;
                                                wc.sibling = 
xevent.xconfigurerequest.above;
                                                wc.stack_mode = 
xevent.xconfigurerequest.detail;
                                                try
                                                {
                                                        display = dpy.Lock();
                                                        Xlib.XConfigureWindow
                                                                (display,
                                                                 
xevent.xconfigurerequest.window,
                                                                 
xevent.xconfigurerequest.value_mask, ref wc);
                                                }
                                                finally
                                                {
                                                        dpy.Unlock();
                                                }
                                        }
                                        base.DispatchEvent(ref xevent);
                                }

        }; // class AppGroupWidget

} // class EmbeddedApplication

#endif // CONFIG_EXTENDED_DIAGNOSTICS

} // namespace Xsharp

Index: XsharpSupport.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/XsharpSupport.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** XsharpSupport.c     15 Oct 2003 01:01:39 -0000      1.17
--- XsharpSupport.c     31 Oct 2003 06:44:35 -0000      1.18
***************
*** 51,54 ****
--- 51,55 ----
  #include <stdlib.h>
  #include <stdio.h>
+ #include <string.h>
  
  int XNextEventWithTimeout(Display *dpy, XEvent *event, int timeout)
***************
*** 1095,1098 ****
--- 1096,1147 ----
  }
  
+ /*
+  * Send a close request to a window.  Tries to send "WM_DELETE_WINDOW",
+  * and if that doesn't work, sends "XKillClent" instead.
+  */
+ void XSharpSendClose(Display *dpy, Window window)
+ {
+       Atom wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+       Atom *protocols;
+       int num_protocols, posn;
+       int use_kill = 1;
+ 
+       /* Get the protocols that are supported by the client window */
+       protocols = 0;
+       num_protocols = 0;
+       if(XGetWMProtocols(dpy, window, &protocols, &num_protocols))
+       {
+               for(posn = 0; posn < num_protocols; ++posn)
+               {
+                       if(protocols[posn] == wmDeleteWindow)
+                       {
+                               use_kill = 0;
+                               break;
+                       }
+               }
+               if(protocols)
+               {
+                       XFree(protocols);
+               }
+       }
+ 
+       /* Send the close request to the client application */
+       if(use_kill)
+       {
+               XKillClient(dpy, (XID)window);
+       }
+       else
+       {
+               XEvent msg;
+               memset(&msg, 0, sizeof(msg));
+               msg.xclient.type = ClientMessage;
+               msg.xclient.window = window;
+               msg.xclient.message_type = XInternAtom(dpy, "WM_PROTOCOLS", 
False);
+               msg.xclient.format = 32;
+               msg.xclient.data.l[0] = wmDeleteWindow;
+               XSendEvent(dpy, window, False, NoEventMask, &msg);
+       }
+ }
+ 
  #else /* X_DISPLAY_MISSING || !HAVE_SELECT */
  
***************
*** 1174,1177 ****
--- 1223,1231 ----
  
  void XSharpGetRegionRect(void *region, int index, void *rect)
+ {
+       /* Nothing to do here */
+ }
+ 
+ void XSharpSendClose(Display *dpy, Window window)
  {
        /* Nothing to do here */

Index: Display.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Display.cs,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** Display.cs  6 Sep 2003 03:08:32 -0000       1.10
--- Display.cs  31 Oct 2003 06:44:35 -0000      1.11
***************
*** 39,43 ****
        // Internal state.
        internal IntPtr dpy;
!       private String displayName;
        private Screen[] screens;
        private int defaultScreen;
--- 39,43 ----
        // Internal state.
        internal IntPtr dpy;
!       internal String displayName;
        private Screen[] screens;
        private int defaultScreen;

Index: Xlib.cs.in
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Xlib.cs.in,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** Xlib.cs.in  1 Oct 2003 23:50:03 -0000       1.14
--- Xlib.cs.in  31 Oct 2003 06:44:35 -0000      1.15
***************
*** 27,31 ****
  using Xsharp.Types;
  
! internal sealed class Xlib
  {
        // Declare Xlib types that may be different sizes on different 
platforms.
--- 27,31 ----
  using Xsharp.Types;
  
! internal sealed unsafe class Xlib
  {
        // Declare Xlib types that may be different sizes on different 
platforms.
***************
*** 35,59 ****
        // to Xlib in the same way as the underlying integer type.
  
!       public enum Pixel    : @X_ulong@ { Zero }
!       public enum XID      : @X_ulong@ { Zero }
!       public enum Mask     : @X_ulong@ { Zero }
!       public enum Atom     : @X_ulong@ { Zero }
!       public enum VisualID : @X_ulong@ { Zero }
!       public enum Time     : @X_ulong@ { CurrentTime }
!       public enum Window   : @X_ulong@ { Zero }
!       public enum Drawable : @X_ulong@ { Zero }
!       public enum Font     : @X_ulong@ { Zero }
!       public enum Pixmap   : @X_ulong@ { Zero, ParentRelative }
!       public enum Cursor   : @X_ulong@ { Zero }
!       public enum Colormap : @X_ulong@ { Zero }
!       public enum GContext : @X_ulong@ { Zero }
!       public enum KeySym   : @X_ulong@ { Zero }
!       public enum KeyCode  : byte { Zero }
!       public enum Bool     : @X_int@ { False, True }
!       public enum Status   : @X_int@ { Zero }
!       public enum Xint     : @X_int@ { Zero }
!       public enum Xuint    : @X_uint@ { Zero }
!       public enum Xlong    : @X_long@ { Zero }
!       public enum Xulong   : @X_ulong@ { Zero }
  
        // Declare display-related external functions.
--- 35,60 ----
        // to Xlib in the same way as the underlying integer type.
  
!       public enum Pixel     : @X_ulong@ { Zero }
!       public enum XID       : @X_ulong@ { Zero }
!       public enum Mask      : @X_ulong@ { Zero }
!       public enum Atom      : @X_ulong@ { Zero }
!       public enum VisualID  : @X_ulong@ { Zero }
!       public enum Time      : @X_ulong@ { CurrentTime }
!       public enum Window    : @X_ulong@ { Zero }
!       public enum Drawable  : @X_ulong@ { Zero }
!       public enum Font      : @X_ulong@ { Zero }
!       public enum Pixmap    : @X_ulong@ { Zero, ParentRelative }
!       public enum Cursor    : @X_ulong@ { Zero }
!       public enum Colormap  : @X_ulong@ { Zero }
!       public enum GContext  : @X_ulong@ { Zero }
!       public enum XAppGroup : @X_ulong@ { Zero }
!       public enum KeySym    : @X_ulong@ { Zero }
!       public enum KeyCode   : byte { Zero }
!       public enum Bool      : @X_int@ { False, True }
!       public enum Status    : @X_int@ { Zero }
!       public enum Xint      : @X_int@ { Zero }
!       public enum Xuint     : @X_uint@ { Zero }
!       public enum Xlong     : @X_long@ { Zero }
!       public enum Xulong    : @X_ulong@ { Zero }
  
        // Declare display-related external functions.
***************
*** 469,475 ****
--- 470,483 ----
  
        [DllImport("X11")]
+       extern public static Status XGetTransientForHint
+                       (IntPtr display, Window w, out Window prop_window);
+ 
+       [DllImport("X11")]
        extern public static void XSetWMNormalHints
                        (IntPtr display, Window w, ref XSizeHints hints);
  
+       [DllImport("X11")]
+       extern public static @X_int@ XKillClient(IntPtr display, XID resource);
+ 
        // Declare color-related external functions.
  
***************
*** 575,578 ****
--- 583,590 ----
                        (IntPtr image, out @X_int@ width, out @X_int@ height);
  
+       [DllImport("XsharpSupport")]
+       extern public static void XSharpSendClose
+                       (IntPtr display, Xlib.Window window);
+ 
        // Helper functions from "libImlib.so" for loading images.
  
***************
*** 587,590 ****
--- 599,637 ----
        [DllImport("Xext")]
        extern public static Bool XShmQueryExtension(IntPtr display);
+ 
+       // Helper functions for creating and managing application groups.
+ 
+       [DllImport("Xext")]
+       extern public static Bool XagQueryVersion
+                       (IntPtr display, out Xint major, out Xint minor);
+ 
+       [DllImport("Xext")]
+       extern public static Status XagCreateEmbeddedApplicationGroup
+                       (IntPtr display, VisualID root_visual, Colormap 
default_colormap,
+                        Pixel black_pixel, Pixel white_pixel, out XAppGroup 
app_group);
+ 
+       [DllImport("Xext")]
+       extern public static Status XagDestroyApplicationGroup
+                       (IntPtr display, XAppGroup app_group);
+ 
+       // Helper functions for managing security tokens.
+ 
+       public enum XSecurityAuthorization : @X_ulong@ { Zero }
+ 
+       [DllImport("Xext")]
+       extern public static Bool XSecurityQueryExtension
+                       (IntPtr display, out Xint major, out Xint minor);
+ 
+       [DllImport("Xext")]
+       extern public static Xauth *XSecurityAllocXauth();
+ 
+       [DllImport("Xext")]
+       extern public static void XSecurityFreeXauth(Xauth *auth);
+ 
+       [DllImport("Xext")]
+       extern public static Xauth *XSecurityGenerateAuthorization
+                       (IntPtr dpy, Xauth *auth_in, @X_ulong@ valuemask,
+                        ref XSecurityAuthorizationAttributes attributes,
+                        out XSecurityAuthorization auth_id_return);
  
  } // class Xlib





reply via email to

[Prev in Thread] Current Thread [Next in Thread]