/mcs/class/Managed.Windows.Forms/System.Windows.Forms.X11Internal/X11Display.cs
C# | 2710 lines | 1994 code | 525 blank | 191 comment | 424 complexity | fcb6fc812e50ee5e684ec41fdd689f1c MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- // 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) 2006 Novell, Inc. (http://www.novell.com)
- //
- //
- using System;
- 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.Text;
- using System.Threading;
- using System.Windows.Forms;
- // Only do the poll when building with mono for now
- #if __MonoCS__
- using Mono.Unix.Native;
- #endif
- namespace System.Windows.Forms.X11Internal {
- internal class X11Display {
- IntPtr display; /* our X handle */
- // XXX internal because X11Hwnd needs them
- internal IntPtr CustomVisual; // Visual for window creation
- internal IntPtr CustomColormap; // Colormap for window creation
- X11Keyboard Keyboard;
- internal X11Dnd Dnd; // XXX X11Hwnd needs it to enable Dnd
- bool detectable_key_auto_repeat;
- X11Atoms atoms;
- X11RootHwnd root_hwnd;
- X11Hwnd foster_hwnd;
- // Clipboard
- IntPtr ClipMagic;
- ClipboardStruct Clipboard; // Our clipboard
- // Focus tracking
- internal X11Hwnd ActiveWindow;
- X11Hwnd FocusWindow;
- // Modality support
- Stack ModalWindows; // Stack of our modal windows
- // Caret
- CaretStruct Caret;
- // mouse hover message generation
- // XXX internal because X11Atoms needs to access it..
- internal HoverStruct HoverState;
- // double click message generation
- ClickStruct ClickPending;
- int DoubleClickInterval; // msec; max interval between clicks to count as double click
- // Support for mouse grab
- GrabStruct Grab;
- // Cursors
- IntPtr LastCursorWindow; // The last window we set the cursor on
- IntPtr LastCursorHandle; // The handle that was last set on LastCursorWindow
- IntPtr OverrideCursorHandle; // The cursor that is set to override any other cursors
- // State
- Point MousePosition; // Last position of mouse, in screen coords
- MouseButtons MouseState; // Last state of mouse buttons
- XErrorHandler ErrorHandler; // Error handler delegate
- bool ErrorExceptions; // Throw exceptions on X errors
- Thread event_thread; // the background thread that just watches our X socket
- #if __MonoCS__
- Pollfd[] pollfds;
- #endif
- public X11Display (IntPtr display)
- {
- if (display == IntPtr.Zero) {
- throw new ArgumentNullException("Display",
- "Could not open display (X-Server required. Check you DISPLAY environment variable)");
- }
- this.display = display;
- // Debugging support
- if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
- Xlib.XSynchronize (display, true);
- }
- if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
- ErrorExceptions = true;
- }
- atoms = new X11Atoms (this);
- 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 = null;
- FocusWindow = null;
- ModalWindows = new Stack(3);
- MouseState = MouseButtons.None;
- MousePosition = 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);
- // XXX multiscreen work here
- root_hwnd = new X11RootHwnd (this, Xlib.XRootWindow (display, DefaultScreen));
- // XXX do we need a per-screen foster parent?
- // Create the foster parent
- foster_hwnd = new X11Hwnd (this,
- Xlib.XCreateSimpleWindow (display, root_hwnd.WholeWindow,
- 0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero));
- #if __MonoCS__
- pollfds = new Pollfd [1];
- pollfds [0] = new Pollfd ();
- pollfds [0].fd = Xlib.XConnectionNumber (display);
- pollfds [0].events = PollEvents.POLLIN;
- #endif
- Keyboard = new X11Keyboard(display, foster_hwnd.Handle);
- Dnd = new X11Dnd (display, Keyboard);
- ErrorExceptions = false;
- // Handle any upcoming errors
- ErrorHandler = new XErrorHandler (HandleError);
- Xlib.XSetErrorHandler (ErrorHandler);
- X11DesktopColors.Initialize(); // XXX we need to figure out how to make this display specific?
- // Disable keyboard autorepeat
- try {
- Xlib.XkbSetDetectableAutoRepeat (display, 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;
- }
- // we re-set our error handler here, X11DesktopColor stuff might have stolen it (gtk does)
- Xlib.XSetErrorHandler (ErrorHandler);
- // create our event thread (just sits on the X socket waiting for events)
- event_thread = new Thread (new ThreadStart (XEventThread));
- event_thread.IsBackground = true;
- event_thread.Start ();
- }
- #region Callbacks
- private void MouseHover(object sender, EventArgs e)
- {
- HoverState.Timer.Enabled = false;
- if (HoverState.Window != IntPtr.Zero) {
- X11Hwnd hwnd = (X11Hwnd)Hwnd.GetObjectFromWindow (HoverState.Window);
- if (hwnd != null) {
- XEvent xevent = new XEvent ();
- xevent.type = XEventName.ClientMessage;
- xevent.ClientMessageEvent.display = display;
- xevent.ClientMessageEvent.window = HoverState.Window;
- xevent.ClientMessageEvent.message_type = HoverState.Atom;
- xevent.ClientMessageEvent.format = 32;
- xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
- hwnd.Queue.Enqueue (xevent);
- }
- }
- }
- private void CaretCallback (object sender, EventArgs e)
- {
- if (Caret.Paused) {
- return;
- }
- Caret.On = !Caret.On;
- Xlib.XDrawLine (display, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
- }
- internal string WhereString ()
- {
- StackTrace stack;
- StackFrame frame;
- string newline;
- string unknown;
- StringBuilder sb;
- MethodBase method;
- newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
- unknown = Locale.GetText("<unknown method>");
- sb = new StringBuilder();
- stack = new StackTrace(true);
- for (int i = 0; i < stack.FrameCount; i++) {
- frame = stack.GetFrame (i);
- sb.Append(newline);
- method = frame.GetMethod();
- if (method != null) {
- if (frame.GetFileLineNumber() != 0)
- sb.AppendFormat ("{0}.{1} () [{2}:{3}]",
- method.DeclaringType.FullName, method.Name,
- Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
- else
- sb.AppendFormat ("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
- } else {
- sb.Append(unknown);
- }
- }
- return sb.ToString();
- }
- private int HandleError (IntPtr display, ref XErrorEvent error_event)
- {
- if (ErrorExceptions)
- throw new X11Exception (error_event.display, error_event.resourceid,
- error_event.serial, error_event.error_code,
- error_event.request_code, error_event.minor_code);
- else
- Console.WriteLine ("X11 Error encountered: {0}{1}\n",
- X11Exception.GetMessage(error_event.display, error_event.resourceid,
- error_event.serial, error_event.error_code,
- error_event.request_code, error_event.minor_code),
- WhereString());
- return 0;
- }
- #endregion // Callbacks
- private void ShowCaret()
- {
- if ((Caret.gc == IntPtr.Zero) || Caret.On) {
- return;
- }
- Caret.On = true;
- Xlib.XDrawLine (display, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
- }
- private void HideCaret()
- {
- if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
- return;
- }
- Caret.On = false;
- Xlib.XDrawLine (display, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
- }
- public void CaretVisible (IntPtr handle, bool visible)
- {
- if (Caret.Hwnd == handle) {
- if (visible) {
- if (!Caret.Visible) {
- Caret.Visible = true;
- ShowCaret();
- Caret.Timer.Start();
- }
- } else {
- Caret.Visible = false;
- Caret.Timer.Stop();
- HideCaret();
- }
- }
- }
- public void AudibleAlert ()
- {
- Xlib.XBell (display, 0);
- }
- public void Flush ()
- {
- Xlib.XFlush (display);
- }
- public void Close ()
- {
- // XXX shut down the event_thread
- Xlib.XCloseDisplay (display);
- }
- public IntPtr XGetParent(IntPtr handle)
- {
- IntPtr Root;
- IntPtr Parent;
- IntPtr Children;
- int ChildCount;
- Xlib.XQueryTree (display, handle, out Root, out Parent, out Children, out ChildCount);
- if (Children!=IntPtr.Zero) {
- Xlib.XFree(Children);
- }
- return Parent;
- }
- public bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt)
- {
- IntPtr SystrayMgrWindow;
- Xlib.XGrabServer (display);
- SystrayMgrWindow = Xlib.XGetSelectionOwner (display, Atoms._NET_SYSTEM_TRAY_S);
- Xlib.XUngrabServer (display);
- if (SystrayMgrWindow != IntPtr.Zero) {
- XSizeHints size_hints;
- X11Hwnd hwnd;
- hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
- #if DriverDebug
- Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}",
- hwnd.WholeWindow.ToInt32(), hwnd.ClientWindow.ToInt32());
- #endif
- // Oh boy.
- if (hwnd.ClientWindow != hwnd.WholeWindow) {
- Xlib.XDestroyWindow (display, hwnd.ClientWindow);
- hwnd.ClientWindow = hwnd.WholeWindow;
- try {
- hwnd.Queue.Lock ();
- /* by virtue of the way the tests are ordered when determining if it's PAINT
- or NCPAINT, ClientWindow == WholeWindow will always be PAINT. So, if we're
- waiting on an nc_expose, drop it and remove the hwnd from the list (unless
- there's a pending expose). */
- hwnd.PendingNCExpose = false;
- }
- finally {
- hwnd.Queue.Unlock ();
- }
- }
- size_hints = new XSizeHints();
- size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
- size_hints.min_width = 24;
- size_hints.min_height = 24;
- size_hints.max_width = 24;
- size_hints.max_height = 24;
- size_hints.base_width = 24;
- size_hints.base_height = 24;
- Xlib.XSetWMNormalHints (display, hwnd.WholeWindow, ref size_hints);
- int[] atoms = new int[2];
- atoms [0] = 1; // Version 1
- atoms [1] = 1; // we want to be mapped
- // This line cost me 3 days...
- Xlib.XChangeProperty (display,
- hwnd.WholeWindow, Atoms._XEMBED_INFO, Atoms._XEMBED_INFO, 32,
- PropertyMode.Replace, atoms, 2);
- // Need to pick some reasonable defaults
- tt = new ToolTip();
- tt.AutomaticDelay = 100;
- tt.InitialDelay = 250;
- tt.ReshowDelay = 250;
- tt.ShowAlways = true;
- if ((tip != null) && (tip != string.Empty)) {
- tt.SetToolTip(Control.FromHandle(handle), tip);
- tt.Active = true;
- } else {
- tt.Active = false;
- }
- SendNetClientMessage (SystrayMgrWindow,
- Atoms._NET_SYSTEM_TRAY_OPCODE,
- IntPtr.Zero,
- (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK,
- hwnd.WholeWindow);
- return true;
- }
- tt = null;
- return false;
- }
- public bool SystrayChange (IntPtr handle, string tip, Icon icon, ref ToolTip tt)
- {
- Control control;
- control = Control.FromHandle(handle);
- if (control != null && tt != null) {
- tt.SetToolTip(control, tip);
- tt.Active = true;
- return true;
- } else {
- return false;
- }
- }
- public void SystrayRemove(IntPtr handle, ref ToolTip tt)
- {
- #if GTKSOCKET_SUPPORTS_REPARENTING
- X11Hwnd hwnd;
- hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
- /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
- * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
- * 2. The client can reparent its window out of the embedder window.
- * 3. The client can destroy its window.
- *
- * this call to SetParent is case 2, but in
- * the spec it also mentions that gtk doesn't
- * support this at present. Looking at HEAD
- * gtksocket-x11.c jives with this statement.
- *
- * so we can't reparent. we have to destroy.
- */
- SetParent(hwnd.WholeWindow, FosterParent);
- #else
- Control control = Control.FromHandle(handle);
- if (control is NotifyIcon.NotifyIconWindow)
- ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
- #endif
- // The caller can now re-dock it later...
- if (tt != null) {
- tt.Dispose();
- tt = null;
- }
- }
- public void ResetMouseHover (X11Hwnd hovering)
- {
- HoverState.Timer.Enabled = hovering != null;
- HoverState.X = MousePosition.X;
- HoverState.Y = MousePosition.Y;
- HoverState.Window = hovering == null ? IntPtr.Zero : hovering.Handle;
- }
- public void ShowCursor (bool show)
- {
- ; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
- }
- public void SetModal (X11Hwnd hwnd, bool Modal)
- {
- if (Modal) {
- ModalWindows.Push(hwnd);
- } else {
- // XXX do we need to pop until the
- // hwnd is off the stack? or just the
- // most recently pushed hwnd?
- if (ModalWindows.Contains(hwnd)) {
- ModalWindows.Pop();
- }
- if (ModalWindows.Count > 0) {
- X11Hwnd top_hwnd = (X11Hwnd)ModalWindows.Peek();
- top_hwnd.Activate();
- }
- }
- }
- public TransparencySupport SupportsTransparency ()
- {
- // compiz adds _NET_WM_WINDOW_OPACITY to _NET_SUPPORTED on the root window, check for that
- return ((IList)root_hwnd._NET_SUPPORTED).Contains (Atoms._NET_WM_WINDOW_OPACITY) ? TransparencySupport.GetSet : TransparencySupport.None;
- }
- public void SendAsyncMethod (AsyncMethodData method)
- {
- X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(method.Handle);
- XEvent xevent = new XEvent ();
- xevent.type = XEventName.ClientMessage;
- xevent.ClientMessageEvent.display = display;
- xevent.ClientMessageEvent.window = method.Handle;
- xevent.ClientMessageEvent.message_type = Atoms.AsyncAtom;
- xevent.ClientMessageEvent.format = 32;
- xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
- hwnd.Queue.Enqueue (xevent);
- }
- delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
- public IntPtr SendMessage (IntPtr handle, Msg message, IntPtr wParam, IntPtr lParam)
- {
- X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
- if (hwnd == null)
- return IntPtr.Zero;
- if (hwnd.Queue.Thread != Thread.CurrentThread) {
- AsyncMethodResult result;
- AsyncMethodData data;
- result = new AsyncMethodResult ();
- data = new AsyncMethodData ();
- data.Handle = hwnd.Handle;
- data.Method = new WndProcDelegate (NativeWindow.WndProc);
- data.Args = new object[] { hwnd.Handle, message, wParam, lParam };
- data.Result = result;
-
- SendAsyncMethod (data);
- #if DriverDebug || DriverDebugThreads
- Console.WriteLine ("Sending {0} message across.", message);
- #endif
- return IntPtr.Zero;
- }
- else {
- return NativeWindow.WndProc (hwnd.Handle, message, wParam, lParam);
- }
- }
- public int SendInput (IntPtr handle, Queue keys) {
- if (handle == IntPtr.Zero)
- return 0;
- int count = keys.Count;
- Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
- while (keys.Count > 0) {
-
- MSG msg = (MSG)keys.Dequeue();
- XEvent xevent = new XEvent ();
- xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
- xevent.KeyEvent.display = display;
- if (hwnd != null) {
- xevent.KeyEvent.window = hwnd.whole_window;
- } else {
- xevent.KeyEvent.window = IntPtr.Zero;
- }
- xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
- hwnd.Queue.EnqueueLocked (xevent);
- }
- return count;
- }
- // FIXME - I think this should just enqueue directly
- public bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam)
- {
- XEvent xevent = new XEvent ();
- X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
- xevent.type = XEventName.ClientMessage;
- xevent.ClientMessageEvent.display = display;
- if (hwnd != null) {
- xevent.ClientMessageEvent.window = hwnd.WholeWindow;
- } else {
- xevent.ClientMessageEvent.window = IntPtr.Zero;
- }
- xevent.ClientMessageEvent.message_type = Atoms.PostAtom;
- xevent.ClientMessageEvent.format = 32;
- xevent.ClientMessageEvent.ptr1 = handle;
- xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
- xevent.ClientMessageEvent.ptr3 = wparam;
- xevent.ClientMessageEvent.ptr4 = lparam;
- hwnd.Queue.Enqueue (xevent);
- return true;
- }
- public void SendNetWMMessage (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;
- Xlib.XSendEvent (display, root_hwnd.Handle, false,
- new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
- }
- public 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;
- Xlib.XSendEvent (display, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
- }
- public bool TranslateMessage (ref MSG msg)
- {
- return Keyboard.TranslateMessage (ref msg);
- }
- public IntPtr DispatchMessage (ref MSG msg)
- {
- return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
- }
- private void QueryPointer (IntPtr w, out IntPtr root, out IntPtr child,
- out int root_x, out int root_y, out int child_x, out int child_y,
- out int mask)
- {
- /* this code was written with the help of
- glance at gdk. I never would have realized we
- needed a loop in order to traverse down in the
- hierarchy. I would have assumed you'd get the
- most deeply nested child and have to do
- XQueryTree to move back up the hierarchy..
- stupid me, of course. */
- IntPtr c;
- // Xlib.XGrabServer (display);
- Xlib.XQueryPointer (display, w, out root, out c,
- out root_x, out root_y, out child_x, out child_y,
- out mask);
- if (root != w)
- c = root;
- IntPtr child_last = IntPtr.Zero;
- while (c != IntPtr.Zero) {
- child_last = c;
- Xlib.XQueryPointer (display, c, out root, out c,
- out root_x, out root_y, out child_x, out child_y,
- out mask);
- }
- // Xlib.XUngrabServer (display);
- child = child_last;
- }
- public void SetCursorPos (int x, int y)
- {
- IntPtr root, child;
- int root_x, root_y, child_x, child_y, mask;
- /* we need to do a
- * QueryPointer before warping
- * because if the warp is on
- * the RootWindow, the x/y are
- * relative to the current
- * mouse position
- */
- QueryPointer (RootWindow.Handle,
- out root,
- out child,
- out root_x, out root_y,
- out child_x, out child_y,
- out mask);
- Xlib.XWarpPointer (display, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
- Xlib.XFlush (display);
- /* then we need to a
- * QueryPointer after warping
- * to manually generate a
- * motion event for the window
- * we move into.
- */
- QueryPointer (RootWindow.Handle,
- out root,
- out child,
- out root_x, out root_y,
- out child_x, out child_y,
- out mask);
- X11Hwnd child_hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(child);
- if (child_hwnd == null)
- return;
- XEvent xevent = new XEvent ();
- xevent.type = XEventName.MotionNotify;
- xevent.MotionEvent.display = display;
- xevent.MotionEvent.window = child_hwnd.Handle;
- xevent.MotionEvent.root = RootWindow.Handle;
- xevent.MotionEvent.x = child_x;
- xevent.MotionEvent.y = child_y;
- xevent.MotionEvent.x_root = root_x;
- xevent.MotionEvent.y_root = root_y;
- xevent.MotionEvent.state = mask;
- child_hwnd.Queue.Enqueue (xevent);
- }
- public void SetFocus (X11Hwnd new_focus)
- {
- if (new_focus == FocusWindow)
- return;
- X11Hwnd prev_focus = FocusWindow;
- FocusWindow = new_focus;
- if (prev_focus != null)
- SendMessage (prev_focus.Handle, Msg.WM_KILLFOCUS,
- FocusWindow == null ? IntPtr.Zero : FocusWindow.Handle, IntPtr.Zero);
- if (FocusWindow != null)
- SendMessage (FocusWindow.Handle, Msg.WM_SETFOCUS,
- prev_focus == null ? IntPtr.Zero : prev_focus.Handle, IntPtr.Zero);
- //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).ClientWindow, RevertTo.None, IntPtr.Zero);
- }
- public IntPtr DefineCursor (Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot)
- {
- IntPtr cursor;
- Bitmap cursor_bitmap;
- Bitmap cursor_mask;
- Byte[] cursor_bits;
- Byte[] mask_bits;
- Color c_pixel;
- Color m_pixel;
- int width;
- int height;
- IntPtr cursor_pixmap;
- IntPtr mask_pixmap;
- XColor fg;
- XColor bg;
- bool and;
- bool xor;
- if (Xlib.XQueryBestCursor (display, RootWindow.Handle, bitmap.Width, bitmap.Height, out width, out height) == 0) {
- return IntPtr.Zero;
- }
- // Win32 only allows creation cursors of a certain size
- if ((bitmap.Width != width) || (bitmap.Width != height)) {
- cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
- cursor_mask = new Bitmap(mask, new Size(width, height));
- } else {
- cursor_bitmap = bitmap;
- cursor_mask = mask;
- }
- width = cursor_bitmap.Width;
- height = cursor_bitmap.Height;
- cursor_bits = new Byte[(width / 8) * height];
- mask_bits = new Byte[(width / 8) * height];
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- c_pixel = cursor_bitmap.GetPixel(x, y);
- m_pixel = cursor_mask.GetPixel(x, y);
- and = c_pixel == cursor_pixel;
- xor = m_pixel == mask_pixel;
- if (!and && !xor) {
- // Black
- // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8))); // The bit already is 0
- mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
- } else if (and && !xor) {
- // White
- cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
- mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
- #if notneeded
- } else if (and && !xor) {
- // Screen
- } else if (and && xor) {
- // Inverse Screen
- // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
- // we want both to be 0 so nothing to be done
- //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
- //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
- #endif
- }
- }
- }
- cursor_pixmap = Xlib.XCreatePixmapFromBitmapData (display, RootWindow.Handle,
- cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
- mask_pixmap = Xlib.XCreatePixmapFromBitmapData (display, RootWindow.Handle,
- mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
- fg = new XColor();
- bg = new XColor();
- fg.pixel = Xlib.XWhitePixel (display, DefaultScreen);
- fg.red = (ushort)65535;
- fg.green = (ushort)65535;
- fg.blue = (ushort)65535;
- bg.pixel = Xlib.XBlackPixel (display, DefaultScreen);
- cursor = Xlib.XCreatePixmapCursor (display, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
- Xlib.XFreePixmap (display, cursor_pixmap);
- Xlib.XFreePixmap (display, mask_pixmap);
- return cursor;
- }
-
- public Bitmap DefineStdCursorBitmap (StdCursor id)
- {
- CursorFontShape shape;
- string name;
- IntPtr theme;
- int size;
- Bitmap bmp = null;
- try {
- shape = XplatUIX11.StdCursorToFontShape (id);
- name = shape.ToString ().Replace ("XC_", string.Empty);
- size = XplatUIX11.XcursorGetDefaultSize (Handle);
- theme = XplatUIX11.XcursorGetTheme (Handle);
- IntPtr images_ptr = XplatUIX11.XcursorLibraryLoadImages (name, theme, size);
- #if debug
- Console.WriteLine ("DefineStdCursorBitmap, id={0}, #id={1}, name{2}, size={3}, theme: {4}, images_ptr={5}", id, (int) id, name, size, Marshal.PtrToStringAnsi (theme), images_ptr);
- #endif
- if (images_ptr == IntPtr.Zero) {
- return null;
- }
- XcursorImages images = (XcursorImages)Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
- #if debug
- Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
- #endif
- if (images.nimage > 0) {
- // We only care about the first image.
- XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
- #if debug
- Console.WriteLine ("DefineStdCursorBitmap, loaded image <size={0}, height={1}, width={2}, xhot={3}, yhot={4}, pixels={5}", image.size, image.height, image.width, image.xhot, image.yhot, image.pixels);
- #endif
- // A sanity check
- if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
- int [] pixels = new int [image.width * image.height];
- Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
- bmp = new Bitmap (image.width, image.height);
- for (int w = 0; w < image.width; w++) {
- for (int h = 0; h < image.height; h++) {
- bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
- }
- }
- }
- }
- XplatUIX11.XcursorImagesDestroy (images_ptr);
- } catch (DllNotFoundException ex) {
- Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
- return null;
- }
- return bmp;
- }
-
- public IntPtr DefineStdCursor (StdCursor id)
- {
- CursorFontShape shape;
- // FIXME - define missing shapes
- switch (id) {
- case StdCursor.AppStarting:
- shape = CursorFontShape.XC_watch;
- break;
- case StdCursor.Arrow:
- shape = CursorFontShape.XC_top_left_arrow;
- break;
- case StdCursor.Cross:
- shape = CursorFontShape.XC_crosshair;
- break;
- case StdCursor.Default:
- shape = CursorFontShape.XC_top_left_arrow;
- break;
- case StdCursor.Hand:
- shape = CursorFontShape.XC_hand1;
- break;
- case StdCursor.Help:
- shape = CursorFontShape.XC_question_arrow;
- break;
-
- case StdCursor.HSplit:
- shape = CursorFontShape.XC_sb_v_double_arrow;
- break;
- case StdCursor.IBeam:
- shape = CursorFontShape.XC_xterm;
- break;
- case StdCursor.No:
- shape = CursorFontShape.XC_circle;
- break;
- case StdCursor.NoMove2D:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.NoMoveHoriz:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.NoMoveVert:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanEast:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanNE:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanNorth:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanNW:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanSE:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanSouth:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanSW:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.PanWest:
- shape = CursorFontShape.XC_sizing;
- break;
- case StdCursor.SizeAll:
- shape = CursorFontShape.XC_fleur;
- break;
- case StdCursor.SizeNESW:
- shape = CursorFontShape.XC_top_right_corner;
- break;
- case StdCursor.SizeNS:
- shape = CursorFontShape.XC_sb_v_double_arrow;
- break;
- case StdCursor.SizeNWSE:
- shape = CursorFontShape.XC_top_left_corner;
- break;
- case StdCursor.SizeWE:
- shape = CursorFontShape.XC_sb_h_double_arrow;
- break;
- case StdCursor.UpArrow:
- shape = CursorFontShape.XC_center_ptr;
- break;
- case StdCursor.VSplit:
- shape = CursorFontShape.XC_sb_h_double_arrow;
- break;
- case StdCursor.WaitCursor:
- shape = CursorFontShape.XC_watch;
- break;
- default:
- return IntPtr.Zero;
- }
- return Xlib.XCreateFontCursor (display, shape);
- }
- // XXX this should take an X11Hwnd.
- public void CreateCaret (IntPtr handle, int width, int height)
- {
- XGCValues gc_values;
- X11Hwnd hwnd;
- hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
- if (Caret.Hwnd != IntPtr.Zero)
- DestroyCaret(Caret.Hwnd);
- Caret.Hwnd = handle;
- Caret.Window = hwnd.ClientWindow;
- Caret.Width = width;
- Caret.Height = height;
- Caret.Visible = false;
- Caret.On = false;
- gc_values = new XGCValues();
- gc_values.line_width = width;
- Caret.gc = Xlib.XCreateGC (display, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
- if (Caret.gc == IntPtr.Zero) {
- Caret.Hwnd = IntPtr.Zero;
- return;
- }
- Xlib.XSetFunction (display, Caret.gc, GXFunction.GXinvert);
- }
- // XXX this should take an X11Hwnd.
- public void DestroyCaret (IntPtr handle)
- {
- if (Caret.Hwnd == handle) {
- if (Caret.Visible == true) {
- Caret.Timer.Stop ();
- }
- if (Caret.gc != IntPtr.Zero) {
- Xlib.XFreeGC (display, Caret.gc);
- Caret.gc = IntPtr.Zero;
- }
- Caret.Hwnd = IntPtr.Zero;
- Caret.Visible = false;
- Caret.On = false;
- }
- }
- public void SetCaretPos (IntPtr handle, int x, int y)
- {
- if (Caret.Hwnd == handle) {
- Caret.Timer.Stop();
- HideCaret();
- Caret.X = x;
- Caret.Y = y;
- if (Caret.Visible == true) {
- ShowCaret();
- Caret.Timer.Start();
- }
- }
- }
- public void DestroyCursor (IntPtr cursor)
- {
- Xlib.XFreeCursor (display, cursor);
- }
- private void AccumulateDestroyedHandles (Control c, ArrayList list)
- {
- if (c != null) {
- Control[] controls = c.Controls.GetAllControls ();
- if (c.IsHandleCreated && !c.IsDisposed) {
- X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(c.Handle);
- #if DriverDebug || DriverDebugDestroy
- Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
- Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.WholeWindow).ToInt32());
- #endif
- list.Add (hwnd);
- CleanupCachedWindows (hwnd);
- hwnd.zombie = true;
- }
- for (int i = 0; i < controls.Length; i ++) {
- AccumulateDestroyedHandles (controls[i], list);
- }
- }
-
- }
- void CleanupCachedWindows (X11Hwnd hwnd)
- {
- if (ActiveWindow == hwnd) {
- SendMessage (hwnd.ClientWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
- ActiveWindow = null;
- }
- if (FocusWindow == hwnd) {
- SendMessage (hwnd.ClientWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
- FocusWindow = null;
- }
- if (Grab.Hwnd == hwnd.Handle) {
- Grab.Hwnd = IntPtr.Zero;
- Grab.Confined = false;
- }
- DestroyCaret (hwnd.Handle);
- }
- public void DestroyWindow (X11Hwnd hwnd)
- {
- CleanupCachedWindows (hwnd);
- hwnd.SendParentNotify (Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
- ArrayList windows = new ArrayList ();
- AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
- hwnd.DestroyWindow ();
- foreach (X11Hwnd h in windows) {
- SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
- }
- }
- public X11Hwnd GetActiveWindow ()
- {
- IntPtr actual_atom;
- int actual_format;
- IntPtr nitems;
- IntPtr bytes_after;
- IntPtr prop = IntPtr.Zero;
- IntPtr active = IntPtr.Zero;
- Xlib.XGetWindowProperty (display, RootWindow.Handle,
- Atoms._NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false,
- Atoms.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
- if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
- active = (IntPtr)Marshal.ReadInt32(prop);
- Xlib.XFree(prop);
- }
- return (X11Hwnd)Hwnd.GetObjectFromWindow(active);
- }
- public void SetActiveWindow (X11Hwnd new_active_window)
- {
- if (new_active_window != ActiveWindow) {
- if (ActiveWindow != null)
- PostMessage (ActiveWindow.Handle, Msg.WM_ACTIVATE,
- (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
- ActiveWindow = new_active_window;
- if (ActiveWindow != null)
- PostMessage (ActiveWindow.Handle, Msg.WM_ACTIVATE,
- (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
- }
- if (ModalWindows.Count > 0) {
- // Modality handling, if we are modal and the new active window is one
- // of ours but not the modal one, switch back to the modal window
- if (ActiveWindow != null &&
- NativeWindow.FromHandle (ActiveWindow.Handle) != null) {
- if (ActiveWindow != (X11Hwnd)ModalWindows.Peek())
- ((X11Hwnd)ModalWindows.Peek()).Activate ();
- }
- }
- }
- public void GetDisplaySize (out Size size)
- {
- XWindowAttributes attributes = new XWindowAttributes();
- // FIXME - use _NET_WM messages instead?
- Xlib.XGetWindowAttributes (display, RootWindow.Handle, ref attributes);
- size = new Size(attributes.width, attributes.height);
- }
- // XXX this method doesn't really fit well anywhere in the backend
- public SizeF GetAutoScaleSize (Font font)
- {
- Graphics g;
- float width;
- string magic_string = "The quick brown fox jumped over the lazy dog.";
- double magic_number = 44.549996948242189; // XXX my god, where did this number come from?
- g = Graphics.FromHwnd (FosterParent.Handle);
- width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
- return new SizeF(width, font.Height);
- }
- public void GetCursorPos (X11Hwnd hwnd, out int x, out int y)
- {
- IntPtr use_handle;
- IntPtr root;
- IntPtr child;
- int root_x;
- int root_y;
- int win_x;
- int win_y;
- int keys_buttons;
- if (hwnd != null)
- use_handle = hwnd.Handle;
- else
- use_handle = RootWindow.Handle;
- QueryPointer (use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
- if (hwnd != null) {
- x = win_x;
- y = win_y;
- } else {
- x = root_x;
- y = root_y;
- }
- }
- public IntPtr GetFocus ()
- {
- return FocusWindow.Handle;
- }
- public IntPtr GetMousewParam (int Delta)
- {
- int result = 0;
- if ((MouseState & MouseButtons.Left) != 0) {
- result |= (int)MsgButtons.MK_LBUTTON;
- }
- if ((MouseState & MouseButtons.Middle) != 0) {
- result |= (int)MsgButtons.MK_MBUTTON;
- }
- if ((MouseState & MouseButtons.Right) != 0) {
- result |= (int)MsgButtons.MK_RBUTTON;
- }
- Keys mods = ModifierKeys;
- if ((mods & Keys.Control) != 0) {
- result |= (int)MsgButtons.MK_CONTROL;
- }
- if ((mods & Keys.Shift) != 0) {
- result |= (int)MsgButtons.MK_SHIFT;
- }
- result |= Delta << 16;
- return (IntPtr)result;
- }
- public void GrabInfo (out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea)
- {
- handle = Grab.Hwnd;
- GrabConfined = Grab.Confined;
- GrabArea = Grab.Area;
- }
- public void GrabWindow (X11Hwnd hwnd, X11Hwnd confine_to)
- {
- IntPtr confine_to_window;
- confine_to_window = IntPtr.Zero;
- if (confine_to != null) {
- Console.WriteLine (Environment.StackTrace);
- XWindowAttributes attributes = new XWindowAttributes();
- Xlib.XGetWindowAttributes (display, confine_to.ClientWindow, ref attributes);
- Grab.Area.X = attributes.x;
- Grab.Area.Y = attributes.y;
- Grab.Area.Width = attributes.width;
- Grab.Area.Height = attributes.height;
- Grab.Confined = true;
- confine_to_window = confine_to.ClientWindow;
- }
- Grab.Hwnd = hwnd.ClientWindow;
- Xlib.XGrabPointer (display, hwnd.ClientWindow, false,
- EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
- EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
- GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
- }
- public void UngrabWindow (X11Hwnd hwnd)
- {
- Xlib.XUngrabPointer (display, IntPtr.Zero);
- Xlib.XFlush (display);
- // XXX make sure hwnd is what should have the grab and throw if not
- Grab.Hwnd = IntPtr.Zero;
- Grab.Confined = false;
- }
- #if notyet
- private void TranslatePropertyToClipboard (IntPtr property)
- {
- IntPtr actual_atom;
- int actual_format;
- IntPtr nitems;
- IntPtr bytes_after;
- IntPtr prop = IntPtr.Zero;
- Clipboard.Item = null;
- Xlib.XGetWindowProperty (display, FosterParent.Handle,
- property, IntPtr.Zero, new IntPtr (0x7fffffff), true,
- Atoms.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
- if ((long)nitems > 0) {
- if (property == Atoms.XA_STRING) {
- Clipboard.Item = Marshal.PtrToStringAnsi(prop);
- } else if (property == Atoms.XA_BITMAP) {
- // FIXME - convert bitmap to image
- } else if (property == Atoms.XA_PIXMAP) {
- // FIXME - convert pixmap to image
- } else if (property == Atoms.OEMTEXT) {
- Clipboard.Item = Marshal.PtrToStringAnsi(prop);
- } else if (property == Atoms.UNICODETEXT) {
- Clipboard.Item = Marshal.PtrToStringAnsi(prop);
- }
- Xlib.XFree(prop);
- }
- }
- #endif
- // XXX should we be using @handle instead of Atoms.CLIPBOARD here?
- public int[] ClipboardAvailableFormats (IntPtr handle)
- {
- // XXX deal with the updatemessagequeue stuff
- #if true
- return new int[0];
- #else
- DataFormats.Format f;
- int[] result;
- f = DataFormats.Format.List;
- if (Xlib.XGetSelectionOwner (display, Atoms.CLIPBOARD) == IntPtr.Zero) {
- return null;
- }
- Clipboard.Formats = new ArrayList();
- while (f != null) {
- Xlib.XConvertSelection (display, Atoms.CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent.Handle, IntPtr.Zero);
- Clipboard.Enumerating = true;
- while (Clipboard.Enumerating) {
- UpdateMessageQueue(null);
- }
- f = f.Next;
- }
- result = new int[Clipboard.Formats.Count];
- for (int i = 0; i < Clipboard.Formats.Count; i++) {
- result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
- }
- Clipboard.Formats = null;
- return result;
- #endif
- }
- public void ClipboardClose (IntPtr handle)
- {
- if (handle != ClipMagic) {
- throw new ArgumentException("handle is not a valid clipboard handle");
- }
- return;
- }
- public int ClipboardGetID (IntPtr handle, string format)
- {
- if (handle != ClipMagic) {
- throw new ArgumentException("handle is not a valid clipboard handle");
- }
- if (format == "Text" ) return Atoms.XA_STRING.ToInt32();
- else if (format == "Bitmap" ) return Atoms.XA_BITMAP.ToInt32();
- //else if (format == "MetaFilePict" ) return 3;
- //else if (format == "SymbolicLink" ) return 4;
- //else if (format == "DataInterchangeFormat" ) return 5;
- //else if (format == "Tiff" ) return 6;
- else if (format == "OEMText" ) return Atoms.OEMTEXT.ToInt32();
- else if (format == "DeviceIndependentBitmap" ) return Atoms.XA_PIXMAP.ToInt32();
- else if (format == "Palette" ) return Atoms.XA_COLORMAP.ToInt32(); // Useless
- //else if (format == "PenData" ) return 10;
- //else if (format == "RiffAudio" ) return 11;
- //else if (format == "WaveAudio" ) return 12;
- else if (format == "UnicodeText" ) return Atoms.UNICODETEXT.ToInt32();
- //else if (format == "EnhancedMetafile" ) return 14;
- //else if (format == "FileDrop" ) return 15;
- //else if (format == "Locale" ) return 16;
- return Xlib.XInternAtom (display, format, false).ToInt32();
- }
- public IntPtr ClipboardOpen (bool primary_selection)
- {
- if (!primary_selection)
- ClipMagic = Atoms.CLIPBOARD;
- else
- ClipMagic = Atoms.PRIMARY;
- return ClipMagic;
- }
- // XXX @converter?
- public object ClipboardRetrieve (IntPtr handle, int type, XplatUI.ClipboardToObject converter)
- {
- // XXX deal with the UpdateMessageQueue stuff
- #if true
- return null;
- #else
- Xlib.XConvertSelection (display, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
- Clipboard.Retrieving = true;
- while (Clipboard.Retrieving) {
- UpdateMessageQueue(null);
- }
- return Clipboard.Item;
- #endif
- }
- public void ClipboardStore (IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter)
- {
- Clipboard.Item = obj;
- Clipboard.Type = type;
- Clipboard.Converter = converter;
- if (obj != null) {
- Xlib.XSetSelectionOwner (display, Atoms.CLIPBOARD, FosterParent.Handle, IntPtr.Zero);
- } else {
- // Clearing the selection
- Xlib.XSetSelectionOwner (display, Atoms.CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
- }
- }
- public PaintEventArgs PaintEventStart (ref Message m, IntPtr handle, bool client)
- {
- X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
- if (Caret.Visible == true) {
- Caret.Paused = true;
- HideCaret();
- }
- return hwnd.PaintEventStart (ref m, client);
- }
- public void PaintEventEnd (ref Message m, IntPtr handle, bool client)
- {
- X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
- hwnd.PaintEventEnd (ref m, client);
- if (Caret.Visible == true) {
- ShowCaret();
- Caret.Paused = false;
- }
- }
- public void SetCursor (IntPtr handle, IntPtr cursor)
- {
- Hwnd hwnd;
- if (OverrideCursorHandle == IntPtr.Zero) {
- if ((LastCursorWindow == handle) && (LastCursorHandle == cursor))
- return;
- LastCursorHandle = cursor;
- LastCursorWindow = handle;
- hwnd = Hwnd.ObjectFromHandle(handle);
- if (cursor != IntPtr.Zero)
- Xlib.XDefineCursor (display, hwnd.whole_window, cursor);
- else
- Xlib.XUndefineCursor (display, hwnd.whole_window);
- Xlib.XFlush (display);
- }
- else {
- hwnd = Hwnd.ObjectFromHandle(handle);
- Xlib.XDefineCursor (display, hwnd.whole_window, OverrideCursorHandle);
- }
- }
- public DragDropEffects StartDrag (IntPtr handle, object data,
- DragDropEffects allowed_effects)
- {
- X11Hwnd hwnd = (X11Hwnd)Hwnd.ObjectFromHandle (handle);
- if (hwnd == null)
- throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
- return Dnd.StartDrag (hwnd.ClientWindow, data, allowed_effects);
- }
- public X11Atoms Atoms {
- get { return atoms; }
- }
- public int CurrentTimestamp {
- get {
- TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
- return (int) t.TotalSeconds;
- }
- }
- public Size CursorSize {
- get {
- int x;
- int y;
- if (Xlib.XQueryBestCursor (display, RootWindow.Handle, 32, 32, out x, out y) != 0) {
- return new Size (x, y);
- } else {
- return new Size (16, 16);
- }
- }
- }
- public IntPtr Handle {
- get { return display; }
- }
- public Size IconSize {
- get {
- IntPtr list;
- XIconSize size;
- int count;
- if (Xlib.XGetIconSizes (display, RootWindow.Handle, out list, out count) != 0) {
- long current;
- int largest;
- current = (long)list;
- largest = 0;
- size = new XIconSize();
- for (int i = 0; i < count; i++) {
- size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
- current += Marshal.SizeOf(size);
- // Look for our preferred size
- if (size.min_width == 32) {
- Xlib.XFree(list);
- return new Size(32, 32);
- }
- if (size.max_width == 32) {
- Xlib.XFree(list);
- return new Size(32, 32);
- }
- if (size.min_width < 32 && size.max_width > 32) {
- int x;
- // check if we can fit one
- x = size.min_width;
- while (x < size.max_width) {
- x += size.width_inc;
- if (x == 32) {
- Xlib.XFree(list);
- return new Size(32, 32);
- }
- }
- }
- if (largest < size.max_width) {
- largest = size.max_width;
- }
- }
- // We didn't find a match or we wouldn't be here
- return new Size(largest, largest);
- } else {
- return new Size(32, 32);
- }
- }
- }
- public int KeyboardSpeed {
- get {
- //
- // A lot harder: need to do:
- // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
- // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
- // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58) = 0
- //
- // And from that we can tell the repetition rate
- //
- // Notice, the values must map to:
- // [0, 31] which maps to 2.5 to 30 repetitions per second.
- //
- return 0;
- }
- }
- public int KeyboardDelay {
- get {
- //
- // Return values must range from 0 to 4, 0 meaning 250ms,
- // and 4 meaning 1000 ms.
- //
- return 1; // ie, 500 ms
- }
- }
- public int DefaultScreen {
- get { return Xlib.XDefaultScreen (display); }
- }
- public IntPtr DefaultColormap {
- // XXX multiscreen
- get { return Xlib.XDefaultColormap (display, DefaultScreen); }
- }
- public Keys ModifierKeys {
- get { return Keyboard.ModifierKeys; }
- }
- public IntPtr OverrideCursor {
- get { return OverrideCursorHandle; }
- set {
- if (Grab.Hwnd != IntPtr.Zero) {
- Xlib.XChangeActivePointerGrab (display,
- EventMask.ButtonMotionMask |
- EventMask.PointerMotionMask |
- EventMask.ButtonPressMask |
- EventMask.ButtonReleaseMask,
- value, IntPtr.Zero);
- return;
- }
- OverrideCursorHandle = value;
- }
- }
- public X11RootHwnd RootWindow {
- get { return root_hwnd; }
- }
- public Size SmallIconSize {
- get {
- IntPtr list;
- XIconSize size;
- int count;
- if (Xlib.XGetIconSizes (display, RootWindow.Handle, out list, out count) != 0) {
- long current;
- int smallest;
- current = (long)list;
- smallest = 0;
- size = new XIconSize();
- for (int i = 0; i < count; i++) {
- size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
- current += Marshal.SizeOf(size);
- // Look for our preferred size
- if (size.min_width == 16) {
- Xlib.XFree(list);
- return new Size(16, 16);
- }
- if (size.max_width == 16) {
- Xlib.XFree(list);
- return new Size(16, 16);
- }
- if (size.min_width < 16 && size.max_width > 16) {
- int x;
- // check if we can fit one
- x = size.min_width;
- while (x < size.max_width) {
- x += size.width_inc;
- if (x == 16) {
- Xlib.XFree(list);
- return new Size(16, 16);
- }
- }
- }
- if (smallest == 0 || smallest > size.min_width) {
- smallest = size.min_width;
- }
- }
- // We didn't find a match or we wouldn't be here
- return new Size(smallest, smallest);
- } else {
- return new Size(16, 16);
- }
- }
- }
- public X11Hwnd FosterParent {
- get { return foster_hwnd; }
- }
- public int MouseHoverTime {
- get { return HoverState.Interval; }
- }
- public Rectangle VirtualScreen {
- get {
- IntPtr actual_atom;
- int actual_format;
- IntPtr nitems;
- IntPtr bytes_after;
- IntPtr prop = IntPtr.Zero;
- int width;
- int height;
- Xlib.XGetWindowProperty (display, RootWindow.Handle,
- Atoms._NET_DESKTOP_GEOMETRY, IntPtr.Zero, new IntPtr (256), false, Atoms.XA_CARDINAL,
- out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
- if ((long)nitems < 2)
- goto failsafe;
- width = Marshal.ReadIntPtr(prop, 0).ToInt32();
- height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
- Xlib.XFree(prop);
- return new Rectangle(0, 0, width, height);
- failsafe:
- XWindowAttributes attributes = new XWindowAttributes();
- Xlib.XGetWindowAttributes (display, RootWindow.Handle, ref attributes);
- return new Rectangle(0, 0, attributes.width, attributes.height);
- }
- }
- public Rectangle WorkingArea {
- get {
- IntPtr actual_atom;
- int actual_format;
- IntPtr nitems;
- IntPtr bytes_after;
- IntPtr prop = IntPtr.Zero;
- int width;
- int height;
- int current_desktop;
- int x;
- int y;
- Xlib.XGetWindowProperty (display, RootWindow.Handle,
- Atoms._NET_CURRENT_DESKTOP, IntPtr.Zero, new IntPtr(1), false, Atoms.XA_CARDINAL,
- out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
- if ((long)nitems < 1) {
- goto failsafe;
- }
- current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
- Xlib.XFree(prop);
- Xlib.XGetWindowProperty (display, RootWindow.Handle,
- Atoms._NET_WORKAREA, IntPtr.Zero, new IntPtr (256), false, Atoms.XA_CARDINAL,
- out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
- if ((long)nitems < 4 * current_desktop) {
- goto failsafe;
- }
- x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
- y = Marshal.ReadIntPtr(prop…
Large files files are truncated, but you can click here to view the full file