2 changed files with 13 additions and 601 deletions
@ -1,404 +0,0 @@ |
|||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Disposables; |
|||
using System.Runtime.InteropServices; |
|||
using Gdk; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Input.Raw; |
|||
using Avalonia.Platform; |
|||
using Avalonia.Input; |
|||
using Avalonia.Threading; |
|||
using Action = System.Action; |
|||
using WindowEdge = Avalonia.Controls.WindowEdge; |
|||
|
|||
namespace Avalonia.Gtk |
|||
{ |
|||
using Gtk = global::Gtk; |
|||
|
|||
public class WindowImpl : Gtk.Window, IWindowImpl, IPlatformHandle |
|||
{ |
|||
private IInputRoot _inputRoot; |
|||
|
|||
private Size _lastClientSize; |
|||
|
|||
private Gtk.IMContext _imContext; |
|||
|
|||
private uint _lastKeyEventTimestamp; |
|||
|
|||
private static readonly Gdk.Cursor DefaultCursor = new Gdk.Cursor(CursorType.LeftPtr); |
|||
|
|||
public WindowImpl() |
|||
: base(Gtk.WindowType.Toplevel) |
|||
{ |
|||
DefaultSize = new Gdk.Size(900, 480); |
|||
Init(); |
|||
} |
|||
|
|||
public WindowImpl(Gtk.WindowType type) |
|||
: base(type) |
|||
{ |
|||
Init(); |
|||
} |
|||
|
|||
private void Init() |
|||
{ |
|||
Events = EventMask.PointerMotionMask | |
|||
EventMask.ButtonPressMask | |
|||
EventMask.ButtonReleaseMask; |
|||
_imContext = new Gtk.IMMulticontext(); |
|||
_imContext.Commit += ImContext_Commit; |
|||
DoubleBuffered = false; |
|||
Realize(); |
|||
_lastClientSize = ClientSize; |
|||
} |
|||
|
|||
protected override void OnRealized () |
|||
{ |
|||
base.OnRealized (); |
|||
_imContext.ClientWindow = this.GdkWindow; |
|||
} |
|||
|
|||
public Size ClientSize |
|||
{ |
|||
get |
|||
{ |
|||
int width; |
|||
int height; |
|||
GetSize(out width, out height); |
|||
return new Size(width, height); |
|||
} |
|||
|
|||
set |
|||
{ |
|||
Resize((int)value.Width, (int)value.Height); |
|||
} |
|||
} |
|||
|
|||
public Size MaxClientSize |
|||
{ |
|||
get |
|||
{ |
|||
// TODO: This should take into account things such as taskbar and window border
|
|||
// thickness etc.
|
|||
return new Size(Screen.Width, Screen.Height); |
|||
} |
|||
} |
|||
|
|||
public Avalonia.Controls.WindowState WindowState |
|||
{ |
|||
get |
|||
{ |
|||
switch (GdkWindow.State) |
|||
{ |
|||
case Gdk.WindowState.Iconified: |
|||
return Controls.WindowState.Minimized; |
|||
case Gdk.WindowState.Maximized: |
|||
return Controls.WindowState.Maximized; |
|||
default: |
|||
return Controls.WindowState.Normal; |
|||
} |
|||
} |
|||
|
|||
set |
|||
{ |
|||
switch (value) |
|||
{ |
|||
case Controls.WindowState.Minimized: |
|||
GdkWindow.Iconify(); |
|||
break; |
|||
case Controls.WindowState.Maximized: |
|||
GdkWindow.Maximize(); |
|||
break; |
|||
case Controls.WindowState.Normal: |
|||
GdkWindow.Deiconify(); |
|||
GdkWindow.Unmaximize(); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public double Scaling => 1; |
|||
|
|||
IPlatformHandle ITopLevelImpl.Handle => this; |
|||
|
|||
[DllImport("libgdk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] |
|||
extern static IntPtr gdk_win32_drawable_get_handle(IntPtr gdkWindow); |
|||
|
|||
[DllImport("libgtk-x11-2.0.so.0", CallingConvention = CallingConvention.Cdecl)] |
|||
extern static IntPtr gdk_x11_drawable_get_xid(IntPtr gdkWindow); |
|||
|
|||
[DllImport("libgdk-quartz-2.0-0.dylib", CallingConvention = CallingConvention.Cdecl)] |
|||
extern static IntPtr gdk_quartz_window_get_nswindow(IntPtr gdkWindow); |
|||
|
|||
IntPtr _nativeWindow; |
|||
|
|||
IntPtr GetNativeWindow() |
|||
{ |
|||
IntPtr h = GdkWindow.Handle; |
|||
if (_nativeWindow != IntPtr.Zero) |
|||
return _nativeWindow; |
|||
//Try whatever backend that works
|
|||
try |
|||
{ |
|||
return _nativeWindow = gdk_quartz_window_get_nswindow(h); |
|||
} |
|||
catch |
|||
{ |
|||
} |
|||
try |
|||
{ |
|||
return _nativeWindow = gdk_x11_drawable_get_xid(h); |
|||
} |
|||
catch |
|||
{ |
|||
} |
|||
return _nativeWindow = gdk_win32_drawable_get_handle(h); |
|||
} |
|||
|
|||
|
|||
IntPtr IPlatformHandle.Handle => GetNativeWindow(); |
|||
public string HandleDescriptor => "HWND"; |
|||
|
|||
public Action Activated { get; set; } |
|||
|
|||
public Action Closed { get; set; } |
|||
|
|||
public Action Deactivated { get; set; } |
|||
|
|||
public Action<RawInputEventArgs> Input { get; set; } |
|||
|
|||
public Action<Rect> Paint { get; set; } |
|||
|
|||
public Action<Size> Resized { get; set; } |
|||
|
|||
public Action<double> ScalingChanged { get; set; } |
|||
|
|||
public IPopupImpl CreatePopup() |
|||
{ |
|||
return new PopupImpl(); |
|||
} |
|||
|
|||
public void Invalidate(Rect rect) |
|||
{ |
|||
if (base.GdkWindow != null) |
|||
base.GdkWindow.InvalidateRect( |
|||
new Rectangle((int) rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height), true); |
|||
} |
|||
|
|||
public Point PointToClient(Point point) |
|||
{ |
|||
int x, y; |
|||
GdkWindow.GetDeskrelativeOrigin(out x, out y); |
|||
|
|||
return new Point(point.X - x, point.Y - y); |
|||
} |
|||
|
|||
public Point PointToScreen(Point point) |
|||
{ |
|||
int x, y; |
|||
GdkWindow.GetDeskrelativeOrigin(out x, out y); |
|||
|
|||
return new Point(point.X + x, point.Y + y); |
|||
} |
|||
|
|||
public void SetInputRoot(IInputRoot inputRoot) |
|||
{ |
|||
_inputRoot = inputRoot; |
|||
} |
|||
|
|||
public void SetTitle(string title) |
|||
{ |
|||
Title = title; |
|||
} |
|||
|
|||
|
|||
public void SetCursor(IPlatformHandle cursor) |
|||
{ |
|||
GdkWindow.Cursor = cursor != null ? new Gdk.Cursor(cursor.Handle) : DefaultCursor; |
|||
} |
|||
|
|||
public void BeginMoveDrag() |
|||
{ |
|||
int x, y; |
|||
ModifierType mod; |
|||
Screen.RootWindow.GetPointer(out x, out y, out mod); |
|||
BeginMoveDrag(1, x, y, 0); |
|||
} |
|||
|
|||
public void BeginResizeDrag(WindowEdge edge) |
|||
{ |
|||
int x, y; |
|||
ModifierType mod; |
|||
Screen.RootWindow.GetPointer(out x, out y, out mod); |
|||
BeginResizeDrag((Gdk.WindowEdge) (int) edge, 1, x, y, 0); |
|||
} |
|||
|
|||
public Point Position |
|||
{ |
|||
get |
|||
{ |
|||
int x, y; |
|||
GetPosition(out x, out y); |
|||
return new Point(x, y); |
|||
} |
|||
set |
|||
{ |
|||
Move((int)value.X, (int)value.Y); |
|||
} |
|||
} |
|||
|
|||
public IDisposable ShowDialog() |
|||
{ |
|||
Modal = true; |
|||
Show(); |
|||
|
|||
return Disposable.Empty; |
|||
} |
|||
|
|||
public void SetSystemDecorations(bool enabled) => Decorated = enabled; |
|||
|
|||
void ITopLevelImpl.Activate() |
|||
{ |
|||
Activate(); |
|||
} |
|||
|
|||
private static InputModifiers GetModifierKeys(ModifierType state) |
|||
{ |
|||
var rv = InputModifiers.None; |
|||
if (state.HasFlag(ModifierType.ControlMask)) |
|||
rv |= InputModifiers.Control; |
|||
if (state.HasFlag(ModifierType.ShiftMask)) |
|||
rv |= InputModifiers.Shift; |
|||
if (state.HasFlag(ModifierType.Mod1Mask)) |
|||
rv |= InputModifiers.Control; |
|||
if(state.HasFlag(ModifierType.Button1Mask)) |
|||
rv |= InputModifiers.LeftMouseButton; |
|||
if (state.HasFlag(ModifierType.Button2Mask)) |
|||
rv |= InputModifiers.RightMouseButton; |
|||
if (state.HasFlag(ModifierType.Button3Mask)) |
|||
rv |= InputModifiers.MiddleMouseButton; |
|||
return rv; |
|||
} |
|||
|
|||
protected override bool OnButtonPressEvent(EventButton evnt) |
|||
{ |
|||
|
|||
var e = new RawMouseEventArgs( |
|||
GtkMouseDevice.Instance, |
|||
evnt.Time, |
|||
_inputRoot, |
|||
evnt.Button == 1 |
|||
? RawMouseEventType.LeftButtonDown |
|||
: evnt.Button == 3 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown, |
|||
new Point(evnt.X, evnt.Y), GetModifierKeys(evnt.State)); |
|||
Input(e); |
|||
return true; |
|||
} |
|||
|
|||
protected override bool OnScrollEvent(EventScroll evnt) |
|||
{ |
|||
double step = 1; |
|||
var delta = new Vector(); |
|||
if (evnt.Direction == ScrollDirection.Down) |
|||
delta = new Vector(0, -step); |
|||
else if (evnt.Direction == ScrollDirection.Up) |
|||
delta = new Vector(0, step); |
|||
else if (evnt.Direction == ScrollDirection.Right) |
|||
delta = new Vector(-step, 0); |
|||
if (evnt.Direction == ScrollDirection.Left) |
|||
delta = new Vector(step, 0); |
|||
var e = new RawMouseWheelEventArgs(GtkMouseDevice.Instance, evnt.Time, _inputRoot, new Point(evnt.X, evnt.Y), delta, GetModifierKeys(evnt.State)); |
|||
Input(e); |
|||
return base.OnScrollEvent(evnt); |
|||
} |
|||
|
|||
protected override bool OnButtonReleaseEvent(EventButton evnt) |
|||
{ |
|||
var e = new RawMouseEventArgs( |
|||
GtkMouseDevice.Instance, |
|||
evnt.Time, |
|||
_inputRoot, |
|||
evnt.Button == 1 |
|||
? RawMouseEventType.LeftButtonUp |
|||
: evnt.Button == 3 ? RawMouseEventType.RightButtonUp : RawMouseEventType.MiddleButtonUp, |
|||
new Point(evnt.X, evnt.Y), GetModifierKeys(evnt.State)); |
|||
Input(e); |
|||
return true; |
|||
} |
|||
|
|||
protected override bool OnConfigureEvent(EventConfigure evnt) |
|||
{ |
|||
var newSize = new Size(evnt.Width, evnt.Height); |
|||
|
|||
if (newSize != _lastClientSize) |
|||
{ |
|||
Resized(newSize); |
|||
_lastClientSize = newSize; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
protected override void OnDestroyed() |
|||
{ |
|||
Closed(); |
|||
} |
|||
|
|||
private bool ProcessKeyEvent(EventKey evnt) |
|||
{ |
|||
_lastKeyEventTimestamp = evnt.Time; |
|||
if (_imContext.FilterKeypress(evnt)) |
|||
return true; |
|||
var e = new RawKeyEventArgs( |
|||
GtkKeyboardDevice.Instance, |
|||
evnt.Time, |
|||
evnt.Type == EventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp, |
|||
GtkKeyboardDevice.ConvertKey(evnt.Key), GetModifierKeys(evnt.State)); |
|||
Input(e); |
|||
return true; |
|||
} |
|||
|
|||
protected override bool OnKeyPressEvent(EventKey evnt) => ProcessKeyEvent(evnt); |
|||
|
|||
protected override bool OnKeyReleaseEvent(EventKey evnt) => ProcessKeyEvent(evnt); |
|||
|
|||
private void ImContext_Commit(object o, Gtk.CommitArgs args) |
|||
{ |
|||
Input(new RawTextInputEventArgs(GtkKeyboardDevice.Instance, _lastKeyEventTimestamp, args.Str)); |
|||
} |
|||
|
|||
protected override bool OnExposeEvent(EventExpose evnt) |
|||
{ |
|||
Paint(evnt.Area.ToAvalonia()); |
|||
return true; |
|||
} |
|||
|
|||
protected override void OnFocusActivated() |
|||
{ |
|||
Activated(); |
|||
} |
|||
|
|||
protected override bool OnMotionNotifyEvent(EventMotion evnt) |
|||
{ |
|||
var position = new Point(evnt.X, evnt.Y); |
|||
|
|||
GtkMouseDevice.Instance.SetClientPosition(position); |
|||
|
|||
var e = new RawMouseEventArgs( |
|||
GtkMouseDevice.Instance, |
|||
evnt.Time, |
|||
_inputRoot, |
|||
RawMouseEventType.Move, |
|||
position, GetModifierKeys(evnt.State)); |
|||
Input(e); |
|||
return true; |
|||
} |
|||
|
|||
public void SetIcon(IWindowIconImpl icon) |
|||
{ |
|||
Icon = ((IconImpl)icon).Pixbuf; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue