mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-24 18:13:15 -05:00
hopefully fix clipboard issues on linux
This commit is contained in:
parent
b060fc78ec
commit
40532a439f
4 changed files with 484 additions and 391 deletions
|
@ -410,7 +410,7 @@ namespace ClassicalSharp.Gui.Widgets {
|
|||
if (key == Key.V && Text.Length < maxChars) {
|
||||
string text = null;
|
||||
try {
|
||||
text = game.window.ClipboardText.Trim(trimChars);
|
||||
text = game.window.GetClipboardText().Trim(trimChars);
|
||||
} catch (Exception ex) {
|
||||
ErrorHandler.LogError("Paste from clipboard", ex);
|
||||
const string warning = "&cError while trying to paste from clipboard.";
|
||||
|
@ -424,7 +424,7 @@ namespace ClassicalSharp.Gui.Widgets {
|
|||
} else if (key == Key.C) {
|
||||
if (Text.Empty) return true;
|
||||
try {
|
||||
game.window.ClipboardText = Text.ToString();
|
||||
game.window.SetClipboardText(Text.ToString());
|
||||
} catch (Exception ex) {
|
||||
ErrorHandler.LogError("Copy to clipboard", ex);
|
||||
const string warning = "&cError while trying to copy to clipboard.";
|
||||
|
|
|
@ -53,21 +53,5 @@ namespace ClassicalSharp {
|
|||
ErrorHandler.LogError("DesktopWindow.LoadIcon()", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: retry when clipboard returns null.
|
||||
public string ClipboardText {
|
||||
get {
|
||||
if (!OpenTK.Configuration.RunningOnLinux)
|
||||
return GetClipboardText();
|
||||
else
|
||||
return Clipboard.GetText();
|
||||
}
|
||||
set {
|
||||
if (!OpenTK.Configuration.RunningOnLinux)
|
||||
SetClipboardText(value);
|
||||
else
|
||||
Clipboard.SetText(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,365 +1,377 @@
|
|||
#region --- License ---
|
||||
/* Licensed under the MIT/X11 license.
|
||||
* Copyright (c) 2006-2008 the OpenTK Team.
|
||||
* This notice may not be removed from any source distribution.
|
||||
* See license.txt for licensing detailed licensing details.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using Window = System.IntPtr;
|
||||
using KeySym = System.IntPtr;
|
||||
using Display = System.IntPtr;
|
||||
using Bool = System.Boolean;
|
||||
using Status = System.Int32;
|
||||
using Drawable = System.IntPtr;
|
||||
using Time = System.IntPtr;
|
||||
// Randr and Xrandr
|
||||
using XRRScreenConfiguration = System.IntPtr; // opaque datatype
|
||||
using KeyCode = System.Byte; // Or maybe ushort?
|
||||
|
||||
namespace OpenTK.Platform.X11 {
|
||||
|
||||
public static class API {
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XOpenDisplay(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XCloseDisplay(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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, IntPtr valuemask, ref XSetWindowAttributes attributes);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XMapWindow(IntPtr display, IntPtr window);
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XUnmapWindow(IntPtr display, IntPtr window);
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XRootWindow(IntPtr display, int screen_number);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static Bool XCheckWindowEvent(Display display, Window w, EventMask event_mask, ref XEvent event_return);
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static Bool XCheckTypedWindowEvent(Display display, Window w, XEventName event_type, ref XEvent event_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDestroyWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XMoveWindow(IntPtr display, IntPtr w, int x, int y);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFlush(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
|
||||
|
||||
public static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event) {
|
||||
return XSendEvent(display, window, propagate, new IntPtr((int)event_mask), ref send_event);
|
||||
}
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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"), SuppressUnmanagedCodeSecurity]
|
||||
public 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"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFree(IntPtr data);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XRaiseWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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);
|
||||
|
||||
// Colormaps
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDefaultDepth(IntPtr display, int screen_number);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDefaultScreen(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XUndefineCursor(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFreeCursor(IntPtr display, IntPtr cursor);
|
||||
|
||||
// Drawing
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, XGCValues[] values);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFreeGC(IntPtr display, IntPtr gc);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foregroundCol, ref XColor backgroundCol, int x_hot, int y_hot);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XGetWMHints(Display display, Window w); // returns XWMHints*
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XSetWMHints(Display display, Window w, ref XWMHints wmhints);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XAllocWMHints();
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static bool XkbSetDetectableAutoRepeat(IntPtr display, bool detectable, out bool supported);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Status XGetTransientForHint(Display display, Window w, out Window prop_window_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XSync(Display display, bool discard);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XDefaultRootWindow(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XBitmapBitOrder(Display display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XCreateImage(Display display, IntPtr visual,
|
||||
uint depth, ImageFormat format, int offset, IntPtr data, int width, int height,
|
||||
int bitmap_pad, int bytes_per_line);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XPutImage(Display display, IntPtr drawable,
|
||||
IntPtr gc, IntPtr image, int src_x, int src_y, int dest_x, int dest_y, int width, int height);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XLookupString(ref XKeyEvent event_struct, [Out] byte[] buffer_return,
|
||||
int bytes_buffer, [Out] KeySym[] keysym_return, IntPtr status_in_out);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XRefreshKeyboardMapping(ref XMappingEvent event_map);
|
||||
|
||||
static readonly IntPtr CopyFromParent = IntPtr.Zero;
|
||||
|
||||
public static void SendNetWMMessage(X11WindowInfo window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)
|
||||
{
|
||||
XEvent xev = new XEvent();
|
||||
xev.ClientMessageEvent.type = XEventName.ClientMessage;
|
||||
xev.ClientMessageEvent.send_event = true;
|
||||
xev.ClientMessageEvent.window = window.WindowHandle;
|
||||
xev.ClientMessageEvent.message_type = message_type;
|
||||
xev.ClientMessageEvent.format = 32;
|
||||
xev.ClientMessageEvent.ptr1 = l0;
|
||||
xev.ClientMessageEvent.ptr2 = l1;
|
||||
xev.ClientMessageEvent.ptr3 = l2;
|
||||
|
||||
XSendEvent(window.Display, window.RootWindow, false,
|
||||
EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);
|
||||
}
|
||||
|
||||
public static IntPtr CreatePixmapFromImage(Display display, System.Drawing.Bitmap image)
|
||||
{
|
||||
int width = image.Width, height = image.Height;
|
||||
|
||||
System.Drawing.Imaging.BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
|
||||
System.Drawing.Imaging.ImageLockMode.ReadOnly,
|
||||
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
|
||||
IntPtr ximage = XCreateImage(display, CopyFromParent, 24, ImageFormat.ZPixmap,
|
||||
0, data.Scan0, width, height, 32, 0);
|
||||
IntPtr pixmap = XCreatePixmap(display, XDefaultRootWindow(display),
|
||||
width, height, 24);
|
||||
IntPtr gc = XCreateGC(display, pixmap, IntPtr.Zero, null);
|
||||
|
||||
XPutImage(display, pixmap, gc, ximage, 0, 0, 0, 0, width, height);
|
||||
|
||||
XFreeGC(display, gc);
|
||||
image.UnlockBits(data);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
public static IntPtr CreateMaskFromImage(Display display, System.Drawing.Bitmap image)
|
||||
{
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = (width + 7) >> 3;
|
||||
byte[] mask = new byte[stride * height];
|
||||
bool msbfirst = (XBitmapBitOrder(display) == 1); // 1 = MSBFirst
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
byte bit = (byte) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7)));
|
||||
int offset = y * stride + (x >> 3);
|
||||
|
||||
if (image.GetPixel(x, y).A >= 128)
|
||||
mask[offset] |= bit;
|
||||
}
|
||||
}
|
||||
|
||||
return XCreatePixmapFromBitmapData(display, XDefaultRootWindow(display),
|
||||
mask, width, height, new IntPtr(1), IntPtr.Zero, 1);
|
||||
}
|
||||
|
||||
const string XrandrLibrary = "libXrandr.so.2";
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern XRRScreenConfiguration XRRGetScreenInfo(Display dpy, Drawable draw);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern void XRRFreeScreenConfigInfo(XRRScreenConfiguration config);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern Status XRRSetScreenConfig(Display dpy, XRRScreenConfiguration config,
|
||||
Drawable draw, int size_index, ref ushort rotation, Time timestamp);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern Status XRRSetScreenConfigAndRate(Display dpy, XRRScreenConfiguration config,
|
||||
Drawable draw, int size_index, ushort rotation, short rate, Time timestamp);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern ushort XRRConfigCurrentConfiguration(XRRScreenConfiguration config, out ushort rotation);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern short XRRConfigCurrentRate(XRRScreenConfiguration config);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern int XRRRootToScreen(Display dpy, Window root);
|
||||
|
||||
// the following are always safe to call, even if RandR is not implemented on a screen
|
||||
[DllImport(XrandrLibrary)]
|
||||
unsafe static extern XRRScreenSize* XRRSizes(Display dpy, int screen, int* nsizes);
|
||||
|
||||
public unsafe static XRRScreenSize[] XRRSizes(Display dpy, int screen) {
|
||||
int count;
|
||||
XRRScreenSize* data = XRRSizes(dpy, screen, &count);
|
||||
if (count == 0) return null;
|
||||
|
||||
XRRScreenSize[] sizes = new XRRScreenSize[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
sizes[i] = *data++;
|
||||
return sizes;
|
||||
}
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
unsafe static extern short* XRRRates(Display dpy, int screen, int size_index, int* nrates);
|
||||
|
||||
public unsafe static short[] XRRRates(Display dpy, int screen, int size_index) {
|
||||
int count;
|
||||
short* data = XRRRates(dpy, screen, size_index, &count);
|
||||
if (count == 0) return null;
|
||||
|
||||
short[] rates = new short[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
rates[i] = *data++;
|
||||
return rates;
|
||||
}
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern Time XRRTimes(Display dpy, int screen, out Time config_timestamp);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XScreenCount(Display display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
unsafe static extern int* XListDepths(Display display, int screen_number, int* count_return);
|
||||
|
||||
public unsafe static int[] XListDepths(Display display, int screen_number) {
|
||||
int count;
|
||||
int* data = XListDepths(display, screen_number, &count);
|
||||
if (count == 0) return null;
|
||||
|
||||
int[] depths = new int[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
depths[i] = *data++;
|
||||
return depths;
|
||||
}
|
||||
|
||||
public static Display DefaultDisplay;
|
||||
internal static int ScreenCount;
|
||||
|
||||
static API() {
|
||||
DefaultDisplay = API.XOpenDisplay(IntPtr.Zero);
|
||||
if (DefaultDisplay == IntPtr.Zero)
|
||||
throw new PlatformException("Could not establish connection to the X-Server.");
|
||||
|
||||
ScreenCount = API.XScreenCount(DefaultDisplay);
|
||||
Debug.Print("Display connection: {0}, Screen count: {1}", DefaultDisplay, ScreenCount);
|
||||
|
||||
//AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
|
||||
}
|
||||
|
||||
static void CurrentDomain_ProcessExit(object sender, EventArgs e) {
|
||||
if (DefaultDisplay != IntPtr.Zero) {
|
||||
API.XCloseDisplay(DefaultDisplay);
|
||||
DefaultDisplay = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern KeySym XGetKeyboardMapping(Display display, KeyCode first_keycode, int keycode_count,
|
||||
ref int keysyms_per_keycode_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XDisplayKeycodes(Display display, ref int min_keycodes_return, ref int max_keycodes_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern KeySym XLookupKeysym(ref XKeyEvent key_event, int index);
|
||||
}
|
||||
}
|
||||
#region --- License ---
|
||||
/* Licensed under the MIT/X11 license.
|
||||
* Copyright (c) 2006-2008 the OpenTK Team.
|
||||
* This notice may not be removed from any source distribution.
|
||||
* See license.txt for licensing detailed licensing details.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using Window = System.IntPtr;
|
||||
using KeySym = System.IntPtr;
|
||||
using Display = System.IntPtr;
|
||||
using Bool = System.Boolean;
|
||||
using Status = System.Int32;
|
||||
using Drawable = System.IntPtr;
|
||||
using Time = System.IntPtr;
|
||||
// Randr and Xrandr
|
||||
using XRRScreenConfiguration = System.IntPtr; // opaque datatype
|
||||
using KeyCode = System.Byte; // Or maybe ushort?
|
||||
|
||||
namespace OpenTK.Platform.X11 {
|
||||
|
||||
public static class API {
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XOpenDisplay(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XCloseDisplay(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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, IntPtr valuemask, ref XSetWindowAttributes attributes);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XMapWindow(IntPtr display, IntPtr window);
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XUnmapWindow(IntPtr display, IntPtr window);
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XRootWindow(IntPtr display, int screen_number);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static Bool XCheckWindowEvent(Display display, Window w, EventMask event_mask, ref XEvent event_return);
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static Bool XCheckTypedWindowEvent(Display display, Window w, XEventName event_type, ref XEvent event_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDestroyWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XMoveWindow(IntPtr display, IntPtr w, int x, int y);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFlush(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
|
||||
|
||||
public static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event) {
|
||||
return XSendEvent(display, window, propagate, new IntPtr((int)event_mask), ref send_event);
|
||||
}
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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"), SuppressUnmanagedCodeSecurity]
|
||||
public 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"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFree(IntPtr data);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XRaiseWindow(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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);
|
||||
|
||||
// Colormaps
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDefaultDepth(IntPtr display, int screen_number);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDefaultScreen(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr data, int nelements);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XUndefineCursor(IntPtr display, IntPtr window);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFreeCursor(IntPtr display, IntPtr cursor);
|
||||
|
||||
// Drawing
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, XGCValues[] values);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XFreeGC(IntPtr display, IntPtr gc);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public 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"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foregroundCol, ref XColor backgroundCol, int x_hot, int y_hot);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XGetWMHints(Display display, Window w); // returns XWMHints*
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XSetWMHints(Display display, Window w, ref XWMHints wmhints);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XAllocWMHints();
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static bool XkbSetDetectableAutoRepeat(IntPtr display, bool detectable, out bool supported);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XCreateColormap(Display display, Window window, IntPtr visual, int alloc);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Status XGetTransientForHint(Display display, Window w, out Window prop_window_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XSync(Display display, bool discard);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XDefaultRootWindow(IntPtr display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XBitmapBitOrder(Display display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr XCreateImage(Display display, IntPtr visual,
|
||||
uint depth, ImageFormat format, int offset, IntPtr data, int width, int height,
|
||||
int bitmap_pad, int bytes_per_line);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XPutImage(Display display, IntPtr drawable,
|
||||
IntPtr gc, IntPtr image, int src_x, int src_y, int dest_x, int dest_y, int width, int height);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XLookupString(ref XKeyEvent event_struct, [Out] byte[] buffer_return,
|
||||
int bytes_buffer, [Out] KeySym[] keysym_return, IntPtr status_in_out);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XRefreshKeyboardMapping(ref XMappingEvent event_map);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
|
||||
|
||||
static readonly IntPtr CopyFromParent = IntPtr.Zero;
|
||||
|
||||
public static void SendNetWMMessage(X11WindowInfo window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2)
|
||||
{
|
||||
XEvent xev = new XEvent();
|
||||
xev.ClientMessageEvent.type = XEventName.ClientMessage;
|
||||
xev.ClientMessageEvent.send_event = true;
|
||||
xev.ClientMessageEvent.window = window.WindowHandle;
|
||||
xev.ClientMessageEvent.message_type = message_type;
|
||||
xev.ClientMessageEvent.format = 32;
|
||||
xev.ClientMessageEvent.ptr1 = l0;
|
||||
xev.ClientMessageEvent.ptr2 = l1;
|
||||
xev.ClientMessageEvent.ptr3 = l2;
|
||||
|
||||
XSendEvent(window.Display, window.RootWindow, false,
|
||||
EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);
|
||||
}
|
||||
|
||||
public static IntPtr CreatePixmapFromImage(Display display, System.Drawing.Bitmap image)
|
||||
{
|
||||
int width = image.Width, height = image.Height;
|
||||
|
||||
System.Drawing.Imaging.BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
|
||||
System.Drawing.Imaging.ImageLockMode.ReadOnly,
|
||||
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
|
||||
IntPtr ximage = XCreateImage(display, CopyFromParent, 24, ImageFormat.ZPixmap,
|
||||
0, data.Scan0, width, height, 32, 0);
|
||||
IntPtr pixmap = XCreatePixmap(display, XDefaultRootWindow(display),
|
||||
width, height, 24);
|
||||
IntPtr gc = XCreateGC(display, pixmap, IntPtr.Zero, null);
|
||||
|
||||
XPutImage(display, pixmap, gc, ximage, 0, 0, 0, 0, width, height);
|
||||
|
||||
XFreeGC(display, gc);
|
||||
image.UnlockBits(data);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
public static IntPtr CreateMaskFromImage(Display display, System.Drawing.Bitmap image)
|
||||
{
|
||||
int width = image.Width;
|
||||
int height = image.Height;
|
||||
int stride = (width + 7) >> 3;
|
||||
byte[] mask = new byte[stride * height];
|
||||
bool msbfirst = (XBitmapBitOrder(display) == 1); // 1 = MSBFirst
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
byte bit = (byte) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7)));
|
||||
int offset = y * stride + (x >> 3);
|
||||
|
||||
if (image.GetPixel(x, y).A >= 128)
|
||||
mask[offset] |= bit;
|
||||
}
|
||||
}
|
||||
|
||||
return XCreatePixmapFromBitmapData(display, XDefaultRootWindow(display),
|
||||
mask, width, height, new IntPtr(1), IntPtr.Zero, 1);
|
||||
}
|
||||
|
||||
const string XrandrLibrary = "libXrandr.so.2";
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern XRRScreenConfiguration XRRGetScreenInfo(Display dpy, Drawable draw);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern void XRRFreeScreenConfigInfo(XRRScreenConfiguration config);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern Status XRRSetScreenConfig(Display dpy, XRRScreenConfiguration config,
|
||||
Drawable draw, int size_index, ref ushort rotation, Time timestamp);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern Status XRRSetScreenConfigAndRate(Display dpy, XRRScreenConfiguration config,
|
||||
Drawable draw, int size_index, ushort rotation, short rate, Time timestamp);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern ushort XRRConfigCurrentConfiguration(XRRScreenConfiguration config, out ushort rotation);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern short XRRConfigCurrentRate(XRRScreenConfiguration config);
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern int XRRRootToScreen(Display dpy, Window root);
|
||||
|
||||
// the following are always safe to call, even if RandR is not implemented on a screen
|
||||
[DllImport(XrandrLibrary)]
|
||||
unsafe static extern XRRScreenSize* XRRSizes(Display dpy, int screen, int* nsizes);
|
||||
|
||||
public unsafe static XRRScreenSize[] XRRSizes(Display dpy, int screen) {
|
||||
int count;
|
||||
XRRScreenSize* data = XRRSizes(dpy, screen, &count);
|
||||
if (count == 0) return null;
|
||||
|
||||
XRRScreenSize[] sizes = new XRRScreenSize[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
sizes[i] = *data++;
|
||||
return sizes;
|
||||
}
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
unsafe static extern short* XRRRates(Display dpy, int screen, int size_index, int* nrates);
|
||||
|
||||
public unsafe static short[] XRRRates(Display dpy, int screen, int size_index) {
|
||||
int count;
|
||||
short* data = XRRRates(dpy, screen, size_index, &count);
|
||||
if (count == 0) return null;
|
||||
|
||||
short[] rates = new short[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
rates[i] = *data++;
|
||||
return rates;
|
||||
}
|
||||
|
||||
[DllImport(XrandrLibrary)]
|
||||
public static extern Time XRRTimes(Display dpy, int screen, out Time config_timestamp);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern int XScreenCount(Display display);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
unsafe static extern int* XListDepths(Display display, int screen_number, int* count_return);
|
||||
|
||||
public unsafe static int[] XListDepths(Display display, int screen_number) {
|
||||
int count;
|
||||
int* data = XListDepths(display, screen_number, &count);
|
||||
if (count == 0) return null;
|
||||
|
||||
int[] depths = new int[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
depths[i] = *data++;
|
||||
return depths;
|
||||
}
|
||||
|
||||
public static Display DefaultDisplay;
|
||||
internal static int ScreenCount;
|
||||
|
||||
static API() {
|
||||
DefaultDisplay = API.XOpenDisplay(IntPtr.Zero);
|
||||
if (DefaultDisplay == IntPtr.Zero)
|
||||
throw new PlatformException("Could not establish connection to the X-Server.");
|
||||
|
||||
ScreenCount = API.XScreenCount(DefaultDisplay);
|
||||
Debug.Print("Display connection: {0}, Screen count: {1}", DefaultDisplay, ScreenCount);
|
||||
|
||||
//AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
|
||||
}
|
||||
|
||||
static void CurrentDomain_ProcessExit(object sender, EventArgs e) {
|
||||
if (DefaultDisplay != IntPtr.Zero) {
|
||||
API.XCloseDisplay(DefaultDisplay);
|
||||
DefaultDisplay = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern KeySym XGetKeyboardMapping(Display display, KeyCode first_keycode, int keycode_count,
|
||||
ref int keysyms_per_keycode_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void XDisplayKeycodes(Display display, ref int min_keycodes_return, ref int max_keycodes_return);
|
||||
|
||||
[DllImport("libX11"), SuppressUnmanagedCodeSecurity]
|
||||
public static extern KeySym XLookupKeysym(ref XKeyEvent key_event, int index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ using System.ComponentModel;
|
|||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
|
||||
|
@ -57,6 +58,9 @@ namespace OpenTK.Platform.X11 {
|
|||
IntPtr net_wm_icon;
|
||||
IntPtr net_frame_extents;
|
||||
|
||||
IntPtr clipboard, xa_targets, xa_utf8_string, xa_atom, data_sel;
|
||||
string clipboard_paste_text, clipboard_copy_text;
|
||||
|
||||
static readonly IntPtr xa_cardinal = (IntPtr)6;
|
||||
static readonly IntPtr _remove = (IntPtr)0;
|
||||
static readonly IntPtr _add = (IntPtr)1;
|
||||
|
@ -188,6 +192,12 @@ namespace OpenTK.Platform.X11 {
|
|||
net_wm_state_maximized_vertical = API.XInternAtom(window.Display, "_NET_WM_STATE_MAXIMIZED_VERT", false);
|
||||
net_wm_icon = API.XInternAtom(window.Display, "_NEW_WM_ICON", false);
|
||||
net_frame_extents = API.XInternAtom(window.Display, "_NET_FRAME_EXTENTS", false);
|
||||
|
||||
clipboard = API.XInternAtom(window.Display, "CLIPBOARD", false);
|
||||
xa_targets = API.XInternAtom(window.Display, "TARGETS", false);
|
||||
xa_utf8_string = API.XInternAtom(window.Display, "UTF8_STRING", false);
|
||||
xa_atom = API.XInternAtom(window.Display, "ATOM", false);
|
||||
data_sel = API.XInternAtom(window.Display, "CS_SEL_DATA", false);
|
||||
}
|
||||
|
||||
void SetWindowMinMax(short min_width, short min_height, short max_width, short max_height) {
|
||||
|
@ -292,13 +302,18 @@ namespace OpenTK.Platform.X11 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GetPendingEvent() {
|
||||
return API.XCheckWindowEvent(window.Display, window.WindowHandle, window.EventMask, ref e) ||
|
||||
API.XCheckTypedWindowEvent(window.Display, window.WindowHandle, XEventName.ClientMessage, ref e) ||
|
||||
API.XCheckTypedWindowEvent(window.Display, window.WindowHandle, XEventName.SelectionNotify, ref e) ||
|
||||
API.XCheckTypedWindowEvent(window.Display, window.WindowHandle, XEventName.SelectionRequest, ref e);
|
||||
}
|
||||
|
||||
public void ProcessEvents() {
|
||||
public unsafe void ProcessEvents() {
|
||||
// Process all pending events
|
||||
while (Exists && window != null) {
|
||||
if (!API.XCheckWindowEvent(window.Display, window.WindowHandle, window.EventMask, ref e) &&
|
||||
!API.XCheckTypedWindowEvent(window.Display, window.WindowHandle, XEventName.ClientMessage, ref e))
|
||||
break;
|
||||
if (!GetPendingEvent ()) break;
|
||||
|
||||
// Respond to the event e
|
||||
switch (e.type) {
|
||||
|
@ -407,13 +422,67 @@ namespace OpenTK.Platform.X11 {
|
|||
case XEventName.PropertyNotify:
|
||||
if (e.PropertyEvent.atom == net_wm_state) {
|
||||
if (WindowStateChanged != null)
|
||||
WindowStateChanged(this, EventArgs.Empty);
|
||||
WindowStateChanged (this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
//if (e.PropertyEvent.atom == net_frame_extents) {
|
||||
// RefreshWindowBorders();
|
||||
//}
|
||||
break;
|
||||
|
||||
case XEventName.SelectionNotify:
|
||||
clipboard_paste_text = "";
|
||||
|
||||
if (e.SelectionEvent.selection == clipboard && e.SelectionEvent.target == xa_utf8_string && e.SelectionEvent.property == data_sel) {
|
||||
IntPtr prop_type, num_items, bytes_after, data = IntPtr.Zero;
|
||||
int prop_format;
|
||||
|
||||
API.XGetWindowProperty (window.Display, window.WinHandle, data_sel, IntPtr.Zero, new IntPtr (1024), false, IntPtr.Zero,
|
||||
out prop_type, out prop_format, out num_items, out bytes_after, ref data);
|
||||
|
||||
API.XDeleteProperty (window.Display, window.WinHandle, data_sel);
|
||||
if (num_items == IntPtr.Zero) break;
|
||||
|
||||
if (prop_type == xa_utf8_string) {
|
||||
byte[] dst = new byte[(int)num_items];
|
||||
byte* src = (byte*)data;
|
||||
for (int i = 0; i < dst.Length; i++) { dst[i] = src[i]; }
|
||||
|
||||
clipboard_paste_text = Encoding.UTF8.GetString(dst);
|
||||
}
|
||||
API.XFree (data);
|
||||
}
|
||||
break;
|
||||
|
||||
case XEventName.SelectionRequest:
|
||||
XEvent reply = default(XEvent);
|
||||
reply.SelectionEvent.type = XEventName.SelectionNotify;
|
||||
reply.SelectionEvent.send_event = true;
|
||||
reply.SelectionEvent.display = window.Display;
|
||||
reply.SelectionEvent.requestor = e.SelectionRequestEvent.requestor;
|
||||
reply.SelectionEvent.selection = e.SelectionRequestEvent.selection;
|
||||
reply.SelectionEvent.target = e.SelectionRequestEvent.target;
|
||||
reply.SelectionEvent.property = IntPtr.Zero;
|
||||
reply.SelectionEvent.time = e.SelectionRequestEvent.time;
|
||||
|
||||
if (e.SelectionRequestEvent.selection == clipboard && e.SelectionRequestEvent.target == xa_utf8_string && clipboard_copy_text != null) {
|
||||
reply.SelectionEvent.property = GetSelectionProperty(ref e);
|
||||
|
||||
byte[] utf8_data = Encoding.UTF8.GetBytes (clipboard_copy_text);
|
||||
fixed (byte* utf8_ptr = utf8_data) {
|
||||
API.XChangeProperty(window.Display, reply.SelectionEvent.requestor, reply.SelectionEvent.property, xa_utf8_string, 8,
|
||||
PropertyMode.Replace, (IntPtr)utf8_ptr, utf8_data.Length);
|
||||
}
|
||||
} else if (e.SelectionRequestEvent.selection == clipboard && e.SelectionRequestEvent.target == xa_targets) {
|
||||
reply.SelectionEvent.property = GetSelectionProperty(ref e);
|
||||
|
||||
IntPtr[] data = new IntPtr[] { xa_utf8_string, xa_targets };
|
||||
API.XChangeProperty(window.Display, reply.SelectionEvent.requestor, reply.SelectionEvent.property, xa_atom, 32,
|
||||
PropertyMode.Replace, data, data.Length);
|
||||
}
|
||||
|
||||
API.XSendEvent(window.Display, e.SelectionRequestEvent.requestor, true, EventMask.NoEventMask, ref reply);
|
||||
break;
|
||||
|
||||
default:
|
||||
//Debug.WriteLine(String.Format("{0} event was not handled", e.type));
|
||||
|
@ -421,10 +490,38 @@ namespace OpenTK.Platform.X11 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
IntPtr GetSelectionProperty(ref XEvent e) {
|
||||
IntPtr property = e.SelectionRequestEvent.property;
|
||||
if (property != IntPtr.Zero) return property;
|
||||
|
||||
/* For obsolete clients. See ICCCM spec, selections chapter for reasoning. */
|
||||
return e.SelectionRequestEvent.target;
|
||||
}
|
||||
|
||||
public string GetClipboardText() { return ""; }
|
||||
public string GetClipboardText() {
|
||||
IntPtr owner = API.XGetSelectionOwner(window.Display, clipboard);
|
||||
if (owner == IntPtr.Zero) return ""; // no window owner
|
||||
|
||||
Console.WriteLine (window.WinHandle + ", " + window.WindowHandle);
|
||||
int result = API.XConvertSelection (window.Display, clipboard, xa_utf8_string, data_sel, window.WinHandle, IntPtr.Zero);
|
||||
Console.WriteLine (owner.ToInt64 () + ", " + result);
|
||||
|
||||
clipboard_paste_text = null;
|
||||
|
||||
// wait up to 1 second for SelectionNotify event to arrive
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ProcessEvents ();
|
||||
if (clipboard_paste_text != null) return clipboard_paste_text;
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public void SetClipboardText( string value ) { }
|
||||
public void SetClipboardText(string value) {
|
||||
clipboard_copy_text = value;
|
||||
API.XSetSelectionOwner(window.Display, clipboard, window.WinHandle, IntPtr.Zero);
|
||||
}
|
||||
|
||||
public Rectangle Bounds {
|
||||
get { return bounds; }
|
||||
|
@ -759,4 +856,4 @@ namespace OpenTK.Platform.X11 {
|
|||
this.Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue