/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs
https://github.com/catlion/mono · C# · 7588 lines · 5716 code · 1347 blank · 525 comment · 1173 complexity · a5b31050b832856e57a30cc5ca58b9dc MD5 · raw file
Large files are truncated click here to view the full file
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- // Copyright (c) 2004-2006 Novell, Inc.
- //
- // Authors:
- // Peter Bartok pbartok@novell.com
- //
- //
- // NOTE:
- // This driver understands the following environment variables: (Set the var to enable feature)
- //
- // MONO_XEXCEPTIONS = throw an exception when a X11 error is encountered;
- // by default a message is displayed but execution continues
- //
- // MONO_XSYNC = perform all X11 commands synchronous; this is slower but
- // helps in debugging errors
- //
- // NOT COMPLETE
- // define to log Window handles and relationships to stdout
- #undef DriverDebug
- // Extra detailed debug
- #undef DriverDebugExtra
- #undef DriverDebugParent
- #undef DriverDebugCreate
- #undef DriverDebugDestroy
- #undef DriverDebugThreads
- #undef DriverDebugXEmbed
- //#define TRACE
- //#define DEBUG
- using System;
- using System.ComponentModel;
- using System.Collections;
- using System.Diagnostics;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Text;
- using System.Threading;
- // Only do the poll when building with mono for now
- #if __MonoCS__
- using Mono.Unix.Native;
- #endif
- /// X11 Version
- namespace System.Windows.Forms {
- internal class XplatUIX11 : XplatUIDriver {
- #region Local Variables
- // General
- static volatile XplatUIX11 Instance;
- static int RefCount;
- static object XlibLock; // Our locking object
- static bool themes_enabled;
- // General X11
- static IntPtr DisplayHandle; // X11 handle to display
- static int ScreenNo; // Screen number used
- static IntPtr DefaultColormap; // Colormap for screen
- static IntPtr CustomVisual; // Visual for window creation
- static IntPtr CustomColormap; // Colormap for window creation
- static IntPtr RootWindow; // Handle of the root window for the screen/display
- static IntPtr FosterParent; // Container to hold child windows until their parent exists
- static XErrorHandler ErrorHandler; // Error handler delegate
- static bool ErrorExceptions; // Throw exceptions on X errors
- int render_major_opcode;
- int render_first_event;
- int render_first_error;
- // Clipboard
- static IntPtr ClipMagic;
- static ClipboardData Clipboard; // Our clipboard
- // Communication
- static IntPtr PostAtom; // PostMessage atom
- static IntPtr AsyncAtom; // Support for async messages
- // Message Loop
- static Hashtable MessageQueues; // Holds our thread-specific XEventQueues
- static ArrayList unattached_timer_list; // holds timers that are enabled but not attached to a window.
- #if __MonoCS__ //
- static Pollfd[] pollfds; // For watching the X11 socket
- static bool wake_waiting;
- static object wake_waiting_lock = new object ();
- #endif //
- static X11Keyboard Keyboard; //
- static X11Dnd Dnd;
- static Socket listen; //
- static Socket wake; //
- static Socket wake_receive; //
- static byte[] network_buffer; //
- static bool detectable_key_auto_repeat;
- // Focus tracking
- static IntPtr ActiveWindow; // Handle of the active window
- static IntPtr FocusWindow; // Handle of the window with keyboard focus (if any)
- // Modality support
- static Stack ModalWindows; // Stack of our modal windows
- // Systray
- static IntPtr SystrayMgrWindow; // Handle of the Systray Manager window
- // Cursors
- static IntPtr LastCursorWindow; // The last window we set the cursor on
- static IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
- static IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
- // Caret
- static CaretStruct Caret; //
- // Last window containing the pointer
- static IntPtr LastPointerWindow; // The last window containing the pointer
- // Our atoms
- static IntPtr WM_PROTOCOLS;
- static IntPtr WM_DELETE_WINDOW;
- static IntPtr WM_TAKE_FOCUS;
- //static IntPtr _NET_SUPPORTED;
- //static IntPtr _NET_CLIENT_LIST;
- //static IntPtr _NET_NUMBER_OF_DESKTOPS;
- static IntPtr _NET_DESKTOP_GEOMETRY;
- //static IntPtr _NET_DESKTOP_VIEWPORT;
- static IntPtr _NET_CURRENT_DESKTOP;
- //static IntPtr _NET_DESKTOP_NAMES;
- static IntPtr _NET_ACTIVE_WINDOW;
- static IntPtr _NET_WORKAREA;
- //static IntPtr _NET_SUPPORTING_WM_CHECK;
- //static IntPtr _NET_VIRTUAL_ROOTS;
- //static IntPtr _NET_DESKTOP_LAYOUT;
- //static IntPtr _NET_SHOWING_DESKTOP;
- //static IntPtr _NET_CLOSE_WINDOW;
- //static IntPtr _NET_MOVERESIZE_WINDOW;
- static IntPtr _NET_WM_MOVERESIZE;
- //static IntPtr _NET_RESTACK_WINDOW;
- //static IntPtr _NET_REQUEST_FRAME_EXTENTS;
- static IntPtr _NET_WM_NAME;
- //static IntPtr _NET_WM_VISIBLE_NAME;
- //static IntPtr _NET_WM_ICON_NAME;
- //static IntPtr _NET_WM_VISIBLE_ICON_NAME;
- //static IntPtr _NET_WM_DESKTOP;
- static IntPtr _NET_WM_WINDOW_TYPE;
- static IntPtr _NET_WM_STATE;
- //static IntPtr _NET_WM_ALLOWED_ACTIONS;
- //static IntPtr _NET_WM_STRUT;
- //static IntPtr _NET_WM_STRUT_PARTIAL;
- //static IntPtr _NET_WM_ICON_GEOMETRY;
- static IntPtr _NET_WM_ICON;
- //static IntPtr _NET_WM_PID;
- //static IntPtr _NET_WM_HANDLED_ICONS;
- static IntPtr _NET_WM_USER_TIME;
- static IntPtr _NET_FRAME_EXTENTS;
- //static IntPtr _NET_WM_PING;
- //static IntPtr _NET_WM_SYNC_REQUEST;
- static IntPtr _NET_SYSTEM_TRAY_S;
- //static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
- static IntPtr _NET_SYSTEM_TRAY_OPCODE;
- static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
- static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
- static IntPtr _XEMBED;
- static IntPtr _XEMBED_INFO;
- static IntPtr _MOTIF_WM_HINTS;
- static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
- static IntPtr _NET_WM_STATE_ABOVE;
- static IntPtr _NET_WM_STATE_MODAL;
- static IntPtr _NET_WM_STATE_HIDDEN;
- static IntPtr _NET_WM_CONTEXT_HELP;
- static IntPtr _NET_WM_WINDOW_OPACITY;
- //static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
- //static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
- //static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
- //static IntPtr _NET_WM_WINDOW_TYPE_MENU;
- static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
- //static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
- // static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
- static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
- static IntPtr CLIPBOARD;
- static IntPtr PRIMARY;
- //static IntPtr DIB;
- static IntPtr OEMTEXT;
- static IntPtr UTF8_STRING;
- static IntPtr UTF16_STRING;
- static IntPtr RICHTEXTFORMAT;
- static IntPtr TARGETS;
- // mouse hover message generation
- static HoverStruct HoverState; //
- // double click message generation
- static ClickStruct ClickPending; //
- // Support for mouse grab
- static GrabStruct Grab; //
- // State
- Point mouse_position; // Last position of mouse, in screen coords
- internal static MouseButtons MouseState; // Last state of mouse buttons
- internal static bool in_doevents;
- // 'Constants'
- static int DoubleClickInterval; // msec; max interval between clicks to count as double click
- const EventMask SelectInputMask = (EventMask.ButtonPressMask |
- EventMask.ButtonReleaseMask |
- EventMask.KeyPressMask |
- EventMask.KeyReleaseMask |
- EventMask.EnterWindowMask |
- EventMask.LeaveWindowMask |
- EventMask.ExposureMask |
- EventMask.FocusChangeMask |
- EventMask.PointerMotionMask |
- EventMask.PointerMotionHintMask |
- EventMask.SubstructureNotifyMask);
- static readonly object lockobj = new object ();
- // messages WaitForHwndMwssage is waiting on
- static Hashtable messageHold;
- #endregion // Local Variables
- #region Constructors
- XplatUIX11()
- {
- // Handle singleton stuff first
- RefCount = 0;
- in_doevents = false;
- // Now regular initialization
- XlibLock = new object ();
- X11Keyboard.XlibLock = XlibLock;
- MessageQueues = Hashtable.Synchronized (new Hashtable(7));
- unattached_timer_list = ArrayList.Synchronized (new ArrayList (3));
- messageHold = Hashtable.Synchronized (new Hashtable(3));
- Clipboard = new ClipboardData ();
- XInitThreads();
- ErrorExceptions = false;
- // X11 Initialization
- SetDisplay(XOpenDisplay(IntPtr.Zero));
- X11DesktopColors.Initialize();
-
- // Disable keyboard autorepeat
- try {
- XkbSetDetectableAutoRepeat (DisplayHandle, true, IntPtr.Zero);
- detectable_key_auto_repeat = true;
- } catch {
- Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
- detectable_key_auto_repeat = false;
- }
- // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
- ErrorHandler = new XErrorHandler(HandleError);
- XSetErrorHandler(ErrorHandler);
- }
- ~XplatUIX11() {
- // Remove our display handle from S.D
- Graphics.FromHdcInternal (IntPtr.Zero);
- }
- #endregion // Constructors
- #region Singleton Specific Code
- public static XplatUIX11 GetInstance() {
- lock (lockobj) {
- if (Instance == null) {
- Instance=new XplatUIX11();
- }
- RefCount++;
- }
- return Instance;
- }
- public int Reference {
- get {
- return RefCount;
- }
- }
- #endregion
- #region Internal Properties
- internal static IntPtr Display {
- get {
- return DisplayHandle;
- }
- set {
- XplatUIX11.GetInstance().SetDisplay(value);
- }
- }
- internal static int Screen {
- get {
- return ScreenNo;
- }
- set {
- ScreenNo = value;
- }
- }
- internal static IntPtr RootWindowHandle {
- get {
- return RootWindow;
- }
- set {
- RootWindow = value;
- }
- }
- internal static IntPtr Visual {
- get {
- return CustomVisual;
- }
- set {
- CustomVisual = value;
- }
- }
- internal static IntPtr ColorMap {
- get {
- return CustomColormap;
- }
- set {
- CustomColormap = value;
- }
- }
- #if DEBUG_shana
- internal static IntPtr DefaultColorMap {
- get {
- return DefaultColormap;
- }
- }
- #endif
- #endregion
- #region XExceptionClass
- internal class XException : ApplicationException {
- IntPtr Display;
- IntPtr ResourceID;
- IntPtr Serial;
- XRequest RequestCode;
- byte ErrorCode;
- byte MinorCode;
- public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
- this.Display = Display;
- this.ResourceID = ResourceID;
- this.Serial = Serial;
- this.RequestCode = RequestCode;
- this.ErrorCode = ErrorCode;
- this.MinorCode = MinorCode;
- }
- public override string Message {
- get {
- return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
- }
- }
- public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
- StringBuilder sb;
- string x_error_text;
- string error;
- string hwnd_text;
- string control_text;
- Hwnd hwnd;
- Control c;
- sb = new StringBuilder(160);
- XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
- x_error_text = sb.ToString();
- hwnd = Hwnd.ObjectFromHandle(ResourceID);
- if (hwnd != null) {
- hwnd_text = hwnd.ToString();
- c = Control.FromHandle(hwnd.Handle);
- if (c != null) {
- control_text = c.ToString();
- } else {
- control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle.ToInt32());
- }
- } else {
- hwnd_text = "<null>";
- control_text = "<null>";
- }
- error = String.Format("\n Error: {0}\n Request: {1:D} ({2})\n Resource ID: 0x{3:X}\n Serial: {4}\n Hwnd: {5}\n Control: {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
- return error;
- }
- }
- #endregion // XExceptionClass
- #region Internal Methods
- internal void SetDisplay(IntPtr display_handle)
- {
- if (display_handle != IntPtr.Zero) {
- Hwnd hwnd;
- if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
- hwnd = Hwnd.ObjectFromHandle(FosterParent);
- XDestroyWindow(DisplayHandle, FosterParent);
- hwnd.Dispose();
- }
- if (DisplayHandle != IntPtr.Zero) {
- XCloseDisplay(DisplayHandle);
- }
- DisplayHandle=display_handle;
- // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
- // been hacked to do this for us.
- Graphics.FromHdcInternal (DisplayHandle);
- // query for the render extension so
- // we can ignore the spurious
- // BadPicture errors that are
- // generated by cairo/render.
- XQueryExtension (DisplayHandle, "RENDER",
- ref render_major_opcode, ref render_first_event, ref render_first_error);
- // Debugging support
- if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
- XSynchronize(DisplayHandle, true);
- }
- if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
- ErrorExceptions = true;
- }
- // Generic X11 setup
- ScreenNo = XDefaultScreen(DisplayHandle);
- RootWindow = XRootWindow(DisplayHandle, ScreenNo);
- DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
- // Create the foster parent
- // it is important that border_width is kept in synch with the other XCreateWindow calls
- FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 0, UIntPtr.Zero, UIntPtr.Zero);
- if (FosterParent==IntPtr.Zero) {
- Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
- }
- DebugHelper.WriteLine ("FosterParent created 0x{0:x}", FosterParent.ToInt32());
- hwnd = new Hwnd();
- hwnd.Queue = ThreadQueue(Thread.CurrentThread);
- hwnd.WholeWindow = FosterParent;
- hwnd.ClientWindow = FosterParent;
- // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
- hwnd = new Hwnd();
- hwnd.Queue = ThreadQueue(Thread.CurrentThread);
- hwnd.whole_window = RootWindow;
- hwnd.ClientWindow = RootWindow;
- // For sleeping on the X11 socket
- listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
- IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
- listen.Bind(ep);
- listen.Listen(1);
- // To wake up when a timer is ready
- network_buffer = new byte[10];
- wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
- wake.Connect(listen.LocalEndPoint);
- // Make this non-blocking, so it doesn't
- // deadlock if too many wakes are sent
- // before the wake_receive end is polled
- wake.Blocking = false;
- wake_receive = listen.Accept();
- #if __MonoCS__
- pollfds = new Pollfd [2];
- pollfds [0] = new Pollfd ();
- pollfds [0].fd = XConnectionNumber (DisplayHandle);
- pollfds [0].events = PollEvents.POLLIN;
- pollfds [1] = new Pollfd ();
- pollfds [1].fd = wake_receive.Handle.ToInt32 ();
- pollfds [1].events = PollEvents.POLLIN;
- #endif
- Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
- Dnd = new X11Dnd (DisplayHandle, Keyboard);
- DoubleClickInterval = 500;
- HoverState.Interval = 500;
- HoverState.Timer = new Timer();
- HoverState.Timer.Enabled = false;
- HoverState.Timer.Interval = HoverState.Interval;
- HoverState.Timer.Tick += new EventHandler(MouseHover);
- HoverState.Size = new Size(4, 4);
- HoverState.X = -1;
- HoverState.Y = -1;
- ActiveWindow = IntPtr.Zero;
- FocusWindow = IntPtr.Zero;
- ModalWindows = new Stack(3);
- MouseState = MouseButtons.None;
- mouse_position = new Point(0, 0);
- Caret.Timer = new Timer();
- Caret.Timer.Interval = 500; // FIXME - where should this number come from?
- Caret.Timer.Tick += new EventHandler(CaretCallback);
- SetupAtoms();
- // Grab atom changes off the root window to catch certain WM events
- XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
- // Handle any upcoming errors
- ErrorHandler = new XErrorHandler(HandleError);
- XSetErrorHandler(ErrorHandler);
- } else {
- throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
- }
- }
- #endregion // Internal Methods
- #region Methods
- [Conditional ("DriverDebug")]
- static void DriverDebug (string format, params object [] args)
- {
- Console.WriteLine (String.Format (format, args));
- }
-
- int unixtime() {
- TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
- return (int) t.TotalSeconds;
- }
- static void SetupAtoms() {
- // make sure this array stays in sync with the statements below
- string [] atom_names = new string[] {
- "WM_PROTOCOLS",
- "WM_DELETE_WINDOW",
- "WM_TAKE_FOCUS",
- //"_NET_SUPPORTED",
- //"_NET_CLIENT_LIST",
- //"_NET_NUMBER_OF_DESKTOPS",
- "_NET_DESKTOP_GEOMETRY",
- //"_NET_DESKTOP_VIEWPORT",
- "_NET_CURRENT_DESKTOP",
- //"_NET_DESKTOP_NAMES",
- "_NET_ACTIVE_WINDOW",
- "_NET_WORKAREA",
- //"_NET_SUPPORTING_WM_CHECK",
- //"_NET_VIRTUAL_ROOTS",
- //"_NET_DESKTOP_LAYOUT",
- //"_NET_SHOWING_DESKTOP",
- //"_NET_CLOSE_WINDOW",
- //"_NET_MOVERESIZE_WINDOW",
- "_NET_WM_MOVERESIZE",
- //"_NET_RESTACK_WINDOW",
- //"_NET_REQUEST_FRAME_EXTENTS",
- "_NET_WM_NAME",
- //"_NET_WM_VISIBLE_NAME",
- //"_NET_WM_ICON_NAME",
- //"_NET_WM_VISIBLE_ICON_NAME",
- //"_NET_WM_DESKTOP",
- "_NET_WM_WINDOW_TYPE",
- "_NET_WM_STATE",
- //"_NET_WM_ALLOWED_ACTIONS",
- //"_NET_WM_STRUT",
- //"_NET_WM_STRUT_PARTIAL",
- //"_NET_WM_ICON_GEOMETRY",
- "_NET_WM_ICON",
- //"_NET_WM_PID",
- //"_NET_WM_HANDLED_ICONS",
- "_NET_WM_USER_TIME",
- "_NET_FRAME_EXTENTS",
- //"_NET_WM_PING",
- //"_NET_WM_SYNC_REQUEST",
- "_NET_SYSTEM_TRAY_OPCODE",
- //"_NET_SYSTEM_TRAY_ORIENTATION",
- "_NET_WM_STATE_MAXIMIZED_HORZ",
- "_NET_WM_STATE_MAXIMIZED_VERT",
- "_NET_WM_STATE_HIDDEN",
- "_XEMBED",
- "_XEMBED_INFO",
- "_MOTIF_WM_HINTS",
- "_NET_WM_STATE_SKIP_TASKBAR",
- "_NET_WM_STATE_ABOVE",
- "_NET_WM_STATE_MODAL",
- "_NET_WM_CONTEXT_HELP",
- "_NET_WM_WINDOW_OPACITY",
- //"_NET_WM_WINDOW_TYPE_DESKTOP",
- //"_NET_WM_WINDOW_TYPE_DOCK",
- //"_NET_WM_WINDOW_TYPE_TOOLBAR",
- //"_NET_WM_WINDOW_TYPE_MENU",
- "_NET_WM_WINDOW_TYPE_UTILITY",
- // "_NET_WM_WINDOW_TYPE_DIALOG",
- //"_NET_WM_WINDOW_TYPE_SPLASH",
- "_NET_WM_WINDOW_TYPE_NORMAL",
- "CLIPBOARD",
- "PRIMARY",
- "COMPOUND_TEXT",
- "UTF8_STRING",
- "UTF16_STRING",
- "RICHTEXTFORMAT",
- "TARGETS",
- "_SWF_AsyncAtom",
- "_SWF_PostMessageAtom",
- "_SWF_HoverAtom" };
- IntPtr[] atoms = new IntPtr [atom_names.Length];;
- XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
- int off = 0;
- WM_PROTOCOLS = atoms [off++];
- WM_DELETE_WINDOW = atoms [off++];
- WM_TAKE_FOCUS = atoms [off++];
- //_NET_SUPPORTED = atoms [off++];
- //_NET_CLIENT_LIST = atoms [off++];
- //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
- _NET_DESKTOP_GEOMETRY = atoms [off++];
- //_NET_DESKTOP_VIEWPORT = atoms [off++];
- _NET_CURRENT_DESKTOP = atoms [off++];
- //_NET_DESKTOP_NAMES = atoms [off++];
- _NET_ACTIVE_WINDOW = atoms [off++];
- _NET_WORKAREA = atoms [off++];
- //_NET_SUPPORTING_WM_CHECK = atoms [off++];
- //_NET_VIRTUAL_ROOTS = atoms [off++];
- //_NET_DESKTOP_LAYOUT = atoms [off++];
- //_NET_SHOWING_DESKTOP = atoms [off++];
- //_NET_CLOSE_WINDOW = atoms [off++];
- //_NET_MOVERESIZE_WINDOW = atoms [off++];
- _NET_WM_MOVERESIZE = atoms [off++];
- //_NET_RESTACK_WINDOW = atoms [off++];
- //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
- _NET_WM_NAME = atoms [off++];
- //_NET_WM_VISIBLE_NAME = atoms [off++];
- //_NET_WM_ICON_NAME = atoms [off++];
- //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
- //_NET_WM_DESKTOP = atoms [off++];
- _NET_WM_WINDOW_TYPE = atoms [off++];
- _NET_WM_STATE = atoms [off++];
- //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
- //_NET_WM_STRUT = atoms [off++];
- //_NET_WM_STRUT_PARTIAL = atoms [off++];
- //_NET_WM_ICON_GEOMETRY = atoms [off++];
- _NET_WM_ICON = atoms [off++];
- //_NET_WM_PID = atoms [off++];
- //_NET_WM_HANDLED_ICONS = atoms [off++];
- _NET_WM_USER_TIME = atoms [off++];
- _NET_FRAME_EXTENTS = atoms [off++];
- //_NET_WM_PING = atoms [off++];
- //_NET_WM_SYNC_REQUEST = atoms [off++];
- _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
- //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
- _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
- _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
- _NET_WM_STATE_HIDDEN = atoms [off++];
- _XEMBED = atoms [off++];
- _XEMBED_INFO = atoms [off++];
- _MOTIF_WM_HINTS = atoms [off++];
- _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
- _NET_WM_STATE_ABOVE = atoms [off++];
- _NET_WM_STATE_MODAL = atoms [off++];
- _NET_WM_CONTEXT_HELP = atoms [off++];
- _NET_WM_WINDOW_OPACITY = atoms [off++];
- //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
- //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
- //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
- //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
- _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
- // _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
- //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
- _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
- CLIPBOARD = atoms [off++];
- PRIMARY = atoms [off++];
- OEMTEXT = atoms [off++];
- UTF8_STRING = atoms [off++];
- UTF16_STRING = atoms [off++];
- RICHTEXTFORMAT = atoms [off++];
- TARGETS = atoms [off++];
- AsyncAtom = atoms [off++];
- PostAtom = atoms [off++];
- HoverState.Atom = atoms [off++];
- //DIB = (IntPtr)Atom.XA_PIXMAP;
- _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
- }
- void GetSystrayManagerWindow() {
- XGrabServer(DisplayHandle);
- SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
- XUngrabServer(DisplayHandle);
- XFlush(DisplayHandle);
- }
- void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
- SendNetWMMessage (window, message_type, l0, l1, l2, IntPtr.Zero);
- }
- void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2, IntPtr l3) {
- XEvent xev;
- xev = new XEvent();
- xev.ClientMessageEvent.type = XEventName.ClientMessage;
- xev.ClientMessageEvent.send_event = true;
- xev.ClientMessageEvent.window = window;
- xev.ClientMessageEvent.message_type = message_type;
- xev.ClientMessageEvent.format = 32;
- xev.ClientMessageEvent.ptr1 = l0;
- xev.ClientMessageEvent.ptr2 = l1;
- xev.ClientMessageEvent.ptr3 = l2;
- xev.ClientMessageEvent.ptr4 = l3;
- XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
- }
- void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
- XEvent xev;
- xev = new XEvent();
- xev.ClientMessageEvent.type = XEventName.ClientMessage;
- xev.ClientMessageEvent.send_event = true;
- xev.ClientMessageEvent.window = window;
- xev.ClientMessageEvent.message_type = message_type;
- xev.ClientMessageEvent.format = 32;
- xev.ClientMessageEvent.ptr1 = l0;
- xev.ClientMessageEvent.ptr2 = l1;
- xev.ClientMessageEvent.ptr3 = l2;
- XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
- }
- // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
- // WM_CREATE and WM_DESTROY causes
- void SendParentNotify(IntPtr child, Msg cause, int x, int y)
- {
- Hwnd hwnd;
-
- if (child == IntPtr.Zero) {
- return;
- }
-
- hwnd = Hwnd.GetObjectFromWindow (child);
-
- if (hwnd == null) {
- return;
- }
-
- if (hwnd.Handle == IntPtr.Zero) {
- return;
- }
-
- if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
- return;
- }
-
- if (hwnd.Parent == null) {
- return;
- }
-
- if (hwnd.Parent.Handle == IntPtr.Zero) {
- return;
- }
- if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
- SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
- } else {
- SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
- }
-
- SendParentNotify (hwnd.Parent.Handle, cause, x, y);
- }
-
- bool StyleSet (int s, WindowStyles ws)
- {
- return (s & (int)ws) == (int)ws;
- }
- bool ExStyleSet (int ex, WindowExStyles exws)
- {
- return (ex & (int)exws) == (int)exws;
- }
- internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
- {
- return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
- }
-
- internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
- {
- /*
- * If this is a form with no window manager, X is handling all the border and caption painting
- * so remove that from the area (since the area we set of the window here is the part of the window
- * we're painting in only)
- */
- Rectangle rect = hwnd.ClientRect;
- Form form = ctrl as Form;
- CreateParams cp = null;
- if (form != null)
- cp = form.GetCreateParams ();
- if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
- Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
- Rectangle xrect = rect;
- xrect.Y -= borders.top;
- xrect.X -= borders.left;
- xrect.Width += borders.left + borders.right;
- xrect.Height += borders.top + borders.bottom;
- rect = xrect;
- }
-
- if (rect.Width < 1 || rect.Height < 1) {
- rect.Width = 1;
- rect.Height = 1;
- rect.X = -5;
- rect.Y = -5;
- }
-
- return rect;
- }
- internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
- {
- return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
- }
- internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
- {
- /*
- * If this is a form with no window manager, X is handling all the border and caption painting
- * so remove that from the area (since the area we set of the window here is the part of the window
- * we're painting in only)
- */
- Form form = cp.control as Form;
- if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
- Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
- Size xrect = size;
- xrect.Width -= borders.left + borders.right;
- xrect.Height -= borders.top + borders.bottom;
- size = xrect;
- }
- if (size.Height == 0)
- size.Height = 1;
- if (size.Width == 0)
- size.Width = 1;
- return size;
- }
- internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
- {
- /*
- * If this is a form with no window manager, X is handling all the border and caption painting
- * so remove that from the area (since the area we set of the window here is the part of the window
- * we're painting in only)
- */
- Size rect = new Size (xWidth, xHeight);
- Form form = cp.control as Form;
- if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
- Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
- Size xrect = rect;
- xrect.Width += borders.left + borders.right;
- xrect.Height += borders.top + borders.bottom;
- rect = xrect;
- }
- return rect;
- }
-
- internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
- {
- IntPtr dummy;
- int x, y;
- Hwnd.Borders frame;
- XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
- frame = FrameExtents (hwnd.whole_window);
- x -= frame.left;
- y -= frame.top;
-
- return new Point (x, y);
- }
-
- void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out bool border_static, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
- caption_height = 0;
- tool_caption_height = 19;
- border_static = false;
- if (StyleSet (Style, WindowStyles.WS_CHILD)) {
- if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
- border_style = FormBorderStyle.Fixed3D;
- } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
- border_style = FormBorderStyle.Fixed3D;
- border_static = true;
- } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
- border_style = FormBorderStyle.None;
- } else {
- border_style = FormBorderStyle.FixedSingle;
- }
- title_style = TitleStyle.None;
-
- if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
- caption_height = 19;
- if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
- title_style = TitleStyle.Tool;
- } else {
- title_style = TitleStyle.Normal;
- }
- }
- if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
- caption_height = 19;
- if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
- ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
- border_style = (FormBorderStyle) 0xFFFF;
- } else {
- border_style = FormBorderStyle.None;
- }
- }
- } else {
- title_style = TitleStyle.None;
- if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
- if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
- title_style = TitleStyle.Tool;
- } else {
- title_style = TitleStyle.Normal;
- }
- }
- border_style = FormBorderStyle.None;
- if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
- if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
- border_style = FormBorderStyle.SizableToolWindow;
- } else {
- border_style = FormBorderStyle.Sizable;
- }
- } else {
- if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
- if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
- border_style = FormBorderStyle.Fixed3D;
- } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
- border_style = FormBorderStyle.Fixed3D;
- border_static = true;
- } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
- border_style = FormBorderStyle.FixedDialog;
- } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
- border_style = FormBorderStyle.FixedToolWindow;
- } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
- border_style = FormBorderStyle.FixedSingle;
- }
- } else {
- if (StyleSet (Style, WindowStyles.WS_BORDER)) {
- border_style = FormBorderStyle.FixedSingle;
- }
- }
- }
- }
- }
- void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
- DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.border_static, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
- }
- void SetWMStyles(Hwnd hwnd, CreateParams cp) {
- MotifWmHints mwmHints;
- MotifFunctions functions;
- MotifDecorations decorations;
- int[] atoms;
- int atom_count;
- Rectangle client_rect;
- Form form;
- IntPtr window_type;
- bool hide_from_taskbar;
- IntPtr transient_for_parent;
-
- // Windows we manage ourselves don't need WM window styles.
- if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
- return;
- }
- atoms = new int[8];
- mwmHints = new MotifWmHints();
- functions = 0;
- decorations = 0;
- window_type = _NET_WM_WINDOW_TYPE_NORMAL;
- transient_for_parent = IntPtr.Zero;
- mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
- mwmHints.functions = (IntPtr)0;
- mwmHints.decorations = (IntPtr)0;
- form = cp.control as Form;
- if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
- /* tool windows get no window manager
- decorations.
- */
- /* just because the window doesn't get any decorations doesn't
- mean we should disable the functions. for instance, without
- MotifFunctions.Maximize, changing the windowstate to Maximized
- is ignored by metacity. */
- functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
- } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
- /* allow borderless window to be maximized */
- functions |= MotifFunctions.All | MotifFunctions.Resize;
- } else {
- if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
- functions |= MotifFunctions.Move;
- decorations |= MotifDecorations.Title | MotifDecorations.Menu;
- }
- if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
- functions |= MotifFunctions.Move | MotifFunctions.Resize;
- decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
- }
- if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
- functions |= MotifFunctions.Minimize;
- decorations |= MotifDecorations.Minimize;
- }
- if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
- functions |= MotifFunctions.Maximize;
- decorations |= MotifDecorations.Maximize;
- }
- if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
- functions |= MotifFunctions.Resize;
- decorations |= MotifDecorations.ResizeH;
- }
- if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
- decorations |= MotifDecorations.Border;
- }
- if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
- decorations |= MotifDecorations.Border;
- }
-
- if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
- decorations |= MotifDecorations.Border;
- }
- if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
- functions |= MotifFunctions.Close;
- }
- else {
- functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
- decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
- if (cp.Caption == "") {
- functions &= ~MotifFunctions.Move;
- decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
- }
- }
- }
- if ((functions & MotifFunctions.Resize) == 0) {
- hwnd.fixed_size = true;
- Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
- SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
- } else {
- hwnd.fixed_size = false;
- }
- mwmHints.functions = (IntPtr)functions;
- mwmHints.decorations = (IntPtr)decorations;
- DriverDebug ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
- if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
- // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
- // and get those windows in front of their parents
- window_type = _NET_WM_WINDOW_TYPE_UTILITY;
- } else {
- window_type = _NET_WM_WINDOW_TYPE_NORMAL;
- }
-
- if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
- hide_from_taskbar = true;
- } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) {
- hide_from_taskbar = true;
- } else {
- hide_from_taskbar = false;
- }
- if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
- if (form != null && !hwnd.reparented) {
- if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
- Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
- if (owner_hwnd != null)
- transient_for_parent = owner_hwnd.whole_window;
- }
- }
- }
- if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
- transient_for_parent = hwnd.parent.whole_window;
- }
-
- FormWindowState current_state = GetWindowState (hwnd.Handle);
- if (current_state == (FormWindowState)(-1))
- current_state = FormWindowState.Normal;
- client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
- lock (XlibLock) {
- atom_count = 0;
- atoms [0] = window_type.ToInt32 ();
- XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
- XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
- if (transient_for_parent != IntPtr.Zero) {
- XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
- }
- MoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
- if (hide_from_taskbar) {
- /* this line keeps the window from showing up in gnome's taskbar */
- atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
- }
- /* we need to add these atoms in the
- * event we're maximized, since we're
- * replacing the existing
- * _NET_WM_STATE here. If we don't
- * add them, future calls to
- * GetWindowState will return Normal
- * for a window which is maximized. */
- if (current_state == FormWindowState.Maximized) {
- atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
- atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
- }
-
- if (form != null && form.Modal) {
- atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
- }
-
- XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
- atom_count = 0;
- IntPtr[] atom_ptrs = new IntPtr[2];
- atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
- if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
- atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
- }
- XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
- }
- }
- void SetIcon(Hwnd hwnd, Icon icon)
- {
- if (icon == null) {
- // XXX
- // This really needs to do whatever it
- // takes to remove the window manager
- // menu, not just delete the ICON
- // property. This will cause metacity
- // to use the "no icon set" icon, and
- // we'll still have an icon.
- XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
- }
- else {
- Bitmap bitmap;
- int size;
- IntPtr[] data;
- int index;
- bitmap = icon.ToBitmap();
- index = 0;
- size = bitmap.Width * bitmap.Height + 2;
- data = new IntPtr[size];
- data[index++] = (IntPtr)bitmap.Width;
- data[index++] = (IntPtr)bitmap.Height;
- for (int y = 0; y < bitmap.Height; y++) {
- for (int x = 0; x < bitmap.Width; x++) {
- data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
- }
- }
- XChangeProperty (DisplayHandle, hwnd.whole_window,
- _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
- PropertyMode.Replace, data, size);
- }
- }
- void WakeupMain () {
- try {
- wake.Send (new byte [] { 0xFF });
- } catch (SocketException ex) {
- if (ex.SocketErrorCode != SocketError.WouldBlock) {
- throw;
- }
- }
- }
- XEventQueue ThreadQueue(Thread thread) {
- XEventQueue queue;
- queue = (XEventQueue)MessageQueues[thread];
- if (queue == null) {
- queue = new XEventQueue(thread);
- MessageQueues[thread] = queue;
- }
- return queue;
- }
- void TranslatePropertyToClipboard(IntPtr property) {
- IntPtr actual_atom;
- int actual_format;
- IntPtr nitems;
- IntPtr bytes_after;
- IntPtr prop = IntPtr.Zero;
- Clipboard.Item = null;
- XGetWindowProperty(DisplayHandle, FosterParent, property, IntPtr.Zero, new IntPtr (0x7fffffff), true, (IntPtr)Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
- if ((long)nitems > 0) {
- if (property == (IntPtr)Atom.XA_STRING) {
- // Xamarin-5116: PtrToStringAnsi expects to get UTF-8, but we might have
- // Latin-1 instead.
- var s = Marshal.PtrToStringAnsi (prop);
- if (string.IsNullOrEmpty (s)) {
- var sb = new StringBuilder ();
- for (int i = 0; i < (int)nitems; i++) {
- var b = Marshal.ReadByte (prop, i);
- sb.Append ((char)b);
- }
- s = sb.ToString ();
- }
- // Some X managers/apps pass unicode chars as escaped strings, so
- // we may need to unescape them.
- Clipboard.Item = UnescapeUnicodeFromAnsi (s);
- } else if (property == (IntPtr)Atom.XA_BITMAP) {
- // FIXME - convert bitmap to image
- } else if (property == (IntPtr)Atom.XA_PIXMAP) {
- // FIXME - convert pixmap to image
- } else if (property == OEMTEXT) {
- Clipboard.Item = UnescapeUnicodeFromAnsi (Marshal.PtrToStringAnsi(prop));
- } else if (property == UTF8_STRING) {
- byte [] buffer = new byte [(int)nitems];
- for (int i = 0; i < (int)nitems; i++)
- buffer [i] = Marshal.ReadByte (prop, i);
- Clipboard.Item = Encoding.UTF8.GetString (buffer);
- } else if (property == UTF16_STRING) {
- Clipboard.Item = Marshal.PtrToStringUni (prop, Encoding.Unicode.GetMaxCharCount ((int)nitems));
- } else if (property == RICHTEXTFORMAT)
- Clipboard.Item = Marshal.PtrToStringAnsi(prop);
- else if (DataFormats.ContainsFormat (property.ToInt32 ())) {
- if (DataFormats.GetFormat (property.ToInt32 ()).is_serializable) {
- MemoryStream memory_stream = new MemoryStream ((int)nitems);
- for (int i = 0; i < (int)nitems; i++)
- memory_stream.WriteByte (Marshal.ReadByte (prop, i));
- memory_stream.Position = 0;
- BinaryFormatter formatter = new BinaryFormatter ();
- Clipboard.Item = formatter.Deserialize (memory_stream);
- memory_stream.Close ();
- }
- }
- XFree(prop);
- }
- }
- string UnescapeUnicodeFromAnsi (string value)
- {
- if (value == null || value.IndexOf ("\\u") == -1)
- return value;
- StringBuilder sb = new StringBuilder (value.Length);
- int start, pos;
- start = pos = 0;
- while (start < value.Length) {
- pos = value.IndexOf ("\\u", start);
- if (pos == -1)
- break;
- sb.Append (value, start, pos - start);
- pos += 2;
- start = pos;
- int length = 0;
- while (pos < value.Length) {
- if (!ValidHexDigit (value [pos]))
- break;
- length++;
- pos++;
- }
- int res;
- if (!Int32.TryParse (value.Substring (start, length), System.Globalization.NumberStyles.HexNumber,
- null, out res))
- return value; // Error, return the unescaped original value.
-
- sb.Append ((char)res);
- start = pos;
- }
- // Append any remaining data.
- if (start < value.Length)
- sb.Append (value, start, value.Length - start);
- return sb.ToString ();
- }
- private static bool ValidHexDigit (char e)
- {
- return Char.IsDigit (e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
- }
- void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
- // Don't waste time
- if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
- return;
- }
- // Keep the invalid area as small as needed
- if ((x + width) > hwnd.width) {
- width = hwnd.width - x;
- }
- if ((y + height) > hwnd.height) {
- height = hwnd.height - y;
- }
- if (client) {
- hwnd.AddInvalidArea(x, y, width, height);
- if (!hwnd.expose_pending) {
- if (!hwnd.nc_expose_pending) {
- hwnd.Queue.Paint.Enqueue(hwnd);
- }
- hwnd.expose_pending = true;
- }
- } else {
- hwnd.AddNcInvalidArea (x, y, width, height);
-
- if (!hwnd.nc_expose_pending) {
- if (!hwnd.expose_pending) {
- hwnd.Queue.Paint.Enqueue(hwnd);
- }
- hwnd.nc_expose_pending = true;
- }
- }
- }
- static Hwnd.Borders FrameExtents (IntPtr window)
- {
- IntPtr actual_atom;
- int actual_format;
- IntPtr nitems;
- IntPtr bytes_after;
- IntPtr prop = IntPtr.Zero;
- Hwnd.Borders rect = new Hwnd.Borders ();
- XGetWindowProperty (DisplayHandle, window, _NET_FRAME_EXTENTS, IntPtr.Zero, new IntPtr (16), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
- if (prop != IntPtr.Zero) {
- if (nitems.ToInt32 () == 4) {
- rect.left = Marshal.ReadInt32 (prop, 0);
- rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
- rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
- rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
- }
- XFree (prop);
- }
-
- return rect;
- }
- void AddConfigureNotify (XEvent xevent) {
- Hwnd hwnd;
- hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
- // Don't waste time
- if (hwnd == null || hwnd.zombie) {
- return;
- }
- if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
- if (hwnd.parent == null) {
- // The location given by the event is not reliable between different wm's,
- // so use an alternative way of getting it.
- Point location = GetTopLevelWindowLocation (hwnd);
- hwnd.x = location.X;
- hwnd.y = location.Y;
- }
- // XXX this sucks. this isn't thread safe
- Control ctrl = Control.FromHandle (hwnd.Handle);
- Size TranslatedSize;
- if (ctrl != null) {
- TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
- } else {
- TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
- }
- hwnd.width = TranslatedSize.Width;
- hwnd.height = TranslatedSize.Height;
- hwnd.ClientRect = Rectangle.Empty;
- DriverDebug ("AddConfigureNotify (hwnd.Handle = {1}, final hwnd.rect = {0}, reported rect={2})",
- new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle,
- new Rectangle (xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.width));
- lock (hwnd.configure_lock) {
- if (!hwnd.configure_pending) {
- hwnd.Queue.EnqueueLocked (xevent);
- hwnd.configure_pending = true;
- }
- }
- }
- // We drop configure events for Client windows
- }
- void ShowCaret() {
- if ((Caret.gc == IntPtr.Zero) || Caret.On) {
- return;
- }
- Caret.On = true;
- lock (XlibLock) {
- XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
- }
- }
- void HideCaret() {
- if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
- return;
- }
- Caret.On = false;
- lock (XlibLock) {
- XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
- }
- }
- int NextTimeout (ArrayList timers, DateTime now) {
- int timeout = 0;
- foreach (Timer timer in timers) {
- int next = (int) (timer.Expires - now).TotalMilliseconds;
- if (next < 0) {
- return 0; // Have a timer that has already expired
- }
- if (next < timeout) {
- timeout = next;
- }
- }
- if (timeout < Timer.Minimum) {
- timeout = Timer.Minimum;
- }
- if (timeout > 1000)
- timeout = 1000;
- return timeout;
- }
- void CheckTimers (ArrayList timers, DateTime now) {
- int count;
- count = timers.Count;
- if (count == 0)
- return;
- for (int i = 0; i < timers.Count; i++) {
- Timer timer;
- timer = (Timer) timers [i];
- if (timer.Enabled && timer.Expires <= now && !timer.Busy) {
- // Timer ticks:
- // - Before MainForm.OnLoad if DoEvents () is called.
- // - After MainForm.OnLoad if not.
- //
- if (in_doevents ||
- (Application.MWFThread.Current.Context != null &&
- (Application.MWFThread.Current.Context.MainForm == null ||
- Application.MWFThread.Current.Context.MainForm.IsLoaded))) {
- timer.Busy = true;
- timer.Update (now);
- timer.FireTick ();
- timer.Busy = false;
- }
- }
- }
- }
- void WaitForHwndMessage (Hwnd hwnd, Msg message) {
- WaitForHwndMessage (hwnd, message, false);
- }
- void WaitForHwndMessage (Hwnd hwnd, Msg message, bool process) {
- MSG msg = new MSG ();
- XEventQueue queue;
- queue = ThreadQueue(Thread.CurrentThread);
- queue.DispatchIdle = false;
- bool done = false;
- string key = hwnd.Handle + ":" + message;
- if (!messageHold.ContainsKey (key))
- messageHold.Add (key, 1);
- else
- messageHold[key] = ((int)messageHold[key]) + 1;
-
-
- do {
- DebugHelper.WriteLine ("Waiting for message " + message + " on hwnd " + String.Format("0x{0:x}", hwnd.Handle.ToInt32 ()));
- DebugHelper.Indent ();
-
- if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
- if ((Msg)msg.message == Msg.WM_QUIT) {
- PostQuitMessage (0);
- done = true;
- }
- else {
-
- DebugHelper.WriteLine ("PeekMessage got " + msg);
-
- if (msg.hwnd == hwnd.Handle) {
- if ((Msg)msg.message == message) {
- if (process) {
- TranslateMessage (ref msg);
- DispatchMessage (ref msg);
- }
- break;
- }
- else if ((Msg)msg.message == Msg.WM_DESTROY)
- done = true;
- }
- TranslateMessage (ref msg);
- DispatchMessage (ref msg);
- }
- }
-
- done = !messageHold.ContainsKey (key) || ((int)messageHold[key] < 1) || done;
- } while (!done);
-
- messageHold.Remove (k…