mirror of
https://github.com/seriocomedy/ShiftOS-C-.git
synced 2025-01-24 01:37:35 +00:00
7688 lines
252 KiB
C#
7688 lines
252 KiB
C#
|
// 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 ShiftUI {
|
||
|
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
|
||
|
public 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 Widget_text;
|
||
|
Hwnd hwnd;
|
||
|
Widget 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 = Widget.FromHandle(hwnd.Handle);
|
||
|
if (c != null) {
|
||
|
Widget_text = c.ToString();
|
||
|
} else {
|
||
|
Widget_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle.ToInt32());
|
||
|
}
|
||
|
} else {
|
||
|
hwnd_text = "<null>";
|
||
|
Widget_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 Widget: {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, Widget_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 your 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, Widget.MakeParam((int)cause, 0), child);
|
||
|
} else {
|
||
|
SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Widget.MakeParam((int)cause, 0), Widget.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, Widget.FromHandle (hwnd.Handle));
|
||
|
}
|
||
|
|
||
|
internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Widget 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, in which case it will return null.
|
||
|
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) {
|
||
|
byte [] buffer = new byte [(int)nitems];
|
||
|
for (int i = 0; i < (int)nitems; i++)
|
||
|
buffer [i] = Marshal.ReadByte (prop, i);
|
||
|
Clipboard.Item = Encoding.Unicode.GetString (buffer);
|
||
|
} 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 && length < 4) {
|
||
|
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
|
||
|
Widget ctrl = Widget.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 (key);
|
||
|
|
||
|
DebugHelper.Unindent ();
|
||
|
DebugHelper.WriteLine ("Finished waiting for " + key);
|
||
|
|
||
|
queue.DispatchIdle = true;
|
||
|
|
||
|
}
|
||
|
|
||
|
void MapWindow(Hwnd hwnd, WindowType windows) {
|
||
|
if (!hwnd.mapped) {
|
||
|
Form f = Widget.FromHandle(hwnd.Handle) as Form;
|
||
|
if (f != null) {
|
||
|
if (f.WindowState == FormWindowState.Normal) {
|
||
|
f.waiting_showwindow = true;
|
||
|
SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// it's possible that our Hwnd is no
|
||
|
// longer valid after making that
|
||
|
// SendMessage call, so check here.
|
||
|
if (hwnd.zombie)
|
||
|
return;
|
||
|
|
||
|
if (hwnd.topmost) {
|
||
|
// Most window managers will respect the _NET_WM_STATE property.
|
||
|
// If not, use XMapRaised to map the window at the top level as
|
||
|
// a last ditch effort.
|
||
|
if ((windows & WindowType.Whole) != 0) {
|
||
|
XMapRaised(DisplayHandle, hwnd.whole_window);
|
||
|
}
|
||
|
if ((windows & WindowType.Client) != 0) {
|
||
|
XMapRaised(DisplayHandle, hwnd.client_window);
|
||
|
}
|
||
|
} else {
|
||
|
if ((windows & WindowType.Whole) != 0) {
|
||
|
XMapWindow(DisplayHandle, hwnd.whole_window);
|
||
|
}
|
||
|
if ((windows & WindowType.Client) != 0) {
|
||
|
XMapWindow(DisplayHandle, hwnd.client_window);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hwnd.mapped = true;
|
||
|
|
||
|
if (f != null) {
|
||
|
if (f.waiting_showwindow) {
|
||
|
WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
|
||
|
CreateParams cp = f.GetCreateParams();
|
||
|
if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_MDICHILD) &&
|
||
|
!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
|
||
|
WaitForHwndMessage (hwnd, Msg.WM_ACTIVATE, true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UnmapWindow(Hwnd hwnd, WindowType windows) {
|
||
|
if (hwnd.mapped) {
|
||
|
Form f = null;
|
||
|
if (Widget.FromHandle(hwnd.Handle) is Form) {
|
||
|
f = Widget.FromHandle(hwnd.Handle) as Form;
|
||
|
if (f.WindowState == FormWindowState.Normal) {
|
||
|
f.waiting_showwindow = true;
|
||
|
SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// it's possible that our Hwnd is no
|
||
|
// longer valid after making that
|
||
|
// SendMessage call, so check here.
|
||
|
// FIXME: it is likely wrong, as it has already sent WM_SHOWWINDOW
|
||
|
if (hwnd.zombie)
|
||
|
return;
|
||
|
|
||
|
if ((windows & WindowType.Client) != 0) {
|
||
|
XUnmapWindow(DisplayHandle, hwnd.client_window);
|
||
|
}
|
||
|
if ((windows & WindowType.Whole) != 0) {
|
||
|
XUnmapWindow(DisplayHandle, hwnd.whole_window);
|
||
|
}
|
||
|
|
||
|
hwnd.mapped = false;
|
||
|
|
||
|
if (f != null) {
|
||
|
if (f.waiting_showwindow) {
|
||
|
WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
|
||
|
CreateParams cp = f.GetCreateParams();
|
||
|
if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_MDICHILD) &&
|
||
|
!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
|
||
|
WaitForHwndMessage (hwnd, Msg.WM_ACTIVATE, true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UpdateMessageQueue (XEventQueue queue) {
|
||
|
UpdateMessageQueue(queue, true);
|
||
|
}
|
||
|
|
||
|
void UpdateMessageQueue (XEventQueue queue, bool allowIdle) {
|
||
|
DateTime now;
|
||
|
int pending;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
now = DateTime.UtcNow;
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
pending = XPending (DisplayHandle);
|
||
|
}
|
||
|
|
||
|
if (pending == 0 && allowIdle) {
|
||
|
if ((queue == null || queue.DispatchIdle) && Idle != null) {
|
||
|
Idle (this, EventArgs.Empty);
|
||
|
}
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
pending = XPending (DisplayHandle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pending == 0) {
|
||
|
int timeout = 0;
|
||
|
|
||
|
if (queue != null) {
|
||
|
if (queue.Paint.Count > 0)
|
||
|
return;
|
||
|
|
||
|
timeout = NextTimeout (queue.timer_list, now);
|
||
|
}
|
||
|
|
||
|
if (timeout > 0) {
|
||
|
#if __MonoCS__
|
||
|
int length = pollfds.Length - 1;
|
||
|
lock (wake_waiting_lock) {
|
||
|
if (wake_waiting == false) {
|
||
|
length ++;
|
||
|
wake_waiting = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Syscall.poll (pollfds, (uint)length, timeout);
|
||
|
// Clean out buffer, so we're not busy-looping on the same data
|
||
|
if (length == pollfds.Length) {
|
||
|
if (pollfds[1].revents != 0)
|
||
|
wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
|
||
|
lock (wake_waiting_lock) {
|
||
|
wake_waiting = false;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
lock (XlibLock) {
|
||
|
pending = XPending (DisplayHandle);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (queue != null)
|
||
|
CheckTimers (queue.timer_list, now);
|
||
|
|
||
|
while (true) {
|
||
|
XEvent xevent = new XEvent ();
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
if (XPending (DisplayHandle) == 0)
|
||
|
break;
|
||
|
|
||
|
XNextEvent (DisplayHandle, ref xevent);
|
||
|
|
||
|
if (xevent.AnyEvent.type == XEventName.KeyPress ||
|
||
|
xevent.AnyEvent.type == XEventName.KeyRelease) {
|
||
|
// PreFilter() handles "shift key state updates.
|
||
|
Keyboard.PreFilter (xevent);
|
||
|
if (XFilterEvent (ref xevent, Keyboard.ClientWindow)) {
|
||
|
// probably here we could raise WM_IME_KEYDOWN and
|
||
|
// WM_IME_KEYUP, but I'm not sure it is worthy.
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
else if (XFilterEvent (ref xevent, IntPtr.Zero))
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
|
||
|
if (hwnd == null)
|
||
|
continue;
|
||
|
|
||
|
DebugHelper.WriteLine ("UpdateMessageQueue got Event: " + xevent.ToString ());
|
||
|
|
||
|
switch (xevent.type) {
|
||
|
case XEventName.Expose:
|
||
|
AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
|
||
|
break;
|
||
|
|
||
|
case XEventName.SelectionClear: {
|
||
|
// Should we do something?
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.SelectionRequest: {
|
||
|
if (Dnd.HandleSelectionRequestEvent (ref xevent))
|
||
|
break;
|
||
|
XEvent sel_event;
|
||
|
|
||
|
sel_event = new XEvent();
|
||
|
sel_event.SelectionEvent.type = XEventName.SelectionNotify;
|
||
|
sel_event.SelectionEvent.send_event = true;
|
||
|
sel_event.SelectionEvent.display = DisplayHandle;
|
||
|
sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
|
||
|
sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
|
||
|
sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
|
||
|
sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
|
||
|
sel_event.SelectionEvent.property = IntPtr.Zero;
|
||
|
|
||
|
IntPtr format_atom = xevent.SelectionRequestEvent.target;
|
||
|
|
||
|
// Seems that some apps support asking for supported types
|
||
|
if (format_atom == TARGETS) {
|
||
|
int[] atoms;
|
||
|
int atom_count;
|
||
|
|
||
|
atoms = new int[5];
|
||
|
atom_count = 0;
|
||
|
|
||
|
if (Clipboard.IsSourceText) {
|
||
|
atoms[atom_count++] = (int)Atom.XA_STRING;
|
||
|
atoms[atom_count++] = (int)OEMTEXT;
|
||
|
atoms[atom_count++] = (int)UTF8_STRING;
|
||
|
atoms[atom_count++] = (int)UTF16_STRING;
|
||
|
atoms[atom_count++] = (int)RICHTEXTFORMAT;
|
||
|
} else if (Clipboard.IsSourceImage) {
|
||
|
atoms[atom_count++] = (int)Atom.XA_PIXMAP;
|
||
|
atoms[atom_count++] = (int)Atom.XA_BITMAP;
|
||
|
} else {
|
||
|
// FIXME - handle other types
|
||
|
}
|
||
|
|
||
|
XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property,
|
||
|
(IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
|
||
|
sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
|
||
|
} else if (format_atom == (IntPtr)RICHTEXTFORMAT) {
|
||
|
string rtf_text = Clipboard.GetRtfText ();
|
||
|
if (rtf_text != null) {
|
||
|
// The RTF spec mentions that ascii is enough to contain it
|
||
|
Byte [] bytes = Encoding.ASCII.GetBytes (rtf_text);
|
||
|
int buflen = bytes.Length;
|
||
|
IntPtr buffer = Marshal.AllocHGlobal (buflen);
|
||
|
|
||
|
for (int i = 0; i < buflen; i++)
|
||
|
Marshal.WriteByte (buffer, i, bytes[i]);
|
||
|
|
||
|
XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property,
|
||
|
(IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
|
||
|
sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
|
||
|
Marshal.FreeHGlobal(buffer);
|
||
|
}
|
||
|
} else if (Clipboard.IsSourceText &&
|
||
|
(format_atom == (IntPtr)Atom.XA_STRING
|
||
|
|| format_atom == OEMTEXT
|
||
|
|| format_atom == UTF16_STRING
|
||
|
|| format_atom == UTF8_STRING)) {
|
||
|
IntPtr buffer = IntPtr.Zero;
|
||
|
int buflen;
|
||
|
Encoding encoding = null;
|
||
|
|
||
|
buflen = 0;
|
||
|
|
||
|
// Select an encoding depending on the target
|
||
|
IntPtr target_atom = xevent.SelectionRequestEvent.target;
|
||
|
if (target_atom == (IntPtr)Atom.XA_STRING || target_atom == OEMTEXT)
|
||
|
// FIXME - EOMTEXT should encode into ISO2022
|
||
|
encoding = Encoding.ASCII;
|
||
|
else if (target_atom == UTF16_STRING)
|
||
|
encoding = Encoding.Unicode;
|
||
|
else if (target_atom == UTF8_STRING)
|
||
|
encoding = Encoding.UTF8;
|
||
|
|
||
|
Byte [] bytes;
|
||
|
|
||
|
bytes = encoding.GetBytes (Clipboard.GetPlainText ());
|
||
|
buffer = Marshal.AllocHGlobal (bytes.Length);
|
||
|
buflen = bytes.Length;
|
||
|
|
||
|
for (int i = 0; i < buflen; i++)
|
||
|
Marshal.WriteByte (buffer, i, bytes [i]);
|
||
|
|
||
|
if (buffer != IntPtr.Zero) {
|
||
|
XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
|
||
|
sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
|
||
|
Marshal.FreeHGlobal(buffer);
|
||
|
}
|
||
|
} else if (Clipboard.GetSource (format_atom.ToInt32 ()) != null) { // check if we have an available value of this format
|
||
|
if (DataFormats.GetFormat (format_atom.ToInt32 ()).is_serializable) {
|
||
|
object serializable = Clipboard.GetSource (format_atom.ToInt32 ());
|
||
|
|
||
|
BinaryFormatter formatter = new BinaryFormatter ();
|
||
|
MemoryStream memory_stream = new MemoryStream ();
|
||
|
formatter.Serialize (memory_stream, serializable);
|
||
|
|
||
|
int buflen = (int)memory_stream.Length;
|
||
|
IntPtr buffer = Marshal.AllocHGlobal (buflen);
|
||
|
memory_stream.Position = 0;
|
||
|
for (int i = 0; i < buflen; i++)
|
||
|
Marshal.WriteByte (buffer, i, (byte)memory_stream.ReadByte ());
|
||
|
memory_stream.Close ();
|
||
|
|
||
|
XChangeProperty (DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target,
|
||
|
8, PropertyMode.Replace, buffer, buflen);
|
||
|
sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
|
||
|
Marshal.FreeHGlobal (buffer);
|
||
|
}
|
||
|
|
||
|
} else if (Clipboard.IsSourceImage) {
|
||
|
if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
|
||
|
// FIXME - convert image and store as property
|
||
|
} else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
|
||
|
// FIXME - convert image and store as property
|
||
|
}
|
||
|
}
|
||
|
|
||
|
XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.SelectionNotify: {
|
||
|
if (Clipboard.Enumerating) {
|
||
|
Clipboard.Enumerating = false;
|
||
|
if (xevent.SelectionEvent.property != IntPtr.Zero) {
|
||
|
XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
|
||
|
if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
|
||
|
Clipboard.Formats.Add(xevent.SelectionEvent.property);
|
||
|
DriverDebug("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
|
||
|
}
|
||
|
}
|
||
|
} else if (Clipboard.Retrieving) {
|
||
|
Clipboard.Retrieving = false;
|
||
|
if (xevent.SelectionEvent.property != IntPtr.Zero) {
|
||
|
TranslatePropertyToClipboard(xevent.SelectionEvent.property);
|
||
|
} else {
|
||
|
Clipboard.ClearSources ();
|
||
|
Clipboard.Item = null;
|
||
|
}
|
||
|
} else {
|
||
|
Dnd.HandleSelectionNotifyEvent (ref xevent);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.KeyRelease:
|
||
|
if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
|
||
|
XEvent nextevent = new XEvent ();
|
||
|
|
||
|
XPeekEvent (DisplayHandle, ref nextevent);
|
||
|
|
||
|
if (nextevent.type == XEventName.KeyPress &&
|
||
|
nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
|
||
|
nextevent.KeyEvent.time == xevent.KeyEvent.time) {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
goto case XEventName.KeyPress;
|
||
|
|
||
|
case XEventName.MotionNotify: {
|
||
|
XEvent peek;
|
||
|
|
||
|
/* we can't do motion compression across threads, so just punt if we don't match up */
|
||
|
if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
|
||
|
peek = hwnd.Queue.Peek();
|
||
|
if (peek.AnyEvent.type == XEventName.MotionNotify) {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
goto case XEventName.KeyPress;
|
||
|
}
|
||
|
|
||
|
case XEventName.KeyPress:
|
||
|
hwnd.Queue.EnqueueLocked (xevent);
|
||
|
/* Process KeyPresses immediately. Otherwise multiple Compose messages as a result of a
|
||
|
* single physical keypress are not processed correctly */
|
||
|
return;
|
||
|
case XEventName.ButtonPress:
|
||
|
case XEventName.ButtonRelease:
|
||
|
case XEventName.EnterNotify:
|
||
|
case XEventName.LeaveNotify:
|
||
|
case XEventName.CreateNotify:
|
||
|
case XEventName.DestroyNotify:
|
||
|
case XEventName.FocusIn:
|
||
|
case XEventName.FocusOut:
|
||
|
case XEventName.ClientMessage:
|
||
|
case XEventName.ReparentNotify:
|
||
|
case XEventName.MapNotify:
|
||
|
case XEventName.UnmapNotify:
|
||
|
hwnd.Queue.EnqueueLocked (xevent);
|
||
|
break;
|
||
|
|
||
|
case XEventName.ConfigureNotify:
|
||
|
AddConfigureNotify(xevent);
|
||
|
break;
|
||
|
|
||
|
case XEventName.PropertyNotify:
|
||
|
DriverDebug ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
|
||
|
if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
|
||
|
IntPtr actual_atom;
|
||
|
int actual_format;
|
||
|
IntPtr nitems;
|
||
|
IntPtr bytes_after;
|
||
|
IntPtr prop = IntPtr.Zero;
|
||
|
IntPtr prev_active;
|
||
|
|
||
|
prev_active = ActiveWindow;
|
||
|
XGetWindowProperty(DisplayHandle, RootWindow, _NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
|
||
|
if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
|
||
|
ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
|
||
|
XFree(prop);
|
||
|
|
||
|
DebugHelper.WriteLine ("PropertyNotify: _NET_ACTIVE_WINDOW: previous = 0x{0:x}, new = 0x{1:x}", prev_active.ToInt32 (), ActiveWindow.ToInt32 ());
|
||
|
|
||
|
if (prev_active != ActiveWindow) {
|
||
|
if (prev_active != IntPtr.Zero) {
|
||
|
PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
|
||
|
}
|
||
|
if (ActiveWindow != IntPtr.Zero) {
|
||
|
PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
if (ModalWindows.Count == 0) {
|
||
|
break;
|
||
|
} else {
|
||
|
// Modality Handling
|
||
|
//
|
||
|
// If there is a modal window on the stack and the new active
|
||
|
// window is MWF window, but not the modal one and not a non-modal
|
||
|
// child of the modal one, switch back to the modal window.
|
||
|
//
|
||
|
// To identify if a non-modal form is child of a modal form
|
||
|
// we match their ApplicationContexts, which will be the same.
|
||
|
// This is because each modal form runs the loop with a
|
||
|
// new ApplicationContext, which is inherited by the non-modal
|
||
|
// forms.
|
||
|
|
||
|
Form activeForm = Widget.FromHandle (ActiveWindow) as Form;
|
||
|
if (activeForm != null) {
|
||
|
Form modalForm = Widget.FromHandle ((IntPtr)ModalWindows.Peek()) as Form;
|
||
|
if (ActiveWindow != (IntPtr)ModalWindows.Peek() &&
|
||
|
(modalForm == null || activeForm.context == modalForm.context)) {
|
||
|
Activate((IntPtr)ModalWindows.Peek());
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
|
||
|
// invalidate our cache - we'll query again the next time someone does GetWindowState.
|
||
|
hwnd.cached_window_state = (FormWindowState)(-1);
|
||
|
PostMessage (hwnd.Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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.Widget) != 0) {
|
||
|
result |= (int)MsgButtons.MK_CONTROL;
|
||
|
}
|
||
|
|
||
|
if ((mods & Keys.Shift) != 0) {
|
||
|
result |= (int)MsgButtons.MK_SHIFT;
|
||
|
}
|
||
|
|
||
|
result |= Delta << 16;
|
||
|
|
||
|
return (IntPtr)result;
|
||
|
}
|
||
|
IntPtr XGetParent(IntPtr handle) {
|
||
|
IntPtr Root;
|
||
|
IntPtr Parent;
|
||
|
IntPtr Children;
|
||
|
int ChildCount;
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
|
||
|
}
|
||
|
|
||
|
if (Children!=IntPtr.Zero) {
|
||
|
lock (XlibLock) {
|
||
|
XFree(Children);
|
||
|
}
|
||
|
}
|
||
|
return Parent;
|
||
|
}
|
||
|
|
||
|
int HandleError (IntPtr display, ref XErrorEvent error_event)
|
||
|
{
|
||
|
// we need to workaround a problem with the
|
||
|
// ordering of destruction of Drawables and
|
||
|
// Pictures that exists between cairo and
|
||
|
// RENDER on the server.
|
||
|
if (error_event.request_code == (XRequest)render_major_opcode
|
||
|
&& error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
|
||
|
&& error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (ErrorExceptions) {
|
||
|
XUngrabPointer (display, IntPtr.Zero);
|
||
|
throw new XException (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",
|
||
|
XException.GetMessage (error_event.display, error_event.resourceid,
|
||
|
error_event.serial, error_event.error_code,
|
||
|
error_event.request_code, error_event.minor_code),
|
||
|
Environment.StackTrace);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void AccumulateDestroyedHandles (Widget c, ArrayList list)
|
||
|
{
|
||
|
DebugHelper.Enter ();
|
||
|
if (c != null) {
|
||
|
|
||
|
Widget[] Widgets = c.Widgets.GetAllWidgets ();
|
||
|
|
||
|
DebugHelper.WriteLine ("Checking Widget:0x{0:x}", c.IsHandleCreated ? c.Handle.ToInt32() : 0);
|
||
|
|
||
|
if (c.IsHandleCreated && !c.IsDisposed) {
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
|
||
|
|
||
|
DriverDebug (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
|
||
|
DriverDebug (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
|
||
|
|
||
|
list.Add (hwnd);
|
||
|
CleanupCachedWindows (hwnd);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < Widgets.Length; i ++) {
|
||
|
AccumulateDestroyedHandles (Widgets[i], list);
|
||
|
}
|
||
|
}
|
||
|
DebugHelper.Leave ();
|
||
|
}
|
||
|
|
||
|
void CleanupCachedWindows (Hwnd hwnd)
|
||
|
{
|
||
|
if (ActiveWindow == hwnd.Handle) {
|
||
|
SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
|
||
|
ActiveWindow = IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
if (FocusWindow == hwnd.Handle) {
|
||
|
SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
|
||
|
FocusWindow = IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
if (Grab.Hwnd == hwnd.Handle) {
|
||
|
Grab.Hwnd = IntPtr.Zero;
|
||
|
Grab.Confined = false;
|
||
|
}
|
||
|
|
||
|
DestroyCaret (hwnd.Handle);
|
||
|
}
|
||
|
|
||
|
void PerformNCCalc(Hwnd hwnd) {
|
||
|
XplatUIWin32.NCCALCSIZE_PARAMS ncp;
|
||
|
IntPtr ptr;
|
||
|
Rectangle rect;
|
||
|
|
||
|
rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
|
||
|
|
||
|
ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
|
||
|
ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
|
||
|
|
||
|
ncp.rgrc1.left = rect.Left;
|
||
|
ncp.rgrc1.top = rect.Top;
|
||
|
ncp.rgrc1.right = rect.Right;
|
||
|
ncp.rgrc1.bottom = rect.Bottom;
|
||
|
|
||
|
Marshal.StructureToPtr(ncp, ptr, true);
|
||
|
NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
|
||
|
ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
|
||
|
Marshal.FreeHGlobal(ptr);
|
||
|
|
||
|
|
||
|
rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
|
||
|
hwnd.ClientRect = rect;
|
||
|
|
||
|
rect = TranslateClientRectangleToXClientRectangle (hwnd);
|
||
|
|
||
|
if (hwnd.visible) {
|
||
|
MoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
|
||
|
}
|
||
|
|
||
|
AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
|
||
|
}
|
||
|
#endregion // Methods
|
||
|
|
||
|
#region Callbacks
|
||
|
void MouseHover(object sender, EventArgs e) {
|
||
|
XEvent xevent;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
HoverState.Timer.Enabled = false;
|
||
|
|
||
|
if (HoverState.Window != IntPtr.Zero) {
|
||
|
hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
|
||
|
if (hwnd != null) {
|
||
|
xevent = new XEvent ();
|
||
|
|
||
|
xevent.type = XEventName.ClientMessage;
|
||
|
xevent.ClientMessageEvent.display = DisplayHandle;
|
||
|
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.EnqueueLocked (xevent);
|
||
|
|
||
|
WakeupMain ();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CaretCallback(object sender, EventArgs e) {
|
||
|
if (Caret.Paused) {
|
||
|
return;
|
||
|
}
|
||
|
Caret.On = !Caret.On;
|
||
|
|
||
|
XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
|
||
|
}
|
||
|
#endregion // Callbacks
|
||
|
|
||
|
#region Public Properties
|
||
|
|
||
|
internal override int CaptionHeight {
|
||
|
get {
|
||
|
return 19;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size CursorSize {
|
||
|
get {
|
||
|
int x;
|
||
|
int y;
|
||
|
|
||
|
if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
|
||
|
return new Size(x, y);
|
||
|
} else {
|
||
|
return new Size(16, 16);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override bool DragFullWindows {
|
||
|
get {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size DragSize {
|
||
|
get {
|
||
|
return new Size(4, 4);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size FrameBorderSize {
|
||
|
get {
|
||
|
return new Size (4, 4);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size IconSize {
|
||
|
get {
|
||
|
IntPtr list;
|
||
|
XIconSize size;
|
||
|
int count;
|
||
|
|
||
|
if (XGetIconSizes(DisplayHandle, RootWindow, 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) {
|
||
|
XFree(list);
|
||
|
return new Size(32, 32);
|
||
|
}
|
||
|
|
||
|
if (size.max_width == 32) {
|
||
|
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) {
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override int KeyboardSpeed {
|
||
|
get{
|
||
|
//
|
||
|
// A lot harder: need to do:
|
||
|
// XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 1
|
||
|
// XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58) = 0x080517a8
|
||
|
// XkbGetWidgets(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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override int KeyboardDelay {
|
||
|
get {
|
||
|
//
|
||
|
// Return values must range from 0 to 4, 0 meaning 250ms,
|
||
|
// and 4 meaning 1000 ms.
|
||
|
//
|
||
|
return 1; // ie, 500 ms
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size MaxWindowTrackSize {
|
||
|
get {
|
||
|
return new Size (WorkingArea.Width, WorkingArea.Height);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override bool MenuAccessKeysUnderlined {
|
||
|
get {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size MinimizedWindowSpacingSize {
|
||
|
get {
|
||
|
return new Size(1, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size MinimumWindowSize {
|
||
|
get {
|
||
|
return new Size(110, 22);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size MinimumFixedToolWindowSize {
|
||
|
get { return new Size (27, 22); }
|
||
|
}
|
||
|
|
||
|
internal override Size MinimumSizeableToolWindowSize {
|
||
|
get { return new Size (37, 22); }
|
||
|
}
|
||
|
|
||
|
internal override Size MinimumNoBorderWindowSize {
|
||
|
get { return new Size (2, 2); }
|
||
|
}
|
||
|
|
||
|
internal override Keys ModifierKeys {
|
||
|
get {
|
||
|
return Keyboard.ModifierKeys;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size SmallIconSize {
|
||
|
get {
|
||
|
IntPtr list;
|
||
|
XIconSize size;
|
||
|
int count;
|
||
|
|
||
|
if (XGetIconSizes(DisplayHandle, RootWindow, 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) {
|
||
|
XFree(list);
|
||
|
return new Size(16, 16);
|
||
|
}
|
||
|
|
||
|
if (size.max_width == 16) {
|
||
|
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) {
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override int MouseButtonCount {
|
||
|
get {
|
||
|
return 3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override bool MouseButtonsSwapped {
|
||
|
get {
|
||
|
return false; // FIXME - how to detect?
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Point MousePosition {
|
||
|
get {
|
||
|
return mouse_position;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Size MouseHoverSize {
|
||
|
get {
|
||
|
return new Size (1, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override int MouseHoverTime {
|
||
|
get {
|
||
|
return HoverState.Interval;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
internal override bool MouseWheelPresent {
|
||
|
get {
|
||
|
return true; // FIXME - how to detect?
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override MouseButtons MouseButtons {
|
||
|
get {
|
||
|
return MouseState;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Rectangle VirtualScreen {
|
||
|
get {
|
||
|
IntPtr actual_atom;
|
||
|
int actual_format;
|
||
|
IntPtr nitems;
|
||
|
IntPtr bytes_after;
|
||
|
IntPtr prop = IntPtr.Zero;
|
||
|
int width;
|
||
|
int height;
|
||
|
|
||
|
XGetWindowProperty(DisplayHandle, RootWindow, _NET_DESKTOP_GEOMETRY, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.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();
|
||
|
|
||
|
XFree(prop);
|
||
|
|
||
|
return new Rectangle(0, 0, width, height);
|
||
|
|
||
|
failsafe:
|
||
|
XWindowAttributes attributes=new XWindowAttributes();
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
|
||
|
}
|
||
|
|
||
|
return new Rectangle(0, 0, attributes.width, attributes.height);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override 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;
|
||
|
|
||
|
XGetWindowProperty(DisplayHandle, RootWindow, _NET_CURRENT_DESKTOP, IntPtr.Zero, new IntPtr(1), false, (IntPtr)Atom.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();
|
||
|
XFree(prop);
|
||
|
|
||
|
XGetWindowProperty(DisplayHandle, RootWindow, _NET_WORKAREA, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
|
||
|
if ((long)nitems < 4 * (current_desktop + 1)) {
|
||
|
goto failsafe;
|
||
|
}
|
||
|
|
||
|
x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
|
||
|
y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
|
||
|
width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
|
||
|
height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
|
||
|
XFree(prop);
|
||
|
|
||
|
return new Rectangle(x, y, width, height);
|
||
|
|
||
|
failsafe:
|
||
|
XWindowAttributes attributes=new XWindowAttributes();
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
|
||
|
}
|
||
|
|
||
|
return new Rectangle(0, 0, attributes.width, attributes.height);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override Screen[] AllScreens {
|
||
|
get {
|
||
|
if (!XineramaIsActive (DisplayHandle))
|
||
|
return null;
|
||
|
int nScreens;
|
||
|
IntPtr xineramaScreens = XineramaQueryScreens (DisplayHandle, out nScreens);
|
||
|
var screens = new Screen [nScreens];
|
||
|
IntPtr current = xineramaScreens;
|
||
|
for (int i = 0; i < nScreens; i++) {
|
||
|
var screen = (XineramaScreenInfo)Marshal.PtrToStructure (current,
|
||
|
typeof (XineramaScreenInfo));
|
||
|
var screenRect = new Rectangle (screen.x_org, screen.y_org, screen.width,
|
||
|
screen.height);
|
||
|
var name = string.Format ("Display {0}", screen.screen_number);
|
||
|
screens [i] = new Screen (i == 0, name, screenRect, screenRect);
|
||
|
current = (IntPtr)( (ulong)current + (ulong)Marshal.SizeOf(typeof (XineramaScreenInfo)));
|
||
|
}
|
||
|
XFree (xineramaScreens);
|
||
|
return screens;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override bool ThemesEnabled {
|
||
|
get {
|
||
|
return XplatUIX11.themes_enabled;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#endregion // Public properties
|
||
|
|
||
|
#region Public Static Methods
|
||
|
internal override void RaiseIdle (EventArgs e)
|
||
|
{
|
||
|
if (Idle != null)
|
||
|
Idle (this, e);
|
||
|
}
|
||
|
|
||
|
internal override IntPtr InitializeDriver()
|
||
|
{
|
||
|
lock (this) {
|
||
|
if (DisplayHandle==IntPtr.Zero) {
|
||
|
SetDisplay(XOpenDisplay(IntPtr.Zero));
|
||
|
}
|
||
|
}
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
internal override void ShutdownDriver(IntPtr token)
|
||
|
{
|
||
|
lock (this) {
|
||
|
if (DisplayHandle!=IntPtr.Zero) {
|
||
|
XCloseDisplay(DisplayHandle);
|
||
|
DisplayHandle=IntPtr.Zero;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void EnableThemes()
|
||
|
{
|
||
|
themes_enabled = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
internal override void Activate(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd != null) {
|
||
|
lock (XlibLock) {
|
||
|
if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
|
||
|
SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
|
||
|
XEventQueue q = null;
|
||
|
lock (unattached_timer_list) {
|
||
|
foreach (Timer t in unattached_timer_list) {
|
||
|
if (q == null)
|
||
|
q= (XEventQueue) MessageQueues [Thread.CurrentThread];
|
||
|
t.thread = q.Thread;
|
||
|
q.timer_list.Add (t);
|
||
|
}
|
||
|
unattached_timer_list.Clear ();
|
||
|
}
|
||
|
}
|
||
|
// else {
|
||
|
// XRaiseWindow(DisplayHandle, handle);
|
||
|
// }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void AudibleAlert(AlertType alert)
|
||
|
{
|
||
|
XBell(DisplayHandle, 0);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
internal override 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect)
|
||
|
{
|
||
|
WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal override void ClientToScreen(IntPtr handle, ref int x, ref int y)
|
||
|
{
|
||
|
int dest_x_return;
|
||
|
int dest_y_return;
|
||
|
IntPtr child;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XTranslateCoordinates(handle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
|
||
|
}
|
||
|
|
||
|
x = dest_x_return;
|
||
|
y = dest_y_return;
|
||
|
}
|
||
|
|
||
|
internal override int[] ClipboardAvailableFormats(IntPtr handle)
|
||
|
{
|
||
|
DataFormats.Format f;
|
||
|
int[] result;
|
||
|
|
||
|
f = DataFormats.Format.List;
|
||
|
|
||
|
if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
Clipboard.Formats = new ArrayList();
|
||
|
|
||
|
while (f != null) {
|
||
|
XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
|
||
|
|
||
|
var timeToWaitForSelectionFormats = TimeSpan.FromSeconds(4);
|
||
|
var startTime = DateTime.Now;
|
||
|
Clipboard.Enumerating = true;
|
||
|
while (Clipboard.Enumerating) {
|
||
|
UpdateMessageQueue(null, false);
|
||
|
|
||
|
if (DateTime.Now - startTime > timeToWaitForSelectionFormats)
|
||
|
break;
|
||
|
}
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
internal override void ClipboardClose(IntPtr handle)
|
||
|
{
|
||
|
if (handle != ClipMagic) {
|
||
|
throw new ArgumentException("handle is not a valid clipboard handle");
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
internal override int ClipboardGetID(IntPtr handle, string format)
|
||
|
{
|
||
|
if (handle != ClipMagic) {
|
||
|
throw new ArgumentException("handle is not a valid clipboard handle");
|
||
|
}
|
||
|
|
||
|
if (format == "Text" ) return (int)Atom.XA_STRING;
|
||
|
else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
|
||
|
//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 OEMTEXT.ToInt32();
|
||
|
else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
|
||
|
else if (format == "Palette" ) return (int)Atom.XA_COLORMAP; // Useless
|
||
|
//else if (format == "PenData" ) return 10;
|
||
|
//else if (format == "RiffAudio" ) return 11;
|
||
|
//else if (format == "WaveAudio" ) return 12;
|
||
|
else if (format == "UnicodeText" ) return UTF16_STRING.ToInt32();
|
||
|
//else if (format == "EnhancedMetafile" ) return 14;
|
||
|
//else if (format == "FileDrop" ) return 15;
|
||
|
//else if (format == "Locale" ) return 16;
|
||
|
else if (format == "Rich Text Format") return RICHTEXTFORMAT.ToInt32 ();
|
||
|
|
||
|
return XInternAtom(DisplayHandle, format, false).ToInt32();
|
||
|
}
|
||
|
|
||
|
internal override IntPtr ClipboardOpen(bool primary_selection)
|
||
|
{
|
||
|
if (!primary_selection)
|
||
|
ClipMagic = CLIPBOARD;
|
||
|
else
|
||
|
ClipMagic = PRIMARY;
|
||
|
return ClipMagic;
|
||
|
}
|
||
|
|
||
|
internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter)
|
||
|
{
|
||
|
XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
|
||
|
|
||
|
Clipboard.Retrieving = true;
|
||
|
while (Clipboard.Retrieving) {
|
||
|
UpdateMessageQueue(null, false);
|
||
|
}
|
||
|
|
||
|
return Clipboard.Item;
|
||
|
}
|
||
|
|
||
|
internal override void ClipboardStore (IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter, bool copy)
|
||
|
{
|
||
|
Clipboard.Converter = converter;
|
||
|
|
||
|
if (obj != null) {
|
||
|
Clipboard.AddSource (type, obj);
|
||
|
XSetSelectionOwner (DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
|
||
|
|
||
|
if (copy) {
|
||
|
try {
|
||
|
var clipboardAtom = gdk_atom_intern ("CLIPBOARD", true);
|
||
|
var clipboard = gtk_clipboard_get (clipboardAtom);
|
||
|
if (clipboard != null) {
|
||
|
// for now we only store text
|
||
|
var text = Clipboard.GetRtfText ();
|
||
|
if (string.IsNullOrEmpty (text))
|
||
|
text = Clipboard.GetPlainText ();
|
||
|
if (!string.IsNullOrEmpty (text)) {
|
||
|
gtk_clipboard_set_text (clipboard, text, text.Length);
|
||
|
gtk_clipboard_store (clipboard);
|
||
|
}
|
||
|
}
|
||
|
} catch {
|
||
|
// ignore any errors - most likely because gtk isn't installed?
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// Clearing the selection
|
||
|
Clipboard.ClearSources ();
|
||
|
XSetSelectionOwner (DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void CreateCaret (IntPtr handle, int width, int height)
|
||
|
{
|
||
|
XGCValues gc_values;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (Caret.Hwnd != IntPtr.Zero) {
|
||
|
DestroyCaret(Caret.Hwnd);
|
||
|
}
|
||
|
|
||
|
Caret.Hwnd = handle;
|
||
|
Caret.Window = hwnd.client_window;
|
||
|
Caret.Width = width;
|
||
|
Caret.Height = height;
|
||
|
Caret.Visible = false;
|
||
|
Caret.On = false;
|
||
|
|
||
|
gc_values = new XGCValues();
|
||
|
gc_values.line_width = width;
|
||
|
|
||
|
Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
|
||
|
if (Caret.gc == IntPtr.Zero) {
|
||
|
Caret.Hwnd = IntPtr.Zero;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
|
||
|
}
|
||
|
|
||
|
internal override IntPtr CreateWindow (CreateParams cp)
|
||
|
{
|
||
|
XSetWindowAttributes Attributes;
|
||
|
Hwnd hwnd;
|
||
|
Hwnd parent_hwnd = null;
|
||
|
int X;
|
||
|
int Y;
|
||
|
int Width;
|
||
|
int Height;
|
||
|
IntPtr ParentHandle;
|
||
|
IntPtr WholeWindow;
|
||
|
IntPtr ClientWindow;
|
||
|
SetWindowValuemask ValueMask;
|
||
|
|
||
|
hwnd = new Hwnd();
|
||
|
|
||
|
Attributes = new XSetWindowAttributes();
|
||
|
X = cp.X;
|
||
|
Y = cp.Y;
|
||
|
Width = cp.Width;
|
||
|
Height = cp.Height;
|
||
|
|
||
|
if (Width<1) Width=1;
|
||
|
if (Height<1) Height=1;
|
||
|
|
||
|
if (cp.Parent != IntPtr.Zero) {
|
||
|
parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
|
||
|
ParentHandle = parent_hwnd.client_window;
|
||
|
} else {
|
||
|
if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
|
||
|
// We need to use our foster parent window until this poor child gets it's parent assigned
|
||
|
ParentHandle=FosterParent;
|
||
|
} else {
|
||
|
ParentHandle=RootWindow;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Set the default location location for forms.
|
||
|
Point next;
|
||
|
if (cp.control is Form) {
|
||
|
next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
|
||
|
X = next.X;
|
||
|
Y = next.Y;
|
||
|
}
|
||
|
ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
|
||
|
|
||
|
Attributes.bit_gravity = Gravity.NorthWestGravity;
|
||
|
Attributes.win_gravity = Gravity.NorthWestGravity;
|
||
|
|
||
|
// Save what's under the toolwindow
|
||
|
if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
|
||
|
Attributes.save_under = true;
|
||
|
ValueMask |= SetWindowValuemask.SaveUnder;
|
||
|
}
|
||
|
|
||
|
|
||
|
// If we're a popup without caption we override the WM
|
||
|
if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
|
||
|
Attributes.override_redirect = true;
|
||
|
ValueMask |= SetWindowValuemask.OverrideRedirect;
|
||
|
}
|
||
|
|
||
|
hwnd.x = X;
|
||
|
hwnd.y = Y;
|
||
|
hwnd.width = Width;
|
||
|
hwnd.height = Height;
|
||
|
hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
|
||
|
hwnd.initial_style = cp.WindowStyle;
|
||
|
hwnd.initial_ex_style = cp.WindowExStyle;
|
||
|
|
||
|
if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
|
||
|
hwnd.enabled = false;
|
||
|
}
|
||
|
|
||
|
ClientWindow = IntPtr.Zero;
|
||
|
|
||
|
Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
|
||
|
Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, XWindowSize.Width, XWindowSize.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
|
||
|
if (WholeWindow != IntPtr.Zero) {
|
||
|
ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
|
||
|
|
||
|
if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
|
||
|
ValueMask = SetWindowValuemask.ColorMap;
|
||
|
Attributes.colormap = CustomColormap;
|
||
|
}
|
||
|
ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, XClientRect.X, XClientRect.Y, XClientRect.Width, XClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
|
||
|
throw new Exception("Could not create X11 windows");
|
||
|
}
|
||
|
|
||
|
hwnd.Queue = ThreadQueue(Thread.CurrentThread);
|
||
|
hwnd.WholeWindow = WholeWindow;
|
||
|
hwnd.ClientWindow = ClientWindow;
|
||
|
|
||
|
DriverDebug("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
|
||
|
|
||
|
if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
|
||
|
if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
|
||
|
XSizeHints hints;
|
||
|
|
||
|
hints = new XSizeHints();
|
||
|
hints.x = X;
|
||
|
hints.y = Y;
|
||
|
hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
|
||
|
XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
|
||
|
if (hwnd.whole_window != hwnd.client_window)
|
||
|
XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
|
||
|
}
|
||
|
|
||
|
if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST))
|
||
|
SetTopmost(hwnd.whole_window, true);
|
||
|
|
||
|
SetWMStyles(hwnd, cp);
|
||
|
|
||
|
// set the group leader
|
||
|
XWMHints wm_hints = new XWMHints ();
|
||
|
|
||
|
wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
|
||
|
wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
|
||
|
wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
|
||
|
|
||
|
if (ParentHandle != RootWindow) {
|
||
|
wm_hints.window_group = hwnd.whole_window;
|
||
|
} else {
|
||
|
wm_hints.window_group = ParentHandle;
|
||
|
}
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
|
||
|
}
|
||
|
|
||
|
if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
|
||
|
SetWindowState(hwnd.Handle, FormWindowState.Minimized);
|
||
|
} else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
|
||
|
SetWindowState(hwnd.Handle, FormWindowState.Maximized);
|
||
|
}
|
||
|
|
||
|
// for now make all windows dnd enabled
|
||
|
Dnd.SetAllowDrop (hwnd, true);
|
||
|
|
||
|
// Set caption/window title
|
||
|
Text(hwnd.Handle, cp.Caption);
|
||
|
|
||
|
SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
|
||
|
SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
|
||
|
|
||
|
if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
|
||
|
hwnd.visible = true;
|
||
|
MapWindow(hwnd, WindowType.Both);
|
||
|
if (!(Widget.FromHandle(hwnd.Handle) is Form))
|
||
|
SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
|
||
|
}
|
||
|
|
||
|
return hwnd.Handle;
|
||
|
}
|
||
|
|
||
|
internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height)
|
||
|
{
|
||
|
CreateParams create_params = new CreateParams();
|
||
|
|
||
|
create_params.Caption = "";
|
||
|
create_params.X = X;
|
||
|
create_params.Y = Y;
|
||
|
create_params.Width = Width;
|
||
|
create_params.Height = Height;
|
||
|
|
||
|
create_params.ClassName=XplatUI.GetDefaultClassName (GetType ());
|
||
|
create_params.ClassStyle = 0;
|
||
|
create_params.ExStyle=0;
|
||
|
create_params.Parent=IntPtr.Zero;
|
||
|
create_params.Param=0;
|
||
|
|
||
|
return CreateWindow(create_params);
|
||
|
}
|
||
|
|
||
|
internal override 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 (XQueryBestCursor(DisplayHandle, RootWindow, 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 = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
|
||
|
mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
|
||
|
fg = new XColor();
|
||
|
bg = new XColor();
|
||
|
|
||
|
fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
|
||
|
fg.red = (ushort)65535;
|
||
|
fg.green = (ushort)65535;
|
||
|
fg.blue = (ushort)65535;
|
||
|
|
||
|
bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
|
||
|
|
||
|
cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
|
||
|
|
||
|
XFreePixmap(DisplayHandle, cursor_pixmap);
|
||
|
XFreePixmap(DisplayHandle, mask_pixmap);
|
||
|
|
||
|
return cursor;
|
||
|
}
|
||
|
|
||
|
internal override Bitmap DefineStdCursorBitmap (StdCursor id)
|
||
|
{
|
||
|
CursorFontShape shape;
|
||
|
string name;
|
||
|
IntPtr theme;
|
||
|
int size;
|
||
|
Bitmap bmp = null;
|
||
|
|
||
|
try {
|
||
|
shape = StdCursorToFontShape (id);
|
||
|
name = shape.ToString ().Replace ("XC_", string.Empty);
|
||
|
size = XcursorGetDefaultSize (DisplayHandle);
|
||
|
theme = XcursorGetTheme (DisplayHandle);
|
||
|
IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
|
||
|
DriverDebug ("DefineStdCursorBitmap, id={0}, #id={1}, name{2}, size={3}, theme: {4}, images_ptr={5}", id, (int) id, name, size, Marshal.PtrToStringAnsi (theme), images_ptr);
|
||
|
|
||
|
if (images_ptr == IntPtr.Zero) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
|
||
|
DriverDebug ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
|
||
|
|
||
|
if (images.nimage > 0) {
|
||
|
// We only care about the first image.
|
||
|
XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
|
||
|
|
||
|
DriverDebug ("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);
|
||
|
// 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]));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
XcursorImagesDestroy (images_ptr);
|
||
|
|
||
|
} catch (DllNotFoundException ex) {
|
||
|
Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return bmp;
|
||
|
}
|
||
|
|
||
|
|
||
|
internal override IntPtr DefineStdCursor(StdCursor id)
|
||
|
{
|
||
|
CursorFontShape shape;
|
||
|
IntPtr cursor;
|
||
|
|
||
|
shape = StdCursorToFontShape (id);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
cursor = XCreateFontCursor(DisplayHandle, shape);
|
||
|
}
|
||
|
return cursor;
|
||
|
}
|
||
|
|
||
|
internal static CursorFontShape StdCursorToFontShape (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: {
|
||
|
shape = (CursorFontShape) 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return shape;
|
||
|
}
|
||
|
|
||
|
internal override IntPtr DefWndProc(ref Message msg)
|
||
|
{
|
||
|
switch ((Msg)msg.Msg) {
|
||
|
|
||
|
case Msg.WM_IME_COMPOSITION:
|
||
|
string s = Keyboard.GetCompositionString ();
|
||
|
foreach (char c in s)
|
||
|
SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
|
||
|
return IntPtr.Zero;
|
||
|
|
||
|
case Msg.WM_IME_CHAR:
|
||
|
// On Windows API it sends two WM_CHAR messages for each byte, but
|
||
|
// I wonder if it is worthy to emulate it (also no idea how to
|
||
|
// reconstruct those bytes into chars).
|
||
|
SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
|
||
|
return IntPtr.Zero;
|
||
|
|
||
|
case Msg.WM_PAINT: {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
|
||
|
if (hwnd != null) {
|
||
|
hwnd.expose_pending = false;
|
||
|
}
|
||
|
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
case Msg.WM_NCPAINT: {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
|
||
|
if (hwnd != null) {
|
||
|
hwnd.nc_expose_pending = false;
|
||
|
}
|
||
|
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
case Msg.WM_NCCALCSIZE: {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
if (msg.WParam == (IntPtr)1) {
|
||
|
hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
|
||
|
|
||
|
XplatUIWin32.NCCALCSIZE_PARAMS ncp;
|
||
|
ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
|
||
|
|
||
|
// Add all the stuff X is supposed to draw.
|
||
|
Widget ctrl = Widget.FromHandle (hwnd.Handle);
|
||
|
|
||
|
if (ctrl != null) {
|
||
|
Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
|
||
|
|
||
|
ncp.rgrc1.top += rect.top;
|
||
|
ncp.rgrc1.bottom -= rect.bottom;
|
||
|
ncp.rgrc1.left += rect.left;
|
||
|
ncp.rgrc1.right -= rect.right;
|
||
|
|
||
|
Marshal.StructureToPtr (ncp, msg.LParam, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
case Msg.WM_CONTEXTMENU: {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
|
||
|
|
||
|
if ((hwnd != null) && (hwnd.parent != null)) {
|
||
|
SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
|
||
|
}
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
case Msg.WM_MOUSEWHEEL: {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
|
||
|
|
||
|
if ((hwnd != null) && (hwnd.parent != null)) {
|
||
|
SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
|
||
|
if (msg.Result == IntPtr.Zero) {
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
}
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
case Msg.WM_SETCURSOR: {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
|
||
|
if (hwnd == null)
|
||
|
break; // not sure how this happens, but it does
|
||
|
|
||
|
// Pass to parent window first
|
||
|
while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
|
||
|
hwnd = hwnd.parent;
|
||
|
msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
|
||
|
}
|
||
|
|
||
|
if (msg.Result == IntPtr.Zero) {
|
||
|
IntPtr handle;
|
||
|
|
||
|
switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
|
||
|
case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
|
||
|
case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
|
||
|
case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
|
||
|
case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
|
||
|
case HitTest.HTERROR: if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
|
||
|
AudibleAlert(AlertType.Default);
|
||
|
}
|
||
|
handle = Cursors.Default.handle;
|
||
|
break;
|
||
|
|
||
|
case HitTest.HTHELP: handle = Cursors.Help.handle; break;
|
||
|
case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
|
||
|
case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
|
||
|
case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
|
||
|
case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
|
||
|
case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
|
||
|
|
||
|
#if SameAsDefault
|
||
|
case HitTest.HTGROWBOX:
|
||
|
case HitTest.HTSIZE:
|
||
|
case HitTest.HTZOOM:
|
||
|
case HitTest.HTVSCROLL:
|
||
|
case HitTest.HTSYSMENU:
|
||
|
case HitTest.HTREDUCE:
|
||
|
case HitTest.HTNOWHERE:
|
||
|
case HitTest.HTMAXBUTTON:
|
||
|
case HitTest.HTMINBUTTON:
|
||
|
case HitTest.HTMENU:
|
||
|
case HitTest.HSCROLL:
|
||
|
case HitTest.HTBOTTOM:
|
||
|
case HitTest.HTCAPTION:
|
||
|
case HitTest.HTCLIENT:
|
||
|
case HitTest.HTCLOSE:
|
||
|
#endif
|
||
|
default: handle = Cursors.Default.handle; break;
|
||
|
}
|
||
|
SetCursor(msg.HWnd, handle);
|
||
|
}
|
||
|
return (IntPtr)1;
|
||
|
}
|
||
|
}
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
internal override void DestroyCaret(IntPtr handle)
|
||
|
{
|
||
|
if (Caret.Hwnd == handle) {
|
||
|
if (Caret.Visible) {
|
||
|
HideCaret ();
|
||
|
Caret.Timer.Stop();
|
||
|
}
|
||
|
if (Caret.gc != IntPtr.Zero) {
|
||
|
XFreeGC(DisplayHandle, Caret.gc);
|
||
|
Caret.gc = IntPtr.Zero;
|
||
|
}
|
||
|
Caret.Hwnd = IntPtr.Zero;
|
||
|
Caret.Visible = false;
|
||
|
Caret.On = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void DestroyCursor(IntPtr cursor)
|
||
|
{
|
||
|
lock (XlibLock) {
|
||
|
XFreeCursor(DisplayHandle, cursor);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void DestroyWindow(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
// The window should never ever be a zombie here, since we should
|
||
|
// wait until it's completely dead before returning from
|
||
|
// "destroying" calls, but just in case....
|
||
|
if (hwnd == null || hwnd.zombie) {
|
||
|
DriverDebug ("window {0:X} already destroyed", handle.ToInt32());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DriverDebug ("Destroying window {0}", XplatUI.Window(hwnd.client_window));
|
||
|
|
||
|
SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
|
||
|
|
||
|
CleanupCachedWindows (hwnd);
|
||
|
|
||
|
ArrayList windows = new ArrayList ();
|
||
|
|
||
|
AccumulateDestroyedHandles (Widget.WidgetNativeWindow.WidgetFromHandle(hwnd.Handle), windows);
|
||
|
|
||
|
|
||
|
foreach (Hwnd h in windows) {
|
||
|
SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
|
||
|
h.zombie = true;
|
||
|
}
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
if (hwnd.whole_window != IntPtr.Zero) {
|
||
|
DriverDebug ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
|
||
|
Keyboard.DestroyICForWindow (hwnd.whole_window);
|
||
|
XDestroyWindow(DisplayHandle, hwnd.whole_window);
|
||
|
}
|
||
|
else if (hwnd.client_window != IntPtr.Zero) {
|
||
|
DriverDebug ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
|
||
|
Keyboard.DestroyICForWindow (hwnd.client_window);
|
||
|
XDestroyWindow(DisplayHandle, hwnd.client_window);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override IntPtr DispatchMessage(ref MSG msg)
|
||
|
{
|
||
|
return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||
|
}
|
||
|
|
||
|
IntPtr GetReversibleScreenGC (Color backColor)
|
||
|
{
|
||
|
XGCValues gc_values;
|
||
|
IntPtr gc;
|
||
|
uint pixel;
|
||
|
|
||
|
XColor xcolor = new XColor();
|
||
|
xcolor.red = (ushort)(backColor.R * 257);
|
||
|
xcolor.green = (ushort)(backColor.G * 257);
|
||
|
xcolor.blue = (ushort)(backColor.B * 257);
|
||
|
XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
|
||
|
pixel = (uint)xcolor.pixel.ToInt32();
|
||
|
|
||
|
|
||
|
gc_values = new XGCValues();
|
||
|
|
||
|
gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
|
||
|
gc_values.foreground = (IntPtr)pixel;
|
||
|
|
||
|
gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
|
||
|
XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
|
||
|
XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
|
||
|
|
||
|
return gc;
|
||
|
}
|
||
|
|
||
|
IntPtr GetReversibleWidgetGC (Widget Widget, int line_width)
|
||
|
{
|
||
|
XGCValues gc_values;
|
||
|
IntPtr gc;
|
||
|
|
||
|
gc_values = new XGCValues();
|
||
|
|
||
|
gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
|
||
|
gc_values.line_width = line_width;
|
||
|
gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
|
||
|
|
||
|
// This logic will give us true rubber bands: (libsx, SANE_XOR)
|
||
|
//mask = foreground ^ background;
|
||
|
//XSetForeground(DisplayHandle, gc, 0xffffffff);
|
||
|
//XSetBackground(DisplayHandle, gc, background);
|
||
|
//XSetFunction(DisplayHandle, gc, GXxor);
|
||
|
//XSetPlaneMask(DisplayHandle, gc, mask);
|
||
|
|
||
|
|
||
|
gc = XCreateGC(DisplayHandle, Widget.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
|
||
|
uint foreground;
|
||
|
uint background;
|
||
|
|
||
|
XColor xcolor = new XColor();
|
||
|
|
||
|
xcolor.red = (ushort)(Widget.ForeColor.R * 257);
|
||
|
xcolor.green = (ushort)(Widget.ForeColor.G * 257);
|
||
|
xcolor.blue = (ushort)(Widget.ForeColor.B * 257);
|
||
|
XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
|
||
|
foreground = (uint)xcolor.pixel.ToInt32();
|
||
|
|
||
|
xcolor.red = (ushort)(Widget.BackColor.R * 257);
|
||
|
xcolor.green = (ushort)(Widget.BackColor.G * 257);
|
||
|
xcolor.blue = (ushort)(Widget.BackColor.B * 257);
|
||
|
XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
|
||
|
background = (uint)xcolor.pixel.ToInt32();
|
||
|
|
||
|
uint mask = foreground ^ background;
|
||
|
|
||
|
XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
|
||
|
XSetBackground(DisplayHandle, gc, (UIntPtr)background);
|
||
|
XSetFunction(DisplayHandle, gc, GXFunction.GXxor);
|
||
|
XSetPlaneMask(DisplayHandle, gc, (IntPtr)mask);
|
||
|
|
||
|
return gc;
|
||
|
}
|
||
|
|
||
|
internal override void DrawReversibleLine(Point start, Point end, Color backColor)
|
||
|
{
|
||
|
if (backColor.GetBrightness() < 0.5)
|
||
|
backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
|
||
|
|
||
|
IntPtr gc = GetReversibleScreenGC (backColor);
|
||
|
|
||
|
XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
|
||
|
|
||
|
XFreeGC(DisplayHandle, gc);
|
||
|
}
|
||
|
|
||
|
internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
|
||
|
{
|
||
|
if (backColor.GetBrightness() < 0.5)
|
||
|
backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
|
||
|
|
||
|
IntPtr gc = GetReversibleScreenGC (backColor);
|
||
|
|
||
|
if (rectangle.Width < 0) {
|
||
|
rectangle.X += rectangle.Width;
|
||
|
rectangle.Width = -rectangle.Width;
|
||
|
}
|
||
|
if (rectangle.Height < 0) {
|
||
|
rectangle.Y += rectangle.Height;
|
||
|
rectangle.Height = -rectangle.Height;
|
||
|
}
|
||
|
|
||
|
int line_width = 1;
|
||
|
GCLineStyle line_style = GCLineStyle.LineSolid;
|
||
|
GCCapStyle cap_style = GCCapStyle.CapButt;
|
||
|
GCJoinStyle join_style = GCJoinStyle.JoinMiter;
|
||
|
|
||
|
switch (style) {
|
||
|
case FrameStyle.Dashed:
|
||
|
line_style = GCLineStyle.LineOnOffDash;
|
||
|
break;
|
||
|
case FrameStyle.Thick:
|
||
|
line_width = 2;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
|
||
|
|
||
|
XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
|
||
|
|
||
|
XFreeGC(DisplayHandle, gc);
|
||
|
}
|
||
|
|
||
|
internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor)
|
||
|
{
|
||
|
if (backColor.GetBrightness() < 0.5)
|
||
|
backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
|
||
|
|
||
|
IntPtr gc = GetReversibleScreenGC (backColor);
|
||
|
|
||
|
if (rectangle.Width < 0) {
|
||
|
rectangle.X += rectangle.Width;
|
||
|
rectangle.Width = -rectangle.Width;
|
||
|
}
|
||
|
if (rectangle.Height < 0) {
|
||
|
rectangle.Y += rectangle.Height;
|
||
|
rectangle.Height = -rectangle.Height;
|
||
|
}
|
||
|
XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
|
||
|
|
||
|
XFreeGC(DisplayHandle, gc);
|
||
|
}
|
||
|
|
||
|
internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
|
||
|
{
|
||
|
IntPtr gc;
|
||
|
Widget Widget = Widget.FromHandle(handle);
|
||
|
|
||
|
gc = GetReversibleWidgetGC (Widget, line_width);
|
||
|
|
||
|
if ((rect.Width > 0) && (rect.Height > 0)) {
|
||
|
XDrawRectangle(DisplayHandle, Widget.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
|
||
|
} else {
|
||
|
if (rect.Width > 0) {
|
||
|
XDrawLine(DisplayHandle, Widget.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
|
||
|
} else {
|
||
|
XDrawLine(DisplayHandle, Widget.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
|
||
|
}
|
||
|
}
|
||
|
XFreeGC(DisplayHandle, gc);
|
||
|
}
|
||
|
|
||
|
internal override void DoEvents()
|
||
|
{
|
||
|
DebugHelper.Enter ();
|
||
|
|
||
|
MSG msg = new MSG ();
|
||
|
XEventQueue queue;
|
||
|
|
||
|
if (OverrideCursorHandle != IntPtr.Zero) {
|
||
|
OverrideCursorHandle = IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
queue = ThreadQueue(Thread.CurrentThread);
|
||
|
|
||
|
queue.DispatchIdle = false;
|
||
|
in_doevents = true;
|
||
|
|
||
|
while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
|
||
|
Message m = Message.Create (msg.hwnd, (int)msg.message, msg.wParam, msg.lParam);
|
||
|
|
||
|
if (Application.FilterMessage (ref m))
|
||
|
continue;
|
||
|
|
||
|
TranslateMessage (ref msg);
|
||
|
DispatchMessage (ref msg);
|
||
|
|
||
|
string key = msg.hwnd + ":" + msg.message;
|
||
|
if (messageHold[key] != null) {
|
||
|
messageHold[key] = ((int)messageHold[key]) - 1;
|
||
|
DebugHelper.WriteLine ("Got " + msg + " for " + key);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
in_doevents = false;
|
||
|
queue.DispatchIdle = true;
|
||
|
|
||
|
DebugHelper.Leave ();
|
||
|
}
|
||
|
|
||
|
internal override void EnableWindow(IntPtr handle, bool Enable)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
if (hwnd != null) {
|
||
|
hwnd.Enabled = Enable;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void EndLoop(Thread thread)
|
||
|
{
|
||
|
// This is where we one day will shut down the loop for the thread
|
||
|
}
|
||
|
|
||
|
internal override IntPtr GetActive()
|
||
|
{
|
||
|
IntPtr actual_atom;
|
||
|
int actual_format;
|
||
|
IntPtr nitems;
|
||
|
IntPtr bytes_after;
|
||
|
IntPtr prop = IntPtr.Zero;
|
||
|
IntPtr active = IntPtr.Zero;
|
||
|
|
||
|
XGetWindowProperty(DisplayHandle, RootWindow, _NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.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);
|
||
|
XFree(prop);
|
||
|
} else {
|
||
|
// The window manager does not support _NET_ACTIVE_WINDOW. Fall back to XGetInputFocus.
|
||
|
IntPtr revert_to = IntPtr.Zero;
|
||
|
XGetInputFocus(DisplayHandle, out active, out revert_to);
|
||
|
}
|
||
|
|
||
|
if (active != IntPtr.Zero) {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(active);
|
||
|
if (hwnd != null) {
|
||
|
active = hwnd.Handle;
|
||
|
} else {
|
||
|
active = IntPtr.Zero;
|
||
|
}
|
||
|
}
|
||
|
return active;
|
||
|
}
|
||
|
|
||
|
internal override Region GetClipRegion(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
if (hwnd != null) {
|
||
|
return hwnd.UserClip;
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y)
|
||
|
{
|
||
|
width = 20;
|
||
|
height = 20;
|
||
|
hotspot_x = 0;
|
||
|
hotspot_y = 0;
|
||
|
}
|
||
|
|
||
|
internal override void GetDisplaySize(out Size size)
|
||
|
{
|
||
|
XWindowAttributes attributes=new XWindowAttributes();
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
// FIXME - use _NET_WM messages instead?
|
||
|
XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
|
||
|
}
|
||
|
|
||
|
size = new Size(attributes.width, attributes.height);
|
||
|
}
|
||
|
|
||
|
internal override 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;
|
||
|
|
||
|
g = Graphics.FromHwnd(FosterParent);
|
||
|
|
||
|
width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
|
||
|
return new SizeF(width, font.Height);
|
||
|
}
|
||
|
|
||
|
internal override IntPtr GetParent(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
if (hwnd != null && hwnd.parent != null) {
|
||
|
return hwnd.parent.Handle;
|
||
|
}
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
// This is a nop on win32 and x11
|
||
|
internal override IntPtr GetPreviousWindow(IntPtr handle)
|
||
|
{
|
||
|
return handle;
|
||
|
}
|
||
|
|
||
|
internal override void GetCursorPos(IntPtr handle, 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 (handle != IntPtr.Zero) {
|
||
|
use_handle = Hwnd.ObjectFromHandle(handle).client_window;
|
||
|
} else {
|
||
|
use_handle = RootWindow;
|
||
|
}
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
|
||
|
}
|
||
|
|
||
|
if (handle != IntPtr.Zero) {
|
||
|
x = win_x;
|
||
|
y = win_y;
|
||
|
} else {
|
||
|
x = root_x;
|
||
|
y = root_y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override IntPtr GetFocus()
|
||
|
{
|
||
|
return FocusWindow;
|
||
|
}
|
||
|
|
||
|
|
||
|
internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent)
|
||
|
{
|
||
|
FontFamily ff = font.FontFamily;
|
||
|
ascent = ff.GetCellAscent (font.Style);
|
||
|
descent = ff.GetCellDescent (font.Style);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal override Point GetMenuOrigin(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd != null) {
|
||
|
return hwnd.MenuOrigin;
|
||
|
}
|
||
|
return Point.Empty;
|
||
|
}
|
||
|
|
||
|
[MonoTODO("Implement filtering")]
|
||
|
internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax)
|
||
|
{
|
||
|
XEvent xevent;
|
||
|
bool client;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
ProcessNextMessage:
|
||
|
|
||
|
if (((XEventQueue)queue_id).Count > 0) {
|
||
|
xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
|
||
|
} else {
|
||
|
UpdateMessageQueue ((XEventQueue)queue_id);
|
||
|
|
||
|
if (((XEventQueue)queue_id).Count > 0) {
|
||
|
xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
|
||
|
} else if (((XEventQueue)queue_id).Paint.Count > 0) {
|
||
|
xevent = ((XEventQueue)queue_id).Paint.Dequeue();
|
||
|
} else {
|
||
|
msg.hwnd= IntPtr.Zero;
|
||
|
msg.message = Msg.WM_ENTERIDLE;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
|
||
|
|
||
|
#if DriverDebugDestroy
|
||
|
if (hwnd != null)
|
||
|
if (hwnd.zombie)
|
||
|
Console.WriteLine ( "GetMessage zombie, got Event: " + xevent.ToString () + " for 0x{0:x}", hwnd.Handle.ToInt32());
|
||
|
else
|
||
|
Console.WriteLine ( "GetMessage, got Event: " + xevent.ToString () + " for 0x{0:x}", hwnd.Handle.ToInt32());
|
||
|
#endif
|
||
|
// Handle messages for windows that are already or are about to be destroyed.
|
||
|
|
||
|
// we need a special block for this because unless we remove the hwnd from the paint
|
||
|
// queue it will always stay there (since we don't handle the expose), and we'll
|
||
|
// effectively loop infinitely trying to repaint a non-existant window.
|
||
|
if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
|
||
|
hwnd.expose_pending = hwnd.nc_expose_pending = false;
|
||
|
hwnd.Queue.Paint.Remove (hwnd);
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
// We need to make sure we only allow DestroyNotify events through for zombie
|
||
|
// hwnds, since much of the event handling code makes requests using the hwnd's
|
||
|
// client_window, and that'll result in BadWindow errors if there's some lag
|
||
|
// between the XDestroyWindow call and the DestroyNotify event.
|
||
|
if (hwnd == null || hwnd.zombie && xevent.AnyEvent.type != XEventName.ClientMessage) {
|
||
|
DriverDebug("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
|
||
|
// If we get here, that means the window is no more but there are Client Messages
|
||
|
// to be processed, probably a Posted message (for instance, an WM_ACTIVATE message)
|
||
|
// We don't want anything else to run but the ClientMessage block, so reset all hwnd
|
||
|
// properties that might cause other processing to occur.
|
||
|
if (hwnd.zombie) {
|
||
|
hwnd.resizing_or_moving = false;
|
||
|
}
|
||
|
|
||
|
if (hwnd.client_window == xevent.AnyEvent.window) {
|
||
|
client = true;
|
||
|
//Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
|
||
|
} else {
|
||
|
client = false;
|
||
|
//Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
|
||
|
}
|
||
|
|
||
|
msg.hwnd = hwnd.Handle;
|
||
|
|
||
|
// Windows sends WM_ENTERSIZEMOVE when a form resize/move operation starts and WM_EXITSIZEMOVE
|
||
|
// when it is done. The problem in X11 is that there is no concept of start-end of a moving/sizing.
|
||
|
// Configure events ("this window has resized/moved") are sent for each step of the resize. We send a
|
||
|
// WM_ENTERSIZEMOVE when we get the first Configure event. The problem is the WM_EXITSIZEMOVE.
|
||
|
//
|
||
|
// - There is no way for us to know which is the last Configure event. We can't traverse the events
|
||
|
// queue, because the next configure event might not be pending yet.
|
||
|
// - We can't get ButtonPress/Release events for the window decorations, because they are not part
|
||
|
// of the window(s) we manage.
|
||
|
// - We can't rely on the mouse state to change to "up" before the last Configure event. It doesn't.
|
||
|
//
|
||
|
// We are almost 100% guaranteed to get another event (e.g Expose or other), but we can't know for sure
|
||
|
// which, so we have here to check if the mouse buttons state is "up" and send the WM_EXITSIZEMOVE
|
||
|
//
|
||
|
if (hwnd.resizing_or_moving) {
|
||
|
int root_x, root_y, win_x, win_y, keys_buttons;
|
||
|
IntPtr root, child;
|
||
|
XQueryPointer (DisplayHandle, hwnd.Handle, out root, out child, out root_x, out root_y,
|
||
|
out win_x, out win_y, out keys_buttons);
|
||
|
if ((keys_buttons & (int)MouseKeyMasks.Button1Mask) == 0 &&
|
||
|
(keys_buttons & (int)MouseKeyMasks.Button2Mask) == 0 &&
|
||
|
(keys_buttons & (int)MouseKeyMasks.Button3Mask) == 0) {
|
||
|
hwnd.resizing_or_moving = false;
|
||
|
SendMessage (hwnd.Handle, Msg.WM_EXITSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If you add a new event to this switch make sure to add it in
|
||
|
// UpdateMessage also unless it is not coming through the X event system.
|
||
|
//
|
||
|
switch(xevent.type) {
|
||
|
case XEventName.KeyPress: {
|
||
|
Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
|
||
|
|
||
|
// F1 key special case - WM_HELP sending
|
||
|
if (msg.wParam == (IntPtr)VirtualKeys.VK_F1 || msg.wParam == (IntPtr)VirtualKeys.VK_HELP) {
|
||
|
// Send wM_HELP and then return it as a keypress message in
|
||
|
// case it needs to be preproccessed.
|
||
|
HELPINFO helpInfo = new HELPINFO ();
|
||
|
GetCursorPos (IntPtr.Zero, out helpInfo.MousePos.x, out helpInfo.MousePos.y);
|
||
|
IntPtr helpInfoPtr = Marshal.AllocHGlobal (Marshal.SizeOf (helpInfo));
|
||
|
Marshal.StructureToPtr (helpInfo, helpInfoPtr, true);
|
||
|
NativeWindow.WndProc (FocusWindow, Msg.WM_HELP, IntPtr.Zero, helpInfoPtr);
|
||
|
Marshal.FreeHGlobal (helpInfoPtr);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.KeyRelease: {
|
||
|
Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.ButtonPress: {
|
||
|
switch(xevent.ButtonEvent.button) {
|
||
|
case 1: {
|
||
|
MouseState |= MouseButtons.Left;
|
||
|
if (client) {
|
||
|
msg.message = Msg.WM_LBUTTONDOWN;
|
||
|
msg.wParam = GetMousewParam (0);
|
||
|
} else {
|
||
|
msg.message = Msg.WM_NCLBUTTONDOWN;
|
||
|
msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 2: {
|
||
|
MouseState |= MouseButtons.Middle;
|
||
|
if (client) {
|
||
|
msg.message = Msg.WM_MBUTTONDOWN;
|
||
|
msg.wParam = GetMousewParam (0);
|
||
|
} else {
|
||
|
msg.message = Msg.WM_NCMBUTTONDOWN;
|
||
|
msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 3: {
|
||
|
MouseState |= MouseButtons.Right;
|
||
|
if (client) {
|
||
|
msg.message = Msg.WM_RBUTTONDOWN;
|
||
|
msg.wParam = GetMousewParam (0);
|
||
|
} else {
|
||
|
msg.message = Msg.WM_NCRBUTTONDOWN;
|
||
|
msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 4: {
|
||
|
msg.hwnd = FocusWindow;
|
||
|
msg.message=Msg.WM_MOUSEWHEEL;
|
||
|
msg.wParam=GetMousewParam(120);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 5: {
|
||
|
msg.hwnd = FocusWindow;
|
||
|
msg.message=Msg.WM_MOUSEWHEEL;
|
||
|
msg.wParam=GetMousewParam(-120);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
|
||
|
mouse_position.X = xevent.ButtonEvent.x;
|
||
|
mouse_position.Y = xevent.ButtonEvent.y;
|
||
|
|
||
|
if (!hwnd.Enabled) {
|
||
|
IntPtr dummy;
|
||
|
|
||
|
msg.hwnd = hwnd.EnabledHwnd;
|
||
|
XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy);
|
||
|
msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
|
||
|
}
|
||
|
|
||
|
if (Grab.Hwnd != IntPtr.Zero) {
|
||
|
msg.hwnd = Grab.Hwnd;
|
||
|
}
|
||
|
|
||
|
if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
|
||
|
// Looks like a genuine double click, clicked twice on the same spot with the same keys
|
||
|
switch(xevent.ButtonEvent.button) {
|
||
|
case 1: {
|
||
|
msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 2: {
|
||
|
msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 3: {
|
||
|
msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
ClickPending.Pending = false;
|
||
|
} else {
|
||
|
ClickPending.Pending = true;
|
||
|
ClickPending.Hwnd = msg.hwnd;
|
||
|
ClickPending.Message = msg.message;
|
||
|
ClickPending.wParam = msg.wParam;
|
||
|
ClickPending.lParam = msg.lParam;
|
||
|
ClickPending.Time = (long)xevent.ButtonEvent.time;
|
||
|
}
|
||
|
|
||
|
if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
|
||
|
SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.ButtonRelease: {
|
||
|
switch(xevent.ButtonEvent.button) {
|
||
|
case 1: {
|
||
|
if (client) {
|
||
|
msg.message = Msg.WM_LBUTTONUP;
|
||
|
} else {
|
||
|
msg.message = Msg.WM_NCLBUTTONUP;
|
||
|
msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
|
||
|
}
|
||
|
MouseState &= ~MouseButtons.Left;
|
||
|
msg.wParam = GetMousewParam (0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 2: {
|
||
|
if (client) {
|
||
|
msg.message = Msg.WM_MBUTTONUP;
|
||
|
} else {
|
||
|
msg.message = Msg.WM_NCMBUTTONUP;
|
||
|
msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
|
||
|
}
|
||
|
MouseState &= ~MouseButtons.Middle;
|
||
|
msg.wParam = GetMousewParam (0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 3: {
|
||
|
if (client) {
|
||
|
msg.message = Msg.WM_RBUTTONUP;
|
||
|
} else {
|
||
|
msg.message = Msg.WM_NCRBUTTONUP;
|
||
|
msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
|
||
|
}
|
||
|
MouseState &= ~MouseButtons.Right;
|
||
|
msg.wParam = GetMousewParam (0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 4: {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
case 5: {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!hwnd.Enabled) {
|
||
|
IntPtr dummy;
|
||
|
|
||
|
msg.hwnd = hwnd.EnabledHwnd;
|
||
|
XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy);
|
||
|
msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
|
||
|
}
|
||
|
|
||
|
if (Grab.Hwnd != IntPtr.Zero) {
|
||
|
msg.hwnd = Grab.Hwnd;
|
||
|
}
|
||
|
|
||
|
msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
|
||
|
mouse_position.X = xevent.ButtonEvent.x;
|
||
|
mouse_position.Y = xevent.ButtonEvent.y;
|
||
|
|
||
|
// Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
|
||
|
// not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after
|
||
|
// mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
|
||
|
if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
|
||
|
XEvent motionEvent = new XEvent ();
|
||
|
motionEvent.type = XEventName.MotionNotify;
|
||
|
motionEvent.MotionEvent.display = DisplayHandle;
|
||
|
motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
|
||
|
motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
|
||
|
motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
|
||
|
hwnd.Queue.EnqueueLocked (motionEvent);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.MotionNotify: {
|
||
|
if (client) {
|
||
|
DriverDebug("GetMessage(): Window {0:X} MotionNotify x={1} y={2}",
|
||
|
client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(),
|
||
|
xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
|
||
|
if (Grab.Hwnd != IntPtr.Zero) {
|
||
|
msg.hwnd = Grab.Hwnd;
|
||
|
} else {
|
||
|
if (hwnd.Enabled) {
|
||
|
NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (xevent.MotionEvent.is_hint != 0)
|
||
|
{
|
||
|
IntPtr root, child;
|
||
|
int mask;
|
||
|
XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
|
||
|
out root, out child,
|
||
|
out xevent.MotionEvent.x_root,
|
||
|
out xevent.MotionEvent.y_root,
|
||
|
out xevent.MotionEvent.x,
|
||
|
out xevent.MotionEvent.y, out mask);
|
||
|
}
|
||
|
|
||
|
msg.message = Msg.WM_MOUSEMOVE;
|
||
|
msg.wParam = GetMousewParam(0);
|
||
|
msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
|
||
|
|
||
|
if (!hwnd.Enabled) {
|
||
|
IntPtr dummy;
|
||
|
|
||
|
msg.hwnd = hwnd.EnabledHwnd;
|
||
|
XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
|
||
|
msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
|
||
|
}
|
||
|
|
||
|
mouse_position.X = xevent.MotionEvent.x;
|
||
|
mouse_position.Y = xevent.MotionEvent.y;
|
||
|
|
||
|
if ((HoverState.Timer.Enabled) &&
|
||
|
(((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
|
||
|
((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
|
||
|
((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
|
||
|
((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
|
||
|
HoverState.Timer.Stop();
|
||
|
HoverState.Timer.Start();
|
||
|
HoverState.X = mouse_position.X;
|
||
|
HoverState.Y = mouse_position.Y;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
} else {
|
||
|
HitTest ht;
|
||
|
IntPtr dummy;
|
||
|
|
||
|
DriverDebug("GetMessage(): non-client area {0:X} MotionNotify x={1} y={2}",
|
||
|
client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(),
|
||
|
xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
msg.message = Msg.WM_NCMOUSEMOVE;
|
||
|
|
||
|
if (!hwnd.Enabled) {
|
||
|
msg.hwnd = hwnd.EnabledHwnd;
|
||
|
XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
|
||
|
msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
|
||
|
}
|
||
|
|
||
|
ht = NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
|
||
|
NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
|
||
|
|
||
|
mouse_position.X = xevent.MotionEvent.x;
|
||
|
mouse_position.Y = xevent.MotionEvent.y;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.EnterNotify: {
|
||
|
if (!hwnd.Enabled) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || xevent.AnyEvent.window != hwnd.client_window) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) { // Pseudo motion caused by grabbing
|
||
|
if (LastPointerWindow == xevent.AnyEvent.window)
|
||
|
goto ProcessNextMessage;
|
||
|
|
||
|
if (LastPointerWindow != IntPtr.Zero) {
|
||
|
Point enter_loc = new Point (xevent.ButtonEvent.x, xevent.ButtonEvent.y);
|
||
|
|
||
|
// We need this due to EnterNotify being fired on all the parent Widgets
|
||
|
// of the Widget being grabbed, and obviously in that scenario we are not
|
||
|
// actuallty entering them
|
||
|
Widget ctrl = Widget.FromHandle (hwnd.client_window);
|
||
|
foreach (Widget child_Widget in ctrl.Widgets.GetAllWidgets ())
|
||
|
if (child_Widget.Bounds.Contains (enter_loc))
|
||
|
goto ProcessNextMessage;
|
||
|
|
||
|
// A MouseLeave/LeaveNotify event is sent to the previous window
|
||
|
// until the mouse is ungrabbed, not when actually leaving its bounds
|
||
|
int x = xevent.CrossingEvent.x_root;
|
||
|
int y = xevent.CrossingEvent.y_root;
|
||
|
ScreenToClient (LastPointerWindow, ref x, ref y);
|
||
|
|
||
|
XEvent leaveEvent = new XEvent ();
|
||
|
leaveEvent.type = XEventName.LeaveNotify;
|
||
|
leaveEvent.CrossingEvent.display = DisplayHandle;
|
||
|
leaveEvent.CrossingEvent.window = LastPointerWindow;
|
||
|
leaveEvent.CrossingEvent.x = x;
|
||
|
leaveEvent.CrossingEvent.y = y;
|
||
|
leaveEvent.CrossingEvent.mode = NotifyMode.NotifyNormal;
|
||
|
Hwnd last_pointer_hwnd = Hwnd.ObjectFromHandle (LastPointerWindow);
|
||
|
last_pointer_hwnd.Queue.EnqueueLocked (leaveEvent);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LastPointerWindow = xevent.AnyEvent.window;
|
||
|
|
||
|
msg.message = Msg.WM_MOUSE_ENTER;
|
||
|
HoverState.X = xevent.CrossingEvent.x;
|
||
|
HoverState.Y = xevent.CrossingEvent.y;
|
||
|
HoverState.Timer.Enabled = true;
|
||
|
HoverState.Window = xevent.CrossingEvent.window;
|
||
|
|
||
|
// Win32 sends a WM_MOUSEMOVE after mouse enter
|
||
|
XEvent motionEvent = new XEvent ();
|
||
|
motionEvent.type = XEventName.MotionNotify;
|
||
|
motionEvent.MotionEvent.display = DisplayHandle;
|
||
|
motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
|
||
|
motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
|
||
|
motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
|
||
|
hwnd.Queue.EnqueueLocked (motionEvent);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.LeaveNotify: {
|
||
|
if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
|
||
|
WindowUngrabbed (hwnd.Handle);
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
if (!hwnd.Enabled) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
// If a grab is taking place, ignore it - we handle it in EnterNotify
|
||
|
if (Grab.Hwnd != IntPtr.Zero)
|
||
|
goto ProcessNextMessage;
|
||
|
|
||
|
// Reset the cursor explicitly on X11.
|
||
|
// X11 remembers the last set cursor for the window and in cases where
|
||
|
// the Widget won't get a WM_SETCURSOR X11 will restore the last
|
||
|
// known cursor, which we don't want.
|
||
|
//
|
||
|
SetCursor (hwnd.client_window, IntPtr.Zero);
|
||
|
|
||
|
msg.message=Msg.WM_MOUSELEAVE;
|
||
|
HoverState.Timer.Enabled = false;
|
||
|
HoverState.Window = IntPtr.Zero;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#if later
|
||
|
case XEventName.CreateNotify: {
|
||
|
if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
|
||
|
msg.message = WM_CREATE;
|
||
|
// Set up CreateStruct
|
||
|
} else {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
case XEventName.ReparentNotify: {
|
||
|
if (hwnd.parent == null) { // Toplevel
|
||
|
if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
|
||
|
hwnd.Reparented = true;
|
||
|
|
||
|
// 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;
|
||
|
|
||
|
if (hwnd.opacity != 0xffffffff) {
|
||
|
IntPtr opacity;
|
||
|
|
||
|
opacity = (IntPtr)(Int32)hwnd.opacity;
|
||
|
XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
|
||
|
}
|
||
|
SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
|
||
|
goto ProcessNextMessage;
|
||
|
} else {
|
||
|
hwnd.Reparented = false;
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
}
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
case XEventName.ConfigureNotify: {
|
||
|
if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
|
||
|
DriverDebug("GetMessage(): Window {0:X} ConfigureNotify x={1} y={2} width={3} height={4}",
|
||
|
hwnd.client_window.ToInt32(), xevent.ConfigureEvent.x,
|
||
|
xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
|
||
|
|
||
|
lock (hwnd.configure_lock) {
|
||
|
Form form = Widget.FromHandle (hwnd.client_window) as Form;
|
||
|
if (form != null && !hwnd.resizing_or_moving) {
|
||
|
if (hwnd.x != form.Bounds.X || hwnd.y != form.Bounds.Y) {
|
||
|
SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MOVE, IntPtr.Zero);
|
||
|
hwnd.resizing_or_moving = true;
|
||
|
} else if (hwnd.width != form.Bounds.Width || hwnd.height != form.Bounds.Height) {
|
||
|
SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_SIZE, IntPtr.Zero);
|
||
|
hwnd.resizing_or_moving = true;
|
||
|
}
|
||
|
if (hwnd.resizing_or_moving)
|
||
|
SendMessage (form.Handle, Msg.WM_ENTERSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
|
||
|
SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
|
||
|
hwnd.configure_pending = false;
|
||
|
|
||
|
// We need to adjust our client window to track the resize of whole_window
|
||
|
if (hwnd.whole_window != hwnd.client_window)
|
||
|
PerformNCCalc(hwnd);
|
||
|
}
|
||
|
}
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
case XEventName.FocusIn: {
|
||
|
// We received focus. We use X11 focus only to know if the app window does or does not have focus
|
||
|
// We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
|
||
|
// Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know
|
||
|
// about it having focus again
|
||
|
if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (FocusWindow == IntPtr.Zero) {
|
||
|
Widget c = Widget.FromHandle (hwnd.client_window);
|
||
|
|
||
|
if (c == null)
|
||
|
goto ProcessNextMessage;
|
||
|
Form form = c.FindForm ();
|
||
|
if (form == null)
|
||
|
goto ProcessNextMessage;
|
||
|
|
||
|
if (ActiveWindow != form.Handle) {
|
||
|
ActiveWindow = form.Handle;
|
||
|
SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
|
||
|
}
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
Keyboard.FocusIn (FocusWindow);
|
||
|
SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
case XEventName.FocusOut: {
|
||
|
// Se the comment for our FocusIn handler
|
||
|
if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
|
||
|
SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
|
||
|
}
|
||
|
|
||
|
Keyboard.FocusOut(hwnd.client_window);
|
||
|
SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
// We are already firing WM_SHOWWINDOW messages in the proper places, but I'm leaving this code
|
||
|
// in case we break a scenario not taken into account in the tests
|
||
|
case XEventName.MapNotify: {
|
||
|
/*if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
|
||
|
hwnd.mapped = true;
|
||
|
msg.message = Msg.WM_SHOWWINDOW;
|
||
|
msg.wParam = (IntPtr) 1;
|
||
|
// XXX we're missing the lParam..
|
||
|
break;
|
||
|
}*/
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
case XEventName.UnmapNotify: {
|
||
|
/*if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
|
||
|
hwnd.mapped = false;
|
||
|
msg.message = Msg.WM_SHOWWINDOW;
|
||
|
msg.wParam = (IntPtr) 0;
|
||
|
// XXX we're missing the lParam..
|
||
|
break;
|
||
|
}*/
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
case XEventName.Expose: {
|
||
|
if (!hwnd.Mapped) {
|
||
|
if (client) {
|
||
|
hwnd.expose_pending = false;
|
||
|
} else {
|
||
|
hwnd.nc_expose_pending = false;
|
||
|
}
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
if (client) {
|
||
|
if (!hwnd.expose_pending) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
} else {
|
||
|
if (!hwnd.nc_expose_pending) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
switch (hwnd.border_style) {
|
||
|
case FormBorderStyle.Fixed3D: {
|
||
|
Graphics g;
|
||
|
|
||
|
g = Graphics.FromHwnd(hwnd.whole_window);
|
||
|
if (hwnd.border_static)
|
||
|
WidgetPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
|
||
|
else
|
||
|
WidgetPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
|
||
|
g.Dispose();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case FormBorderStyle.FixedSingle: {
|
||
|
Graphics g;
|
||
|
|
||
|
g = Graphics.FromHwnd(hwnd.whole_window);
|
||
|
WidgetPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
|
||
|
g.Dispose();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
DriverDebug("GetMessage(): Window {0:X} Exposed non-client area {1},{2} {3}x{4}",
|
||
|
hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y,
|
||
|
xevent.ExposeEvent.width, xevent.ExposeEvent.height);
|
||
|
|
||
|
Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
|
||
|
Region region = new Region (rect);
|
||
|
IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
|
||
|
msg.message = Msg.WM_NCPAINT;
|
||
|
msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
|
||
|
msg.refobject = region;
|
||
|
break;
|
||
|
}
|
||
|
DriverDebug("GetMessage(): Window {0:X} Exposed area {1},{2} {3}x{4}",
|
||
|
hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y,
|
||
|
xevent.ExposeEvent.width, xevent.ExposeEvent.height);
|
||
|
if (Caret.Visible == true) {
|
||
|
Caret.Paused = true;
|
||
|
HideCaret();
|
||
|
}
|
||
|
|
||
|
if (Caret.Visible == true) {
|
||
|
ShowCaret();
|
||
|
Caret.Paused = false;
|
||
|
}
|
||
|
msg.message = Msg.WM_PAINT;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.DestroyNotify: {
|
||
|
|
||
|
// This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
|
||
|
hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
|
||
|
|
||
|
// We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
|
||
|
if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
|
||
|
CleanupCachedWindows (hwnd);
|
||
|
|
||
|
DriverDebug("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
|
||
|
|
||
|
msg.hwnd = hwnd.client_window;
|
||
|
msg.message=Msg.WM_DESTROY;
|
||
|
hwnd.Dispose();
|
||
|
} else {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case XEventName.ClientMessage: {
|
||
|
if (Dnd.HandleClientMessage (ref xevent)) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
|
||
|
XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
|
||
|
msg.message = Msg.WM_MOUSEHOVER;
|
||
|
msg.wParam = GetMousewParam(0);
|
||
|
msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
|
||
|
DebugHelper.Indent ();
|
||
|
DebugHelper.WriteLine (String.Format ("Posted message:" + (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 () + " for 0x{0:x}", xevent.ClientMessageEvent.ptr1.ToInt32 ()));
|
||
|
DebugHelper.Unindent ();
|
||
|
msg.hwnd = xevent.ClientMessageEvent.ptr1;
|
||
|
msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
|
||
|
msg.wParam = xevent.ClientMessageEvent.ptr3;
|
||
|
msg.lParam = xevent.ClientMessageEvent.ptr4;
|
||
|
if (msg.message == (Msg)Msg.WM_QUIT)
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (xevent.ClientMessageEvent.message_type == _XEMBED) {
|
||
|
#if DriverDebugXEmbed
|
||
|
Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
|
||
|
#endif
|
||
|
|
||
|
if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
|
||
|
XSizeHints hints = new XSizeHints();
|
||
|
IntPtr dummy;
|
||
|
|
||
|
XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
|
||
|
|
||
|
hwnd.width = hints.max_width;
|
||
|
hwnd.height = hints.max_height;
|
||
|
hwnd.ClientRect = Rectangle.Empty;
|
||
|
SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
|
||
|
if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
|
||
|
SendMessage (msg.hwnd, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero);
|
||
|
msg.message = Msg.WM_CLOSE;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// We should not get this, but I'll leave the code in case we need it in the future
|
||
|
if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
}
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
|
||
|
default: {
|
||
|
goto ProcessNextMessage;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
HitTest NCHitTest (Hwnd hwnd, int x, int y)
|
||
|
{
|
||
|
// The hit test is sent in screen coordinates
|
||
|
IntPtr dummy;
|
||
|
int screen_x, screen_y;
|
||
|
XTranslateCoordinates (DisplayHandle, hwnd.WholeWindow, RootWindow, x, y, out screen_x, out screen_y, out dummy);
|
||
|
return (HitTest) NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero,
|
||
|
(IntPtr) (screen_y << 16 | screen_x & 0xFFFF));
|
||
|
}
|
||
|
|
||
|
// Our very basic implementation of MoveResize - we can extend it later
|
||
|
// *if* needed
|
||
|
internal override void BeginMoveResize (IntPtr handle)
|
||
|
{
|
||
|
// We *need* to ungrab the pointer in the current display
|
||
|
XplatUI.UngrabWindow (Grab.Hwnd);
|
||
|
|
||
|
int x_root, y_root;
|
||
|
GetCursorPos (IntPtr.Zero, out x_root, out y_root);
|
||
|
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
|
||
|
SendNetWMMessage (hwnd.whole_window, _NET_WM_MOVERESIZE, (IntPtr) x_root, (IntPtr) y_root,
|
||
|
(IntPtr) NetWmMoveResize._NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT,
|
||
|
(IntPtr) 1); // left button
|
||
|
}
|
||
|
|
||
|
internal override bool GetText(IntPtr handle, out string text)
|
||
|
{
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
IntPtr actual_atom;
|
||
|
int actual_format;
|
||
|
IntPtr nitems;
|
||
|
IntPtr bytes_after;
|
||
|
IntPtr prop = IntPtr.Zero;
|
||
|
|
||
|
XGetWindowProperty(DisplayHandle, handle,
|
||
|
_NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
|
||
|
UTF8_STRING, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
|
||
|
|
||
|
if ((long)nitems > 0 && prop != IntPtr.Zero) {
|
||
|
text = Marshal.PtrToStringUni (prop, (int)nitems);
|
||
|
XFree (prop);
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
// fallback on the non-_NET property
|
||
|
IntPtr textptr;
|
||
|
|
||
|
textptr = IntPtr.Zero;
|
||
|
|
||
|
XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
|
||
|
if (textptr != IntPtr.Zero) {
|
||
|
text = Marshal.PtrToStringAnsi(textptr);
|
||
|
XFree(textptr);
|
||
|
return true;
|
||
|
} else {
|
||
|
text = "";
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void GetWindowPos(IntPtr handle, bool is_toplevel, out int x, out int y, out int width, out int height, out int client_width, out int client_height)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd != null) {
|
||
|
x = hwnd.x;
|
||
|
y = hwnd.y;
|
||
|
width = hwnd.width;
|
||
|
height = hwnd.height;
|
||
|
|
||
|
PerformNCCalc(hwnd);
|
||
|
|
||
|
client_width = hwnd.ClientRect.Width;
|
||
|
client_height = hwnd.ClientRect.Height;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Should we throw an exception or fail silently?
|
||
|
// throw new ArgumentException("Called with an invalid window handle", "handle");
|
||
|
|
||
|
x = 0;
|
||
|
y = 0;
|
||
|
width = 0;
|
||
|
height = 0;
|
||
|
client_width = 0;
|
||
|
client_height = 0;
|
||
|
}
|
||
|
|
||
|
internal override FormWindowState GetWindowState(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd.cached_window_state == (FormWindowState)(-1))
|
||
|
hwnd.cached_window_state = UpdateWindowState (handle);
|
||
|
|
||
|
return hwnd.cached_window_state;
|
||
|
}
|
||
|
|
||
|
FormWindowState UpdateWindowState (IntPtr handle) {
|
||
|
IntPtr actual_atom;
|
||
|
int actual_format;
|
||
|
IntPtr nitems;
|
||
|
IntPtr bytes_after;
|
||
|
IntPtr prop = IntPtr.Zero;
|
||
|
IntPtr atom;
|
||
|
int maximized;
|
||
|
bool minimized;
|
||
|
XWindowAttributes attributes;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
maximized = 0;
|
||
|
minimized = false;
|
||
|
XGetWindowProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
|
||
|
if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
|
||
|
for (int i = 0; i < (long)nitems; i++) {
|
||
|
atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
|
||
|
if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
|
||
|
maximized++;
|
||
|
} else if (atom == _NET_WM_STATE_HIDDEN) {
|
||
|
minimized = true;
|
||
|
}
|
||
|
}
|
||
|
XFree(prop);
|
||
|
}
|
||
|
|
||
|
if (minimized) {
|
||
|
return FormWindowState.Minimized;
|
||
|
} else if (maximized == 2) {
|
||
|
return FormWindowState.Maximized;
|
||
|
}
|
||
|
|
||
|
attributes = new XWindowAttributes();
|
||
|
XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
|
||
|
if (attributes.map_state == MapState.IsUnmapped) {
|
||
|
return (FormWindowState)(-1);
|
||
|
}
|
||
|
|
||
|
|
||
|
return FormWindowState.Normal;
|
||
|
}
|
||
|
|
||
|
internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea)
|
||
|
{
|
||
|
handle = Grab.Hwnd;
|
||
|
GrabConfined = Grab.Confined;
|
||
|
GrabArea = Grab.Area;
|
||
|
}
|
||
|
|
||
|
internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
IntPtr confine_to_window;
|
||
|
|
||
|
confine_to_window = IntPtr.Zero;
|
||
|
|
||
|
if (confine_to_handle != IntPtr.Zero) {
|
||
|
XWindowAttributes attributes = new XWindowAttributes();
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XGetWindowAttributes(DisplayHandle, hwnd.client_window, 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 = hwnd.client_window;
|
||
|
}
|
||
|
|
||
|
Grab.Hwnd = handle;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XGrabPointer(DisplayHandle, hwnd.client_window, false,
|
||
|
EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
|
||
|
EventMask.ButtonReleaseMask | EventMask.PointerMotionMask |
|
||
|
EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
|
||
|
GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void UngrabWindow(IntPtr hwnd)
|
||
|
{
|
||
|
lock (XlibLock) {
|
||
|
XUngrabPointer(DisplayHandle, IntPtr.Zero);
|
||
|
XFlush(DisplayHandle);
|
||
|
}
|
||
|
WindowUngrabbed (hwnd);
|
||
|
}
|
||
|
|
||
|
void WindowUngrabbed (IntPtr hwnd) {
|
||
|
bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
|
||
|
|
||
|
Grab.Hwnd = IntPtr.Zero;
|
||
|
Grab.Confined = false;
|
||
|
|
||
|
if (was_grabbed) {
|
||
|
// lparam should be the handle to the window gaining the mouse capture,
|
||
|
// but X doesn't seem to give us that information.
|
||
|
// Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
|
||
|
// X will send a NotifyUngrab, but since it comes late sometimes we're
|
||
|
// calling WindowUngrabbed directly from UngrabWindow in order to send
|
||
|
// this WM right away.
|
||
|
SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void HandleException(Exception e)
|
||
|
{
|
||
|
StackTrace st = new StackTrace(e, true);
|
||
|
Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
|
||
|
Console.WriteLine("{0}{1}", e.Message, st.ToString());
|
||
|
}
|
||
|
|
||
|
internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (clear) {
|
||
|
AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
|
||
|
} else {
|
||
|
AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void InvalidateNC (IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
|
||
|
}
|
||
|
|
||
|
internal override bool IsEnabled(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
|
||
|
return (hwnd != null && hwnd.Enabled);
|
||
|
}
|
||
|
|
||
|
internal override bool IsVisible(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
|
||
|
return (hwnd != null && hwnd.visible);
|
||
|
}
|
||
|
|
||
|
internal override void KillTimer(Timer timer)
|
||
|
{
|
||
|
XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
|
||
|
|
||
|
if (queue == null) {
|
||
|
// This isn't really an error, MS doesn't start the timer if
|
||
|
// it has no assosciated queue. In this case, remove the timer
|
||
|
// from the list of unattached timers (if it was enabled).
|
||
|
lock (unattached_timer_list) {
|
||
|
if (unattached_timer_list.Contains (timer))
|
||
|
unattached_timer_list.Remove (timer);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
queue.timer_list.Remove (timer);
|
||
|
}
|
||
|
|
||
|
internal override void MenuToScreen(IntPtr handle, ref int x, ref int y)
|
||
|
{
|
||
|
int dest_x_return;
|
||
|
int dest_y_return;
|
||
|
IntPtr child;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
|
||
|
}
|
||
|
|
||
|
x = dest_x_return;
|
||
|
y = dest_y_return;
|
||
|
}
|
||
|
|
||
|
internal override void OverrideCursor(IntPtr cursor)
|
||
|
{
|
||
|
if (Grab.Hwnd != IntPtr.Zero) {
|
||
|
XChangeActivePointerGrab (DisplayHandle,
|
||
|
EventMask.ButtonMotionMask |
|
||
|
EventMask.PointerMotionMask |
|
||
|
EventMask.PointerMotionHintMask |
|
||
|
EventMask.ButtonPressMask |
|
||
|
EventMask.ButtonReleaseMask,
|
||
|
cursor, IntPtr.Zero);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
OverrideCursorHandle = cursor;
|
||
|
}
|
||
|
|
||
|
internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client)
|
||
|
{
|
||
|
PaintEventArgs paint_event;
|
||
|
Hwnd hwnd;
|
||
|
Hwnd paint_hwnd;
|
||
|
|
||
|
//
|
||
|
// handle (and paint_hwnd) refers to the window that is should be painted.
|
||
|
// msg.HWnd (and hwnd) refers to the window that got the paint message.
|
||
|
//
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
|
||
|
if (msg.HWnd == handle) {
|
||
|
paint_hwnd = hwnd;
|
||
|
} else {
|
||
|
paint_hwnd = Hwnd.ObjectFromHandle (handle);
|
||
|
}
|
||
|
|
||
|
if (Caret.Visible == true) {
|
||
|
Caret.Paused = true;
|
||
|
HideCaret();
|
||
|
}
|
||
|
|
||
|
Graphics dc;
|
||
|
|
||
|
if (client) {
|
||
|
dc = Graphics.FromHwnd (paint_hwnd.client_window);
|
||
|
|
||
|
Region clip_region = new Region ();
|
||
|
clip_region.MakeEmpty();
|
||
|
|
||
|
foreach (Rectangle r in hwnd.ClipRectangles) {
|
||
|
/* Expand the region slightly.
|
||
|
* See bug 464464.
|
||
|
*/
|
||
|
Rectangle r2 = Rectangle.FromLTRB (r.Left, r.Top, r.Right, r.Bottom + 1);
|
||
|
clip_region.Union (r2);
|
||
|
}
|
||
|
|
||
|
if (hwnd.UserClip != null) {
|
||
|
clip_region.Intersect(hwnd.UserClip);
|
||
|
}
|
||
|
|
||
|
dc.Clip = clip_region;
|
||
|
paint_event = new PaintEventArgs(dc, hwnd.Invalid);
|
||
|
hwnd.expose_pending = false;
|
||
|
|
||
|
hwnd.ClearInvalidArea();
|
||
|
|
||
|
hwnd.drawing_stack.Push (paint_event);
|
||
|
hwnd.drawing_stack.Push (dc);
|
||
|
|
||
|
return paint_event;
|
||
|
} else {
|
||
|
dc = Graphics.FromHwnd (paint_hwnd.whole_window);
|
||
|
|
||
|
if (!hwnd.nc_invalid.IsEmpty) {
|
||
|
dc.SetClip (hwnd.nc_invalid);
|
||
|
paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
|
||
|
} else {
|
||
|
paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
|
||
|
}
|
||
|
hwnd.nc_expose_pending = false;
|
||
|
|
||
|
hwnd.ClearNcInvalidArea ();
|
||
|
|
||
|
hwnd.drawing_stack.Push (paint_event);
|
||
|
hwnd.drawing_stack.Push (dc);
|
||
|
|
||
|
return paint_event;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
|
||
|
|
||
|
Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
|
||
|
dc.Flush();
|
||
|
dc.Dispose();
|
||
|
|
||
|
PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
|
||
|
pe.SetGraphics (null);
|
||
|
pe.Dispose ();
|
||
|
|
||
|
if (Caret.Visible == true) {
|
||
|
ShowCaret();
|
||
|
Caret.Paused = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[MonoTODO("Implement filtering and PM_NOREMOVE")]
|
||
|
internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags)
|
||
|
{
|
||
|
XEventQueue queue = (XEventQueue) queue_id;
|
||
|
bool pending;
|
||
|
|
||
|
if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
|
||
|
throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag
|
||
|
}
|
||
|
|
||
|
pending = false;
|
||
|
if (queue.Count > 0) {
|
||
|
pending = true;
|
||
|
} else {
|
||
|
// Only call UpdateMessageQueue if real events are pending
|
||
|
// otherwise we go to sleep on the socket
|
||
|
if (XPending(DisplayHandle) != 0) {
|
||
|
UpdateMessageQueue((XEventQueue)queue_id);
|
||
|
pending = true;
|
||
|
} else if (((XEventQueue)queue_id).Paint.Count > 0) {
|
||
|
pending = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CheckTimers(queue.timer_list, DateTime.UtcNow);
|
||
|
|
||
|
if (!pending) {
|
||
|
return false;
|
||
|
}
|
||
|
return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
|
||
|
}
|
||
|
|
||
|
internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam)
|
||
|
{
|
||
|
XEvent xevent = new XEvent ();
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
xevent.type = XEventName.ClientMessage;
|
||
|
xevent.ClientMessageEvent.display = DisplayHandle;
|
||
|
|
||
|
if (hwnd != null) {
|
||
|
xevent.ClientMessageEvent.window = hwnd.whole_window;
|
||
|
} else {
|
||
|
xevent.ClientMessageEvent.window = IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
|
||
|
xevent.ClientMessageEvent.format = 32;
|
||
|
xevent.ClientMessageEvent.ptr1 = handle;
|
||
|
xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
|
||
|
xevent.ClientMessageEvent.ptr3 = wparam;
|
||
|
xevent.ClientMessageEvent.ptr4 = lparam;
|
||
|
|
||
|
if (hwnd != null)
|
||
|
hwnd.Queue.EnqueueLocked (xevent);
|
||
|
else
|
||
|
ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal override void PostQuitMessage(int exitCode)
|
||
|
{
|
||
|
ApplicationContext ctx = Application.MWFThread.Current.Context;
|
||
|
Form f = ctx != null ? ctx.MainForm : null;
|
||
|
if (f != null)
|
||
|
PostMessage (Application.MWFThread.Current.Context.MainForm.window.Handle, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
|
||
|
else
|
||
|
PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
|
||
|
XFlush(DisplayHandle);
|
||
|
}
|
||
|
|
||
|
internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
|
||
|
{
|
||
|
// TODO
|
||
|
}
|
||
|
|
||
|
internal override void RequestNCRecalc(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd == null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PerformNCCalc(hwnd);
|
||
|
SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
|
||
|
InvalidateNC(handle);
|
||
|
}
|
||
|
|
||
|
internal override void ResetMouseHover(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
if (hwnd == null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
HoverState.Timer.Enabled = true;
|
||
|
HoverState.X = mouse_position.X;
|
||
|
HoverState.Y = mouse_position.Y;
|
||
|
HoverState.Window = handle;
|
||
|
}
|
||
|
|
||
|
|
||
|
internal override void ScreenToClient(IntPtr handle, ref int x, ref int y)
|
||
|
{
|
||
|
int dest_x_return;
|
||
|
int dest_y_return;
|
||
|
IntPtr child;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
|
||
|
}
|
||
|
|
||
|
x = dest_x_return;
|
||
|
y = dest_y_return;
|
||
|
}
|
||
|
|
||
|
internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y)
|
||
|
{
|
||
|
int dest_x_return;
|
||
|
int dest_y_return;
|
||
|
IntPtr child;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
|
||
|
}
|
||
|
|
||
|
Form form = Widget.FromHandle (handle) as Form;
|
||
|
if (form != null && form.window_manager != null) {
|
||
|
dest_y_return -= form.window_manager.TitleBarHeight;
|
||
|
}
|
||
|
|
||
|
x = dest_x_return;
|
||
|
y = dest_y_return;
|
||
|
}
|
||
|
|
||
|
bool GraphicsExposePredicate (IntPtr display, ref XEvent xevent, IntPtr arg)
|
||
|
{
|
||
|
return (xevent.type == XEventName.GraphicsExpose || xevent.type == XEventName.NoExpose) &&
|
||
|
arg == xevent.GraphicsExposeEvent.drawable;
|
||
|
}
|
||
|
|
||
|
delegate bool EventPredicate (IntPtr display, ref XEvent xevent, IntPtr arg);
|
||
|
|
||
|
void ProcessGraphicsExpose (Hwnd hwnd)
|
||
|
{
|
||
|
XEvent xevent = new XEvent ();
|
||
|
IntPtr handle = Hwnd.HandleFromObject (hwnd);
|
||
|
EventPredicate predicate = GraphicsExposePredicate;
|
||
|
|
||
|
for (;;) {
|
||
|
XIfEvent (Display, ref xevent, predicate, handle);
|
||
|
if (xevent.type != XEventName.GraphicsExpose)
|
||
|
break;
|
||
|
|
||
|
AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.GraphicsExposeEvent.x, xevent.GraphicsExposeEvent.y,
|
||
|
xevent.GraphicsExposeEvent.width, xevent.GraphicsExposeEvent.height);
|
||
|
|
||
|
if (xevent.GraphicsExposeEvent.count == 0)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
IntPtr gc;
|
||
|
XGCValues gc_values;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
|
||
|
if (!r.IsEmpty) {
|
||
|
/* We have an invalid area in the window we're scrolling.
|
||
|
Adjust our stored invalid rectangle to to match the scrolled amount */
|
||
|
|
||
|
r.X += XAmount;
|
||
|
r.Y += YAmount;
|
||
|
|
||
|
if (r.X < 0) {
|
||
|
r.Width += r.X;
|
||
|
r.X =0;
|
||
|
}
|
||
|
|
||
|
if (r.Y < 0) {
|
||
|
r.Height += r.Y;
|
||
|
r.Y =0;
|
||
|
}
|
||
|
|
||
|
if (area.Contains (hwnd.Invalid))
|
||
|
hwnd.ClearInvalidArea ();
|
||
|
hwnd.AddInvalidArea(r);
|
||
|
}
|
||
|
|
||
|
gc_values = new XGCValues();
|
||
|
|
||
|
if (with_children) {
|
||
|
gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
|
||
|
}
|
||
|
|
||
|
gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
|
||
|
|
||
|
Rectangle visible_rect = GetTotalVisibleArea (hwnd.client_window);
|
||
|
visible_rect.Intersect (area);
|
||
|
|
||
|
Rectangle dest_rect = visible_rect;
|
||
|
dest_rect.Y += YAmount;
|
||
|
dest_rect.X += XAmount;
|
||
|
dest_rect.Intersect (area);
|
||
|
|
||
|
Point src = new Point (dest_rect.X - XAmount, dest_rect.Y - YAmount);
|
||
|
XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src.X, src.Y,
|
||
|
dest_rect.Width, dest_rect.Height, dest_rect.X, dest_rect.Y);
|
||
|
|
||
|
Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
|
||
|
AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
|
||
|
|
||
|
ProcessGraphicsExpose (hwnd);
|
||
|
|
||
|
XFreeGC(DisplayHandle, gc);
|
||
|
}
|
||
|
|
||
|
internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
Rectangle rect;
|
||
|
|
||
|
hwnd = Hwnd.GetObjectFromWindow(handle);
|
||
|
|
||
|
rect = hwnd.ClientRect;
|
||
|
rect.X = 0;
|
||
|
rect.Y = 0;
|
||
|
ScrollWindow(handle, rect, XAmount, YAmount, with_children);
|
||
|
}
|
||
|
|
||
|
Rectangle GetDirtyArea (Rectangle total_area, Rectangle valid_area, int XAmount, int YAmount)
|
||
|
{
|
||
|
Rectangle dirty_area = total_area;
|
||
|
|
||
|
if (YAmount > 0)
|
||
|
dirty_area.Height -= valid_area.Height;
|
||
|
else if (YAmount < 0) {
|
||
|
dirty_area.Height -= valid_area.Height;
|
||
|
dirty_area.Y += valid_area.Height;
|
||
|
}
|
||
|
|
||
|
if (XAmount > 0)
|
||
|
dirty_area.Width -= valid_area.Width;
|
||
|
else if (XAmount < 0) {
|
||
|
dirty_area.Width -= valid_area.Width;
|
||
|
dirty_area.X += valid_area.Width;
|
||
|
}
|
||
|
|
||
|
return dirty_area;
|
||
|
}
|
||
|
|
||
|
Rectangle GetTotalVisibleArea (IntPtr handle)
|
||
|
{
|
||
|
Widget c = Widget.FromHandle (handle);
|
||
|
|
||
|
Rectangle visible_area = c.ClientRectangle;
|
||
|
visible_area.Location = c.PointToScreen (Point.Empty);
|
||
|
|
||
|
for (Widget parent = c.Parent; parent != null; parent = parent.Parent) {
|
||
|
if (!parent.IsHandleCreated || !parent.Visible)
|
||
|
return visible_area; // Non visible, not need to finish computations
|
||
|
|
||
|
Rectangle r = parent.ClientRectangle;
|
||
|
r.Location = parent.PointToScreen (Point.Empty);
|
||
|
|
||
|
visible_area.Intersect (r);
|
||
|
}
|
||
|
|
||
|
visible_area.Location = c.PointToClient (visible_area.Location);
|
||
|
return visible_area;
|
||
|
}
|
||
|
|
||
|
internal override void SendAsyncMethod (AsyncMethodData method)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
XEvent xevent = new XEvent ();
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(method.Handle);
|
||
|
|
||
|
xevent.type = XEventName.ClientMessage;
|
||
|
xevent.ClientMessageEvent.display = DisplayHandle;
|
||
|
xevent.ClientMessageEvent.window = method.Handle;
|
||
|
xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
|
||
|
xevent.ClientMessageEvent.format = 32;
|
||
|
xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
|
||
|
|
||
|
hwnd.Queue.EnqueueLocked (xevent);
|
||
|
|
||
|
WakeupMain ();
|
||
|
}
|
||
|
|
||
|
delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
|
||
|
|
||
|
internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
|
||
|
{
|
||
|
Hwnd h;
|
||
|
h = Hwnd.ObjectFromHandle(hwnd);
|
||
|
|
||
|
if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
|
||
|
AsyncMethodResult result;
|
||
|
AsyncMethodData data;
|
||
|
|
||
|
result = new AsyncMethodResult ();
|
||
|
data = new AsyncMethodData ();
|
||
|
|
||
|
data.Handle = hwnd;
|
||
|
data.Method = new WndProcDelegate (NativeWindow.WndProc);
|
||
|
data.Args = new object[] { hwnd, message, wParam, lParam };
|
||
|
data.Result = result;
|
||
|
|
||
|
SendAsyncMethod (data);
|
||
|
DriverDebug("Sending {0} message across.", message);
|
||
|
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
string key = hwnd + ":" + message;
|
||
|
if (messageHold[key] != null)
|
||
|
messageHold[key] = ((int)messageHold[key]) - 1;
|
||
|
return NativeWindow.WndProc(hwnd, message, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
internal override 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 = DisplayHandle;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
internal override void SetAllowDrop (IntPtr handle, bool value)
|
||
|
{
|
||
|
// We allow drop on all windows
|
||
|
}
|
||
|
|
||
|
internal override DragDropEffects StartDrag (IntPtr handle, object data,
|
||
|
DragDropEffects allowed_effects)
|
||
|
{
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
|
||
|
|
||
|
if (hwnd == null)
|
||
|
throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
|
||
|
|
||
|
return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
|
||
|
}
|
||
|
|
||
|
internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style)
|
||
|
{
|
||
|
Form form = Widget.FromHandle (handle) as Form;
|
||
|
if (form != null && form.window_manager == null) {
|
||
|
CreateParams cp = form.GetCreateParams ();
|
||
|
if (border_style == FormBorderStyle.FixedToolWindow ||
|
||
|
border_style == FormBorderStyle.SizableToolWindow ||
|
||
|
cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
|
||
|
form.window_manager = new ToolWindowManager (form);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RequestNCRecalc(handle);
|
||
|
}
|
||
|
|
||
|
internal override void SetCaretPos(IntPtr handle, int x, int y)
|
||
|
{
|
||
|
if (Caret.Hwnd == handle) {
|
||
|
Caret.Timer.Stop();
|
||
|
HideCaret();
|
||
|
|
||
|
Caret.X = x;
|
||
|
Caret.Y = y;
|
||
|
|
||
|
Keyboard.SetCaretPos (Caret, handle, x, y);
|
||
|
|
||
|
if (Caret.Visible == true) {
|
||
|
ShowCaret();
|
||
|
Caret.Timer.Start();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void SetClipRegion(IntPtr handle, Region region)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
if (hwnd == null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
hwnd.UserClip = region;
|
||
|
}
|
||
|
|
||
|
internal override 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);
|
||
|
lock (XlibLock) {
|
||
|
if (cursor != IntPtr.Zero) {
|
||
|
XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
|
||
|
} else {
|
||
|
XUndefineCursor(DisplayHandle, hwnd.whole_window);
|
||
|
}
|
||
|
XFlush(DisplayHandle);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
lock (XlibLock) {
|
||
|
XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QueryPointer (IntPtr display, 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;
|
||
|
|
||
|
XGrabServer (display);
|
||
|
|
||
|
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;
|
||
|
XQueryPointer(display, c, out root, out c,
|
||
|
out root_x, out root_y, out child_x, out child_y,
|
||
|
out mask);
|
||
|
}
|
||
|
XUngrabServer (display);
|
||
|
XFlush (display);
|
||
|
|
||
|
child = child_last;
|
||
|
}
|
||
|
|
||
|
internal override void SetCursorPos(IntPtr handle, int x, int y)
|
||
|
{
|
||
|
if (handle == IntPtr.Zero) {
|
||
|
lock (XlibLock) {
|
||
|
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 (DisplayHandle, RootWindow,
|
||
|
out root,
|
||
|
out child,
|
||
|
out root_x, out root_y,
|
||
|
out child_x, out child_y,
|
||
|
out mask);
|
||
|
|
||
|
XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
|
||
|
|
||
|
XFlush (DisplayHandle);
|
||
|
|
||
|
/* then we need to a
|
||
|
* QueryPointer after warping
|
||
|
* to manually generate a
|
||
|
* motion event for the window
|
||
|
* we move into.
|
||
|
*/
|
||
|
QueryPointer (DisplayHandle, RootWindow,
|
||
|
out root,
|
||
|
out child,
|
||
|
out root_x, out root_y,
|
||
|
out child_x, out child_y,
|
||
|
out mask);
|
||
|
|
||
|
Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
|
||
|
if (child_hwnd == null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
XEvent xevent = new XEvent ();
|
||
|
|
||
|
xevent.type = XEventName.MotionNotify;
|
||
|
xevent.MotionEvent.display = DisplayHandle;
|
||
|
xevent.MotionEvent.window = child_hwnd.client_window;
|
||
|
xevent.MotionEvent.root = RootWindow;
|
||
|
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.EnqueueLocked (xevent);
|
||
|
}
|
||
|
} else {
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
lock (XlibLock) {
|
||
|
XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void SetFocus(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
IntPtr prev_focus_window;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd.client_window == FocusWindow) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Win32 doesn't do anything if disabled
|
||
|
if (!hwnd.enabled)
|
||
|
return;
|
||
|
|
||
|
prev_focus_window = FocusWindow;
|
||
|
FocusWindow = hwnd.client_window;
|
||
|
|
||
|
if (prev_focus_window != IntPtr.Zero) {
|
||
|
SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
|
||
|
}
|
||
|
Keyboard.FocusIn (FocusWindow);
|
||
|
SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
|
||
|
|
||
|
//XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
|
||
|
}
|
||
|
|
||
|
internal override void SetIcon(IntPtr handle, Icon icon)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
if (hwnd != null) {
|
||
|
SetIcon(hwnd, icon);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void SetMenu(IntPtr handle, Menu menu)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
hwnd.menu = menu;
|
||
|
|
||
|
RequestNCRecalc(handle);
|
||
|
}
|
||
|
|
||
|
internal override void SetModal(IntPtr handle, bool Modal)
|
||
|
{
|
||
|
if (Modal) {
|
||
|
ModalWindows.Push(handle);
|
||
|
} else {
|
||
|
if (ModalWindows.Contains(handle)) {
|
||
|
ModalWindows.Pop();
|
||
|
}
|
||
|
if (ModalWindows.Count > 0) {
|
||
|
Activate((IntPtr)ModalWindows.Peek());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
|
||
|
Widget ctrl = Widget.FromHandle (handle);
|
||
|
SetWMStyles (hwnd, ctrl.GetCreateParams ());
|
||
|
}
|
||
|
|
||
|
internal override IntPtr SetParent(IntPtr handle, IntPtr parent)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
hwnd.parent = Hwnd.ObjectFromHandle(parent);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
DriverDebug("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
|
||
|
XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
|
||
|
}
|
||
|
|
||
|
return IntPtr.Zero;
|
||
|
}
|
||
|
|
||
|
internal override void SetTimer (Timer timer)
|
||
|
{
|
||
|
XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
|
||
|
|
||
|
if (queue == null) {
|
||
|
// This isn't really an error, MS doesn't start the timer if
|
||
|
// it has no assosciated queue at this stage (it will be
|
||
|
// enabled when a window is activated).
|
||
|
unattached_timer_list.Add (timer);
|
||
|
return;
|
||
|
}
|
||
|
queue.timer_list.Add (timer);
|
||
|
WakeupMain ();
|
||
|
}
|
||
|
|
||
|
internal override bool SetTopmost(IntPtr handle, bool enabled)
|
||
|
{
|
||
|
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
hwnd.topmost = enabled;
|
||
|
|
||
|
if (enabled) {
|
||
|
lock (XlibLock) {
|
||
|
if (hwnd.Mapped) {
|
||
|
SendNetWMMessage(hwnd.WholeWindow, _NET_WM_STATE, (IntPtr) NetWmStateRequest._NET_WM_STATE_ADD, _NET_WM_STATE_ABOVE, IntPtr.Zero);
|
||
|
} else {
|
||
|
int[] atoms = new int[8];
|
||
|
atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
|
||
|
XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
lock (XlibLock) {
|
||
|
if (hwnd.Mapped)
|
||
|
SendNetWMMessage(hwnd.WholeWindow, _NET_WM_STATE, (IntPtr) NetWmStateRequest._NET_WM_STATE_REMOVE, _NET_WM_STATE_ABOVE, IntPtr.Zero);
|
||
|
else
|
||
|
XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal override bool SetOwner(IntPtr handle, IntPtr handle_owner)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
Hwnd hwnd_owner;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (handle_owner != IntPtr.Zero) {
|
||
|
hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
|
||
|
lock (XlibLock) {
|
||
|
int[] atoms;
|
||
|
|
||
|
atoms = new int[8];
|
||
|
|
||
|
atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
|
||
|
XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
|
||
|
|
||
|
if (hwnd_owner != null) {
|
||
|
XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
|
||
|
} else {
|
||
|
XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
lock (XlibLock) {
|
||
|
XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
hwnd.visible = visible;
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
if (visible) {
|
||
|
MapWindow(hwnd, WindowType.Both);
|
||
|
|
||
|
if (Widget.FromHandle(handle) is Form) {
|
||
|
FormWindowState s;
|
||
|
|
||
|
s = ((Form)Widget.FromHandle(handle)).WindowState;
|
||
|
|
||
|
switch(s) {
|
||
|
case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
|
||
|
case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
|
||
|
}
|
||
|
else {
|
||
|
UnmapWindow(hwnd, WindowType.Both);
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max)
|
||
|
{
|
||
|
Widget ctrl = Widget.FromHandle (handle);
|
||
|
SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
|
||
|
}
|
||
|
|
||
|
internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
XSizeHints hints;
|
||
|
IntPtr dummy;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
if (hwnd == null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
|
||
|
min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
|
||
|
|
||
|
hints = new XSizeHints();
|
||
|
|
||
|
XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
|
||
|
if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
|
||
|
if (cp != null)
|
||
|
min = TranslateWindowSizeToXWindowSize (cp, min);
|
||
|
hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
|
||
|
hints.min_width = min.Width;
|
||
|
hints.min_height = min.Height;
|
||
|
}
|
||
|
|
||
|
if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
|
||
|
if (cp != null)
|
||
|
max = TranslateWindowSizeToXWindowSize (cp, max);
|
||
|
hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
|
||
|
hints.max_width = max.Width;
|
||
|
hints.max_height = max.Height;
|
||
|
}
|
||
|
|
||
|
if (hints.flags != IntPtr.Zero) {
|
||
|
// The Metacity team has decided that they won't care about this when clicking the maximize icon,
|
||
|
// they will maximize the window to fill the screen/parent no matter what.
|
||
|
// http://bugzilla.ximian.com/show_bug.cgi?id=80021
|
||
|
XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
|
||
|
}
|
||
|
|
||
|
if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
|
||
|
if (cp != null)
|
||
|
maximized.Size = TranslateWindowSizeToXWindowSize (cp);
|
||
|
hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
|
||
|
hints.x = maximized.X;
|
||
|
hints.y = maximized.Y;
|
||
|
hints.width = maximized.Width;
|
||
|
hints.height = maximized.Height;
|
||
|
|
||
|
// Metacity does not seem to follow this constraint for maximized (zoomed) windows
|
||
|
XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd == null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Win32 automatically changes negative width/height to 0.
|
||
|
if (width < 0)
|
||
|
width = 0;
|
||
|
if (height < 0)
|
||
|
height = 0;
|
||
|
|
||
|
// X requires a sanity check for width & height; otherwise it dies
|
||
|
if (hwnd.zero_sized && width > 0 && height > 0) {
|
||
|
if (hwnd.visible) {
|
||
|
MapWindow(hwnd, WindowType.Whole);
|
||
|
}
|
||
|
hwnd.zero_sized = false;
|
||
|
}
|
||
|
|
||
|
if ((width < 1) || (height < 1)) {
|
||
|
hwnd.zero_sized = true;
|
||
|
UnmapWindow(hwnd, WindowType.Whole);
|
||
|
}
|
||
|
|
||
|
// Save a server roundtrip (and prevent a feedback loop)
|
||
|
if ((hwnd.x == x) && (hwnd.y == y) &&
|
||
|
(hwnd.width == width) && (hwnd.height == height)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!hwnd.zero_sized) {
|
||
|
//Hack?
|
||
|
hwnd.x = x;
|
||
|
hwnd.y = y;
|
||
|
hwnd.width = width;
|
||
|
hwnd.height = height;
|
||
|
SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
|
||
|
|
||
|
if (hwnd.fixed_size) {
|
||
|
SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
|
||
|
}
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
Widget ctrl = Widget.FromHandle (handle);
|
||
|
Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
|
||
|
MoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
|
||
|
PerformNCCalc(hwnd);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Update our position/size immediately, so
|
||
|
// that future calls to SetWindowPos aren't
|
||
|
// kept from calling XMoveResizeWindow (by the
|
||
|
// "Save a server roundtrip" block above).
|
||
|
hwnd.x = x;
|
||
|
hwnd.y = y;
|
||
|
hwnd.width = width;
|
||
|
hwnd.height = height;
|
||
|
hwnd.ClientRect = Rectangle.Empty;
|
||
|
}
|
||
|
|
||
|
internal override void SetWindowState(IntPtr handle, FormWindowState state)
|
||
|
{
|
||
|
FormWindowState current_state;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
current_state = GetWindowState(handle);
|
||
|
|
||
|
if (current_state == state) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch(state) {
|
||
|
case FormWindowState.Normal: {
|
||
|
lock (XlibLock) {
|
||
|
if (current_state == FormWindowState.Minimized) {
|
||
|
MapWindow(hwnd, WindowType.Both);
|
||
|
} else if (current_state == FormWindowState.Maximized) {
|
||
|
SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
|
||
|
}
|
||
|
}
|
||
|
Activate(handle);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case FormWindowState.Minimized: {
|
||
|
lock (XlibLock) {
|
||
|
if (current_state == FormWindowState.Maximized) {
|
||
|
SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
|
||
|
}
|
||
|
XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case FormWindowState.Maximized: {
|
||
|
lock (XlibLock) {
|
||
|
if (current_state == FormWindowState.Minimized) {
|
||
|
MapWindow(hwnd, WindowType.Both);
|
||
|
}
|
||
|
|
||
|
SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
|
||
|
}
|
||
|
Activate(handle);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void SetWindowStyle(IntPtr handle, CreateParams cp)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
SetHwndStyles(hwnd, cp);
|
||
|
SetWMStyles(hwnd, cp);
|
||
|
}
|
||
|
|
||
|
internal override double GetWindowTransparency(IntPtr handle)
|
||
|
{
|
||
|
return 1.0;
|
||
|
}
|
||
|
|
||
|
internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
IntPtr opacity;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (hwnd == null) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
hwnd.opacity = (uint)(0xffffffff * transparency);
|
||
|
opacity = (IntPtr)hwnd.opacity;
|
||
|
|
||
|
if (transparency >= 1.0) {
|
||
|
XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_OPACITY);
|
||
|
} else {
|
||
|
XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom)
|
||
|
{
|
||
|
Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (!hwnd.mapped) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (top) {
|
||
|
lock (XlibLock) {
|
||
|
XRaiseWindow(DisplayHandle, hwnd.whole_window);
|
||
|
}
|
||
|
return true;
|
||
|
} else if (!bottom) {
|
||
|
Hwnd after_hwnd = null;
|
||
|
|
||
|
if (after_handle != IntPtr.Zero) {
|
||
|
after_hwnd = Hwnd.ObjectFromHandle(after_handle);
|
||
|
}
|
||
|
|
||
|
XWindowChanges values = new XWindowChanges();
|
||
|
|
||
|
if (after_hwnd == null) {
|
||
|
// Work around metacity 'issues'
|
||
|
int[] atoms;
|
||
|
|
||
|
atoms = new int[2];
|
||
|
atoms[0] = unixtime();
|
||
|
XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
|
||
|
|
||
|
XRaiseWindow(DisplayHandle, hwnd.whole_window);
|
||
|
SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
|
||
|
return true;
|
||
|
//throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
|
||
|
}
|
||
|
|
||
|
values.sibling = after_hwnd.whole_window;
|
||
|
values.stack_mode = StackMode.Below;
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
|
||
|
}
|
||
|
} else {
|
||
|
// Bottom
|
||
|
lock (XlibLock) {
|
||
|
XLowerWindow(DisplayHandle, hwnd.whole_window);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
internal override void ShowCursor(bool show)
|
||
|
{
|
||
|
; // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
|
||
|
}
|
||
|
|
||
|
internal override object StartLoop(Thread thread)
|
||
|
{
|
||
|
XEventQueue q = ThreadQueue(thread);
|
||
|
return q;
|
||
|
}
|
||
|
|
||
|
internal override TransparencySupport SupportsTransparency()
|
||
|
{
|
||
|
// We need to check if the x compositing manager is running
|
||
|
return TransparencySupport.Set;
|
||
|
}
|
||
|
|
||
|
internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt)
|
||
|
{
|
||
|
GetSystrayManagerWindow();
|
||
|
|
||
|
if (SystrayMgrWindow != IntPtr.Zero) {
|
||
|
XSizeHints size_hints;
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
DriverDebug("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
|
||
|
|
||
|
// Oh boy.
|
||
|
if (hwnd.client_window != hwnd.whole_window) {
|
||
|
Keyboard.DestroyICForWindow (hwnd.client_window);
|
||
|
XDestroyWindow(DisplayHandle, hwnd.client_window);
|
||
|
hwnd.client_window = hwnd.whole_window;
|
||
|
}
|
||
|
|
||
|
/* by virtue of the way the tests are ordered when determining if it's PAINT
|
||
|
or NCPAINT, client_window == whole_window 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). */
|
||
|
if (hwnd.nc_expose_pending) {
|
||
|
hwnd.nc_expose_pending = false;
|
||
|
if (!hwnd.expose_pending)
|
||
|
hwnd.Queue.Paint.Remove (hwnd);
|
||
|
}
|
||
|
|
||
|
// We are going to be directly mapped by the system tray, so mark as mapped
|
||
|
// so we can later properly unmap it.
|
||
|
hwnd.mapped = true;
|
||
|
|
||
|
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;
|
||
|
|
||
|
XSetWMNormalHints(DisplayHandle, hwnd.whole_window, 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...
|
||
|
XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
|
||
|
|
||
|
// Need to pick some reasonable defaults
|
||
|
tt = new ToolTip();
|
||
|
tt.AutomaticDelay = 350;
|
||
|
tt.InitialDelay = 250;
|
||
|
tt.ReshowDelay = 250;
|
||
|
tt.ShowAlways = true;
|
||
|
|
||
|
if ((tip != null) && (tip != string.Empty)) {
|
||
|
tt.SetToolTip(Widget.FromHandle(handle), tip);
|
||
|
tt.Active = true;
|
||
|
} else {
|
||
|
tt.Active = false;
|
||
|
}
|
||
|
|
||
|
SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
tt = null;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt)
|
||
|
{
|
||
|
Widget Widget;
|
||
|
|
||
|
Widget = Widget.FromHandle(handle);
|
||
|
if (Widget != null && tt != null) {
|
||
|
tt.SetToolTip(Widget, tip);
|
||
|
tt.Active = true;
|
||
|
SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void SystrayRemove(IntPtr handle, ref ToolTip tt)
|
||
|
{
|
||
|
|
||
|
SetVisible (handle, false, false);
|
||
|
|
||
|
// The caller can now re-dock it later...
|
||
|
if (tt != null) {
|
||
|
tt.Dispose();
|
||
|
tt = null;
|
||
|
}
|
||
|
// Close any balloon window *we* fired.
|
||
|
ThemeEngine.Current.HideBalloonWindow (handle);
|
||
|
}
|
||
|
|
||
|
internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
|
||
|
{
|
||
|
ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
|
||
|
SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);
|
||
|
}
|
||
|
|
||
|
internal override bool Text(IntPtr handle, string text)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
lock (XlibLock) {
|
||
|
XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UTF8_STRING, 8,
|
||
|
PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
|
||
|
|
||
|
// XXX this has problems with UTF8.
|
||
|
// we need to either use the actual
|
||
|
// text if it's latin-1, or convert it
|
||
|
// to compound text if it's in a
|
||
|
// different charset.
|
||
|
XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal override bool TranslateMessage(ref MSG msg)
|
||
|
{
|
||
|
return Keyboard.TranslateMessage (ref msg);
|
||
|
}
|
||
|
|
||
|
internal override void UpdateWindow(IntPtr handle)
|
||
|
{
|
||
|
Hwnd hwnd;
|
||
|
|
||
|
hwnd = Hwnd.ObjectFromHandle(handle);
|
||
|
|
||
|
if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
|
||
|
hwnd.Queue.Paint.Remove(hwnd);
|
||
|
}
|
||
|
|
||
|
internal override void CreateOffscreenDrawable (IntPtr handle,
|
||
|
int width, int height,
|
||
|
out object offscreen_drawable)
|
||
|
{
|
||
|
IntPtr root_out;
|
||
|
int x_out, y_out, width_out, height_out, border_width_out, depth_out;
|
||
|
|
||
|
XGetGeometry (DisplayHandle, handle,
|
||
|
out root_out,
|
||
|
out x_out, out y_out,
|
||
|
out width_out, out height_out,
|
||
|
out border_width_out, out depth_out);
|
||
|
|
||
|
IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
|
||
|
|
||
|
offscreen_drawable = pixmap;
|
||
|
|
||
|
}
|
||
|
|
||
|
internal override void DestroyOffscreenDrawable (object offscreen_drawable)
|
||
|
{
|
||
|
XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
|
||
|
}
|
||
|
|
||
|
internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
|
||
|
{
|
||
|
return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
|
||
|
}
|
||
|
|
||
|
internal override void BlitFromOffscreen (IntPtr dest_handle,
|
||
|
Graphics dest_dc,
|
||
|
object offscreen_drawable,
|
||
|
Graphics offscreen_dc,
|
||
|
Rectangle r)
|
||
|
{
|
||
|
XGCValues gc_values;
|
||
|
IntPtr gc;
|
||
|
|
||
|
gc_values = new XGCValues();
|
||
|
|
||
|
gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
|
||
|
|
||
|
XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
|
||
|
gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
|
||
|
|
||
|
XFreeGC (DisplayHandle, gc);
|
||
|
}
|
||
|
|
||
|
#endregion // Public Static Methods
|
||
|
|
||
|
#region Events
|
||
|
internal override event EventHandler Idle;
|
||
|
#endregion // Events
|
||
|
|
||
|
|
||
|
#if TRACE && false
|
||
|
|
||
|
#region Xcursor imports
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
|
||
|
internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
|
||
|
internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
|
||
|
internal extern static void XcursorImagesDestroy (IntPtr images);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
|
||
|
internal extern static int XcursorGetDefaultSize (IntPtr display);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
|
||
|
internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
|
||
|
internal extern static IntPtr XcursorGetTheme (IntPtr display);
|
||
|
#endregion
|
||
|
#region X11 Imports
|
||
|
[DllImport ("libX11", EntryPoint="XOpenDisplay")]
|
||
|
internal extern static IntPtr XOpenDisplay(IntPtr display);
|
||
|
[DllImport ("libX11", EntryPoint="XCloseDisplay")]
|
||
|
internal extern static int XCloseDisplay(IntPtr display);
|
||
|
[DllImport ("libX11", EntryPoint="XSynchronize")]
|
||
|
internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreateWindow")]
|
||
|
internal extern static IntPtr _XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, UIntPtr valuemask, ref XSetWindowAttributes attributes);
|
||
|
internal static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, UIntPtr valuemask, ref XSetWindowAttributes attributes)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCreateWindow");
|
||
|
return _XCreateWindow(display, parent, x, y, width, height,
|
||
|
border_width, depth, xclass, visual, valuemask, ref attributes);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
|
||
|
internal extern static IntPtr _XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
|
||
|
internal static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCreateSimpleWindow");
|
||
|
return _XCreateSimpleWindow(display, parent, x, y, width, height, border_width, border, background);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XMapWindow")]
|
||
|
internal extern static int _XMapWindow(IntPtr display, IntPtr window);
|
||
|
internal static int XMapWindow(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XMapWindow");
|
||
|
return _XMapWindow(display, window);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XMapRaised")]
|
||
|
internal extern static int _XMapRaised(IntPtr display, IntPtr window);
|
||
|
internal static int XMapRaised(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XMapRaised");
|
||
|
return _XMapRaised(display, window);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XUnmapWindow")]
|
||
|
internal extern static int _XUnmapWindow(IntPtr display, IntPtr window);
|
||
|
internal static int XUnmapWindow(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XUnmapWindow");
|
||
|
return _XUnmapWindow(display, window);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XMapSubwindows")]
|
||
|
internal extern static int _XMapSubindows(IntPtr display, IntPtr window);
|
||
|
internal static int XMapSubindows(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XMapSubindows");
|
||
|
return _XMapSubindows(display, window);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
|
||
|
internal extern static int _XUnmapSubwindows(IntPtr display, IntPtr window);
|
||
|
internal static int XUnmapSubwindows(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XUnmapSubwindows");
|
||
|
return _XUnmapSubwindows(display, window);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XRootWindow")]
|
||
|
internal extern static IntPtr _XRootWindow(IntPtr display, int screen_number);
|
||
|
internal static IntPtr XRootWindow(IntPtr display, int screen_number)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XRootWindow");
|
||
|
return _XRootWindow(display, screen_number);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XNextEvent")]
|
||
|
internal extern static IntPtr _XNextEvent(IntPtr display, ref XEvent xevent);
|
||
|
internal static IntPtr XNextEvent(IntPtr display, ref XEvent xevent)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XNextEvent");
|
||
|
return _XNextEvent(display, ref xevent);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XConnectionNumber")]
|
||
|
internal extern static int _XConnectionNumber (IntPtr display);
|
||
|
internal static int XConnectionNumber (IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XConnectionNumber");
|
||
|
return _XConnectionNumber (display);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XPending")]
|
||
|
internal extern static int _XPending (IntPtr display);
|
||
|
internal static int XPending (IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XPending");
|
||
|
DebugHelper.DumpCallers (3);
|
||
|
return _XPending (display);
|
||
|
}
|
||
|
[DllImport ("libX11", EntryPoint="XSelectInput")]
|
||
|
internal extern static IntPtr _XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
|
||
|
internal static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSelectInput");
|
||
|
return _XSelectInput(display, window, mask);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDestroyWindow")]
|
||
|
internal extern static int _XDestroyWindow(IntPtr display, IntPtr window);
|
||
|
internal static int XDestroyWindow(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDestroyWindow 0x{0:x}", window.ToInt32());
|
||
|
return _XDestroyWindow(display, window);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XReparentWindow")]
|
||
|
internal extern static int _XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
|
||
|
internal static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XReparentWindow");
|
||
|
return _XReparentWindow(display, window, parent, x, y);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
|
||
|
extern static int _XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
|
||
|
static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height) {
|
||
|
DebugHelper.TraceWriteLine ("XMoveResizeWindow");
|
||
|
return _XMoveResizeWindow(display, window, x, y, width, height);
|
||
|
}
|
||
|
|
||
|
internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height)
|
||
|
{
|
||
|
int ret = XMoveResizeWindow (display, window, x, y, width, height);
|
||
|
Keyboard.MoveCurrentCaretPos ();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XResizeWindow")]
|
||
|
internal extern static int _XResizeWindow(IntPtr display, IntPtr window, int width, int height);
|
||
|
internal static int XResizeWindow(IntPtr display, IntPtr window, int width, int height)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XResizeWindow");
|
||
|
return _XResizeWindow(display, window, width, height);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
|
||
|
internal extern static int _XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
|
||
|
internal static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetWindowAttributes");
|
||
|
return _XGetWindowAttributes(display, window, ref attributes);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFlush")]
|
||
|
internal extern static int _XFlush(IntPtr display);
|
||
|
internal static int XFlush(IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFlush");
|
||
|
return _XFlush(display);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMName")]
|
||
|
internal extern static int _XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
|
||
|
internal static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetWMName");
|
||
|
return _XSetWMName(display, window, ref text_prop);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XStoreName")]
|
||
|
internal extern static int _XStoreName(IntPtr display, IntPtr window, string window_name);
|
||
|
internal static int XStoreName(IntPtr display, IntPtr window, string window_name)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XStoreName");
|
||
|
return _XStoreName(display, window, window_name);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFetchName")]
|
||
|
internal extern static int _XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
|
||
|
internal static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFetchName");
|
||
|
return _XFetchName(display, window, ref window_name);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSendEvent")]
|
||
|
internal extern static int _XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
|
||
|
internal static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSendEvent");
|
||
|
return _XSendEvent(display, window, propagate, event_mask, ref send_event);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryTree")]
|
||
|
internal extern static int _XQueryTree(IntPtr display, IntPtr window, out IntPtr root_return, out IntPtr parent_return, out IntPtr children_return, out int nchildren_return);
|
||
|
internal static int XQueryTree(IntPtr display, IntPtr window, out IntPtr root_return, out IntPtr parent_return, out IntPtr children_return, out int nchildren_return)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XQueryTree");
|
||
|
return _XQueryTree(display, window, out root_return, out parent_return, out children_return, out nchildren_return);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFree")]
|
||
|
internal extern static int _XFree(IntPtr data);
|
||
|
internal static int XFree(IntPtr data)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFree");
|
||
|
return _XFree(data);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XRaiseWindow")]
|
||
|
internal extern static int _XRaiseWindow(IntPtr display, IntPtr window);
|
||
|
internal static int XRaiseWindow(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XRaiseWindow");
|
||
|
return _XRaiseWindow(display, window);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XLowerWindow")]
|
||
|
internal extern static uint _XLowerWindow(IntPtr display, IntPtr window);
|
||
|
internal static uint XLowerWindow(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XLowerWindow");
|
||
|
return _XLowerWindow(display, window);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XConfigureWindow")]
|
||
|
internal extern static uint _XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
|
||
|
internal static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XConfigureWindow");
|
||
|
return _XConfigureWindow(display, window, value_mask, ref values);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XInternAtom")]
|
||
|
internal extern static IntPtr _XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
|
||
|
internal static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XInternAtom");
|
||
|
return _XInternAtom(display, atom_name, only_if_exists);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XInternAtoms")]
|
||
|
internal extern static int _XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
|
||
|
internal static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XInternAtoms");
|
||
|
return _XInternAtoms(display, atom_names, atom_count, only_if_exists, atoms);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMProtocols")]
|
||
|
internal extern static int _XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
|
||
|
internal static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetWMProtocols");
|
||
|
return _XSetWMProtocols(display, window, protocols, count);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGrabPointer")]
|
||
|
internal extern static int _XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, IntPtr timestamp);
|
||
|
internal static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, IntPtr timestamp)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGrabPointer");
|
||
|
return _XGrabPointer(display, window, owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, timestamp);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUngrabPointer")]
|
||
|
internal extern static int _XUngrabPointer(IntPtr display, IntPtr timestamp);
|
||
|
internal static int XUngrabPointer(IntPtr display, IntPtr timestamp)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XUngrabPointer");
|
||
|
return _XUngrabPointer(display, timestamp);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryPointer")]
|
||
|
internal extern static bool _XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);
|
||
|
internal static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XQueryPointer");
|
||
|
return _XQueryPointer(display, window, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
|
||
|
internal extern static bool _XTranslateCoordinates (IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, out int intdest_x_return, out int dest_y_return, out IntPtr child_return);
|
||
|
internal static bool XTranslateCoordinates (IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, out int intdest_x_return, out int dest_y_return, out IntPtr child_return)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XTranslateCoordinates");
|
||
|
return _XTranslateCoordinates (display, src_w, dest_w, src_x, src_y, out intdest_x_return, out dest_y_return, out child_return);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool _XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth);
|
||
|
internal static bool XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetGeometry");
|
||
|
return _XGetGeometry(display, window, out root, out x, out y, out width, out height, out border_width, out depth);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool _XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, out int width, out int height, IntPtr border_width, IntPtr depth);
|
||
|
internal static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, out int width, out int height, IntPtr border_width, IntPtr depth)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetGeometry");
|
||
|
return _XGetGeometry(display, window, root, out x, out y, out width, out height, border_width, depth);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool _XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, IntPtr width, IntPtr height, IntPtr border_width, IntPtr depth);
|
||
|
internal static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, IntPtr width, IntPtr height, IntPtr border_width, IntPtr depth)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetGeometry");
|
||
|
return _XGetGeometry(display, window, root, out x, out y, width, height, border_width, depth);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool _XGetGeometry(IntPtr display, IntPtr window, IntPtr root, IntPtr x, IntPtr y, out int width, out int height, IntPtr border_width, IntPtr depth);
|
||
|
internal static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, IntPtr x, IntPtr y, out int width, out int height, IntPtr border_width, IntPtr depth)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetGeometry");
|
||
|
return _XGetGeometry(display, window, root, x, y, out width, out height, border_width, depth);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XWarpPointer")]
|
||
|
internal extern static uint _XWarpPointer(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, uint src_width, uint src_height, int dest_x, int dest_y);
|
||
|
internal static uint XWarpPointer(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, uint src_width, uint src_height, int dest_x, int dest_y)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XWarpPointer");
|
||
|
return _XWarpPointer(display, src_w, dest_w, src_x, src_y, src_width, src_height, dest_x, dest_y);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XClearWindow")]
|
||
|
internal extern static int _XClearWindow(IntPtr display, IntPtr window);
|
||
|
internal static int XClearWindow(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XClearWindow");
|
||
|
return _XClearWindow(display, window);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XClearArea")]
|
||
|
internal extern static int _XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
|
||
|
internal static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XClearArea");
|
||
|
return _XClearArea(display, window, x, y, width, height, exposures);
|
||
|
}
|
||
|
|
||
|
// Colormaps
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
|
||
|
internal extern static IntPtr _XDefaultScreenOfDisplay(IntPtr display);
|
||
|
internal static IntPtr XDefaultScreenOfDisplay(IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDefaultScreenOfDisplay");
|
||
|
return _XDefaultScreenOfDisplay(display);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
|
||
|
internal extern static int _XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
|
||
|
internal static int XDefaultScreenOfDisplay(IntPtr display, IntPtr Screen)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDefaultScreenOfDisplay");
|
||
|
return _XScreenNumberOfScreen(display, Screen);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultVisual")]
|
||
|
internal extern static IntPtr _XDefaultVisual(IntPtr display, int screen_number);
|
||
|
internal static IntPtr XDefaultScreenOfDisplay(IntPtr display, int screen_number)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDefaultScreenOfDisplay");
|
||
|
return _XDefaultVisual(display, screen_number);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultDepth")]
|
||
|
internal extern static uint _XDefaultDepth(IntPtr display, int screen_number);
|
||
|
internal static uint XDefaultDepth(IntPtr display, int screen_number)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDefaultDepth");
|
||
|
return _XDefaultDepth(display, screen_number);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultScreen")]
|
||
|
internal extern static int _XDefaultScreen(IntPtr display);
|
||
|
internal static int XDefaultScreen(IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDefaultScreen");
|
||
|
return _XDefaultScreen(display);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultColormap")]
|
||
|
internal extern static IntPtr _XDefaultColormap(IntPtr display, int screen_number);
|
||
|
internal static IntPtr XDefaultColormap(IntPtr display, int screen_number)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDefaultColormap");
|
||
|
return _XDefaultColormap(display, screen_number);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XLookupColor")]
|
||
|
internal extern static int _XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
|
||
|
internal static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XLookupColor");
|
||
|
return _XLookupColor(display, Colormap, Coloranem, ref exact_def_color, ref screen_def_color);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XAllocColor")]
|
||
|
internal extern static int _XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
|
||
|
internal static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XAllocColor");
|
||
|
return _XAllocColor(display, Colormap, ref colorcell_def);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetTransientForHint")]
|
||
|
internal extern static int _XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
|
||
|
internal static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetTransientForHint");
|
||
|
return _XSetTransientForHint(display, window, prop_window);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, ref data, nelements);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, ref value, nelements);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, ref value, nelements);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, data, nelements);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, data, nelements);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, data, nelements);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, atoms, nelements);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
|
||
|
internal extern static int _XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
|
||
|
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeProperty");
|
||
|
return _XChangeProperty(display, window, property, type, format, mode, text, text_length);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDeleteProperty")]
|
||
|
internal extern static int _XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
|
||
|
internal static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDeleteProperty");
|
||
|
return _XDeleteProperty(display, window, property);
|
||
|
}
|
||
|
|
||
|
// Drawing
|
||
|
[DllImport ("libX11", EntryPoint="XCreateGC")]
|
||
|
internal extern static IntPtr _XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
|
||
|
internal static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCreateGC");
|
||
|
return _XCreateGC(display, window, valuemask, ref values);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFreeGC")]
|
||
|
internal extern static int _XFreeGC(IntPtr display, IntPtr gc);
|
||
|
internal static int XFreeGC(IntPtr display, IntPtr gc)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFreeGC");
|
||
|
return _XFreeGC(display, gc);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetFunction")]
|
||
|
internal extern static int _XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
|
||
|
internal static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetFunction");
|
||
|
return _XSetFunction(display, gc, function);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetLineAttributes")]
|
||
|
internal extern static int _XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
|
||
|
internal static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetLineAttributes");
|
||
|
return _XSetLineAttributes(display, gc, line_width, line_style, cap_style, join_style);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDrawLine")]
|
||
|
internal extern static int _XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
|
||
|
internal static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDrawLine");
|
||
|
return _XDrawLine(display, drawable, gc, x1, y1, x2, y2);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDrawRectangle")]
|
||
|
internal extern static int _XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
|
||
|
internal static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDrawRectangle");
|
||
|
return _XDrawRectangle(display, drawable, gc, x1, y1, width, height);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFillRectangle")]
|
||
|
internal extern static int _XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
|
||
|
internal static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFillRectangle");
|
||
|
return _XFillRectangle(display, drawable, gc, x1, y1, width, height);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWindowBackground")]
|
||
|
internal extern static int _XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
|
||
|
internal static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetWindowBackground");
|
||
|
return _XSetWindowBackground(display, window, background);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCopyArea")]
|
||
|
internal extern static int _XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y);
|
||
|
internal static int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCopyArea");
|
||
|
return _XCopyArea(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetWindowProperty")]
|
||
|
internal extern static int _XGetWindowProperty(IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, out int actual_format, out IntPtr nitems, out IntPtr bytes_after, ref IntPtr prop);
|
||
|
internal static int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, out int actual_format, out IntPtr nitems, out IntPtr bytes_after, ref IntPtr prop)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetWindowProperty");
|
||
|
return _XGetWindowProperty(display, window, atom, long_offset, long_length, delete, req_type, out actual_type, out actual_format, out nitems, out bytes_after, ref prop);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetInputFocus")]
|
||
|
internal extern static int _XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
|
||
|
internal static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetInputFocus");
|
||
|
return _XSetInputFocus(display, window, revert_to, time);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XIconifyWindow")]
|
||
|
internal extern static int _XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
|
||
|
internal static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XIconifyWindow");
|
||
|
return _XIconifyWindow(display, window, screen_number);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefineCursor")]
|
||
|
internal extern static int _XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
|
||
|
internal static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XDefineCursor");
|
||
|
return _XDefineCursor(display, window, cursor);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUndefineCursor")]
|
||
|
internal extern static int _XUndefineCursor(IntPtr display, IntPtr window);
|
||
|
internal static int XUndefineCursor(IntPtr display, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XUndefineCursor");
|
||
|
return _XUndefineCursor(display, window);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFreeCursor")]
|
||
|
internal extern static int _XFreeCursor(IntPtr display, IntPtr cursor);
|
||
|
internal static int XFreeCursor(IntPtr display, IntPtr cursor)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFreeCursor");
|
||
|
return _XFreeCursor(display, cursor);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreateFontCursor")]
|
||
|
internal extern static IntPtr _XCreateFontCursor(IntPtr display, CursorFontShape shape);
|
||
|
internal static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCreateFontCursor");
|
||
|
return _XCreateFontCursor(display, shape);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
|
||
|
internal extern static IntPtr _XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground_color, ref XColor background_color, int x_hot, int y_hot);
|
||
|
internal static IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground_color, ref XColor background_color, int x_hot, int y_hot)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCreatePixmapCursor");
|
||
|
return _XCreatePixmapCursor(display, source, mask, ref foreground_color, ref background_color, x_hot, y_hot);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
|
||
|
internal extern static IntPtr _XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
|
||
|
internal static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCreatePixmapFromBitmapData");
|
||
|
return _XCreatePixmapFromBitmapData(display, drawable, data, width, height, fg, bg, depth);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreatePixmap")]
|
||
|
internal extern static IntPtr _XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
|
||
|
internal static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XCreatePixmap");
|
||
|
return _XCreatePixmap(display, d, width, height, depth);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFreePixmap")]
|
||
|
internal extern static IntPtr _XFreePixmap(IntPtr display, IntPtr pixmap);
|
||
|
internal static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFreePixmap");
|
||
|
return _XFreePixmap(display, pixmap);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryBestCursor")]
|
||
|
internal extern static int _XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
|
||
|
internal static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XQueryBestCursor");
|
||
|
return _XQueryBestCursor(display, drawable, width, height, out best_width, out best_height);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryExtension")]
|
||
|
internal extern static int _XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
|
||
|
internal static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XQueryExtension");
|
||
|
return _XQueryExtension(display, extension_name, ref major, ref first_event, ref first_error);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XWhitePixel")]
|
||
|
internal extern static IntPtr _XWhitePixel(IntPtr display, int screen_no);
|
||
|
internal static IntPtr XWhitePixel(IntPtr display, int screen_no)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XWhitePixel");
|
||
|
return _XWhitePixel(display, screen_no);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XBlackPixel")]
|
||
|
internal extern static IntPtr _XBlackPixel(IntPtr display, int screen_no);
|
||
|
internal static IntPtr XBlackPixel(IntPtr display, int screen_no)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XBlackPixel");
|
||
|
return _XBlackPixel(display, screen_no);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGrabServer")]
|
||
|
internal extern static void _XGrabServer(IntPtr display);
|
||
|
internal static void XGrabServer(IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGrabServer");
|
||
|
_XGrabServer(display);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUngrabServer")]
|
||
|
internal extern static void _XUngrabServer(IntPtr display);
|
||
|
internal static void XUngrabServer(IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XUngrabServer");
|
||
|
_XUngrabServer(display);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
|
||
|
internal extern static void _XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
|
||
|
internal static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetWMNormalHints");
|
||
|
_XGetWMNormalHints(display, window, ref hints, out supplied_return);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
|
||
|
internal extern static void _XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
|
||
|
internal static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetWMNormalHints");
|
||
|
_XSetWMNormalHints(display, window, ref hints);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetZoomHints")]
|
||
|
internal extern static void _XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
|
||
|
internal static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetZoomHints");
|
||
|
_XSetZoomHints(display, window, ref hints);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMHints")]
|
||
|
internal extern static void _XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
|
||
|
internal static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetWMHints");
|
||
|
_XSetWMHints(display, window, ref wmhints);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetIconSizes")]
|
||
|
internal extern static int _XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
|
||
|
internal static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetIconSizes");
|
||
|
return _XGetIconSizes(display, window, out size_list, out count);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetErrorHandler")]
|
||
|
internal extern static IntPtr _XSetErrorHandler(XErrorHandler error_handler);
|
||
|
internal static IntPtr XSetErrorHandler(XErrorHandler error_handler)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetErrorHandler");
|
||
|
return _XSetErrorHandler(error_handler);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetErrorText")]
|
||
|
internal extern static IntPtr _XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
|
||
|
internal static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetErrorText");
|
||
|
return _XGetErrorText(display, code, buffer, length);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XInitThreads")]
|
||
|
internal extern static int _XInitThreads();
|
||
|
internal static int XInitThreads()
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XInitThreads");
|
||
|
return _XInitThreads();
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XConvertSelection")]
|
||
|
internal extern static int _XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
|
||
|
internal static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XConvertSelection");
|
||
|
return _XConvertSelection(display, selection, target, property, requestor, time);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
|
||
|
internal extern static IntPtr _XGetSelectionOwner(IntPtr display, IntPtr selection);
|
||
|
internal static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XGetSelectionOwner");
|
||
|
return _XGetSelectionOwner(display, selection);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
|
||
|
internal extern static int _XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
|
||
|
internal static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetSelectionOwner");
|
||
|
return _XSetSelectionOwner(display, selection, owner, time);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetPlaneMask")]
|
||
|
internal extern static int _XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
|
||
|
internal static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetPlaneMask");
|
||
|
return _XSetPlaneMask(display, gc, mask);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetForeground")]
|
||
|
internal extern static int _XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
|
||
|
internal static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetForeground");
|
||
|
return _XSetForeground(display, gc, foreground);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetBackground")]
|
||
|
internal extern static int _XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
|
||
|
internal static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XSetBackground");
|
||
|
return _XSetBackground(display, gc, background);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XBell")]
|
||
|
internal extern static int _XBell(IntPtr display, int percent);
|
||
|
internal static int XBell(IntPtr display, int percent)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XBell");
|
||
|
return _XBell(display, percent);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
|
||
|
internal extern static int _XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
|
||
|
internal static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XChangeActivePointerGrab");
|
||
|
return _XChangeActivePointerGrab (display, event_mask, cursor, time);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFilterEvent")]
|
||
|
internal extern static bool _XFilterEvent(ref XEvent xevent, IntPtr window);
|
||
|
internal static bool XFilterEvent(ref XEvent xevent, IntPtr window)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XFilterEvent");
|
||
|
return _XFilterEvent(ref xevent, window);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XkbSetDetectableAutoRepeat")]
|
||
|
internal extern static void _XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
|
||
|
internal static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XkbSetDetectableAutoRepeat");
|
||
|
_XkbSetDetectableAutoRepeat (display, detectable, supported);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XPeekEvent")]
|
||
|
internal extern static void _XPeekEvent (IntPtr display, ref XEvent xevent);
|
||
|
internal static void XPeekEvent (IntPtr display, ref XEvent xevent)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XPeekEvent");
|
||
|
_XPeekEvent (display, ref xevent);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XIfEvent")]
|
||
|
internal extern static void _XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg);
|
||
|
internal static void XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XIfEvent");
|
||
|
_XIfEvent (display, ref xevent, event_predicate, arg);
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#region Xinerama imports
|
||
|
[DllImport ("libXinerama", EntryPoint="XineramaQueryScreens")]
|
||
|
extern static IntPtr _XineramaQueryScreens (IntPtr display, out int number);
|
||
|
internal static IntPtr XineramaQueryScreens (IntPtr display, out int number)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XineramaQueryScreens");
|
||
|
return _XineramaQueryScreens (display, out number);
|
||
|
}
|
||
|
|
||
|
[DllImport ("libXinerama", EntryPoint="XineramaIsActive")]
|
||
|
extern static bool _XineramaIsActive (IntPtr display);
|
||
|
static bool XineramaNotInstalled;
|
||
|
|
||
|
internal static bool XineramaIsActive (IntPtr display)
|
||
|
{
|
||
|
DebugHelper.TraceWriteLine ("XineramaIsActive");
|
||
|
|
||
|
if (XineramaNotInstalled)
|
||
|
return false;
|
||
|
try {
|
||
|
return _XineramaIsActive (display);
|
||
|
} catch (DllNotFoundException) {
|
||
|
// Xinerama isn't installed
|
||
|
XineramaNotInstalled = true;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#else //no TRACE defined
|
||
|
|
||
|
#region Xcursor imports
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
|
||
|
internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
|
||
|
internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
|
||
|
internal extern static void XcursorImagesDestroy (IntPtr images);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
|
||
|
internal extern static int XcursorGetDefaultSize (IntPtr display);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
|
||
|
internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
|
||
|
|
||
|
[DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
|
||
|
internal extern static IntPtr XcursorGetTheme (IntPtr display);
|
||
|
#endregion
|
||
|
#region X11 Imports
|
||
|
[DllImport ("libX11", EntryPoint="XOpenDisplay")]
|
||
|
internal extern static IntPtr XOpenDisplay(IntPtr display);
|
||
|
[DllImport ("libX11", EntryPoint="XCloseDisplay")]
|
||
|
internal extern static int XCloseDisplay(IntPtr display);
|
||
|
[DllImport ("libX11", EntryPoint="XSynchronize")]
|
||
|
internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreateWindow")]
|
||
|
internal extern static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, UIntPtr valuemask, ref XSetWindowAttributes attributes);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
|
||
|
internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XMapWindow")]
|
||
|
internal extern static int XMapWindow(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XMapRaised")]
|
||
|
internal extern static int XMapRaised(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUnmapWindow")]
|
||
|
internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XMapSubwindows")]
|
||
|
internal extern static int XMapSubindows(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
|
||
|
internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XRootWindow")]
|
||
|
internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XNextEvent")]
|
||
|
internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XConnectionNumber")]
|
||
|
internal extern static int XConnectionNumber (IntPtr display);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XPending")]
|
||
|
internal extern static int XPending (IntPtr display);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSelectInput")]
|
||
|
internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDestroyWindow")]
|
||
|
internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XReparentWindow")]
|
||
|
internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
|
||
|
extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
|
||
|
internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height)
|
||
|
{
|
||
|
int ret = XMoveResizeWindow (display, window, x, y, width, height);
|
||
|
Keyboard.MoveCurrentCaretPos ();
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XResizeWindow")]
|
||
|
internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
|
||
|
internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFlush")]
|
||
|
internal extern static int XFlush(IntPtr display);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMName")]
|
||
|
internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XStoreName")]
|
||
|
internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFetchName")]
|
||
|
internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSendEvent")]
|
||
|
internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryTree")]
|
||
|
internal extern static int XQueryTree(IntPtr display, IntPtr window, out IntPtr root_return, out IntPtr parent_return, out IntPtr children_return, out int nchildren_return);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFree")]
|
||
|
internal extern static int XFree(IntPtr data);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XRaiseWindow")]
|
||
|
internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XLowerWindow")]
|
||
|
internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XConfigureWindow")]
|
||
|
internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XInternAtom")]
|
||
|
internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XInternAtoms")]
|
||
|
internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMProtocols")]
|
||
|
internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGrabPointer")]
|
||
|
internal extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, IntPtr timestamp);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUngrabPointer")]
|
||
|
internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryPointer")]
|
||
|
internal extern static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
|
||
|
internal extern static bool XTranslateCoordinates (IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, out int intdest_x_return, out int dest_y_return, out IntPtr child_return);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, out int width, out int height, IntPtr border_width, IntPtr depth);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, IntPtr width, IntPtr height, IntPtr border_width, IntPtr depth);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetGeometry")]
|
||
|
internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, IntPtr x, IntPtr y, out int width, out int height, IntPtr border_width, IntPtr depth);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XWarpPointer")]
|
||
|
internal extern static uint XWarpPointer(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, uint src_width, uint src_height, int dest_x, int dest_y);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XClearWindow")]
|
||
|
internal extern static int XClearWindow(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XClearArea")]
|
||
|
internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
|
||
|
|
||
|
// Colormaps
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
|
||
|
internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
|
||
|
internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultVisual")]
|
||
|
internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultDepth")]
|
||
|
internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultScreen")]
|
||
|
internal extern static int XDefaultScreen(IntPtr display);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefaultColormap")]
|
||
|
internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XLookupColor")]
|
||
|
internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XAllocColor")]
|
||
|
internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetTransientForHint")]
|
||
|
internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty")]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
|
||
|
internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDeleteProperty")]
|
||
|
internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
|
||
|
|
||
|
// Drawing
|
||
|
[DllImport ("libX11", EntryPoint="XCreateGC")]
|
||
|
internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFreeGC")]
|
||
|
internal extern static int XFreeGC(IntPtr display, IntPtr gc);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetFunction")]
|
||
|
internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetLineAttributes")]
|
||
|
internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDrawLine")]
|
||
|
internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDrawRectangle")]
|
||
|
internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFillRectangle")]
|
||
|
internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWindowBackground")]
|
||
|
internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCopyArea")]
|
||
|
internal extern static int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetWindowProperty")]
|
||
|
internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, out int actual_format, out IntPtr nitems, out IntPtr bytes_after, ref IntPtr prop);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetInputFocus")]
|
||
|
internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XIconifyWindow")]
|
||
|
internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XDefineCursor")]
|
||
|
internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUndefineCursor")]
|
||
|
internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFreeCursor")]
|
||
|
internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreateFontCursor")]
|
||
|
internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
|
||
|
internal extern static IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground_color, ref XColor background_color, int x_hot, int y_hot);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
|
||
|
internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XCreatePixmap")]
|
||
|
internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFreePixmap")]
|
||
|
internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryBestCursor")]
|
||
|
internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XQueryExtension")]
|
||
|
internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XWhitePixel")]
|
||
|
internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XBlackPixel")]
|
||
|
internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGrabServer")]
|
||
|
internal extern static void XGrabServer(IntPtr display);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XUngrabServer")]
|
||
|
internal extern static void XUngrabServer(IntPtr display);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
|
||
|
internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
|
||
|
internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetZoomHints")]
|
||
|
internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetWMHints")]
|
||
|
internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetIconSizes")]
|
||
|
internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetErrorHandler")]
|
||
|
internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetErrorText")]
|
||
|
internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XInitThreads")]
|
||
|
internal extern static int XInitThreads();
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XConvertSelection")]
|
||
|
internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
|
||
|
internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
|
||
|
internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetPlaneMask")]
|
||
|
internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetForeground")]
|
||
|
internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XSetBackground")]
|
||
|
internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XBell")]
|
||
|
internal extern static int XBell(IntPtr display, int percent);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
|
||
|
internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XFilterEvent")]
|
||
|
internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XkbSetDetectableAutoRepeat")]
|
||
|
internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XPeekEvent")]
|
||
|
internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XIfEvent")]
|
||
|
internal extern static void XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg);
|
||
|
|
||
|
[DllImport ("libX11", EntryPoint="XGetInputFocus")]
|
||
|
internal extern static void XGetInputFocus (IntPtr display, out IntPtr focus, out IntPtr revert_to);
|
||
|
#endregion
|
||
|
#region Gtk/Gdk imports
|
||
|
[DllImport("libgdk-x11-2.0")]
|
||
|
internal extern static IntPtr gdk_atom_intern (string atomName, bool onlyIfExists);
|
||
|
|
||
|
[DllImport("libgtk-x11-2.0")]
|
||
|
internal extern static IntPtr gtk_clipboard_get (IntPtr atom);
|
||
|
|
||
|
[DllImport("libgtk-x11-2.0")]
|
||
|
internal extern static void gtk_clipboard_store (IntPtr clipboard);
|
||
|
|
||
|
[DllImport("libgtk-x11-2.0")]
|
||
|
internal extern static void gtk_clipboard_set_text (IntPtr clipboard, string text, int len);
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
#region Xinerama imports
|
||
|
[DllImport ("libXinerama")]
|
||
|
internal extern static IntPtr XineramaQueryScreens (IntPtr display, out int number);
|
||
|
|
||
|
[DllImport ("libXinerama", EntryPoint = "XineramaIsActive")]
|
||
|
extern static bool _XineramaIsActive (IntPtr display);
|
||
|
static bool XineramaNotInstalled;
|
||
|
|
||
|
internal static bool XineramaIsActive (IntPtr display)
|
||
|
{
|
||
|
if (XineramaNotInstalled)
|
||
|
return false;
|
||
|
try {
|
||
|
return _XineramaIsActive (display);
|
||
|
} catch (DllNotFoundException) {
|
||
|
// Xinerama isn't installed
|
||
|
XineramaNotInstalled = true;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
}
|