Browse Source

Merge branch 'master' into fixes/TextBlock

pull/3690/head
Benedikt Stebner 7 years ago
committed by GitHub
parent
commit
a8309765c2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 95
      native/Avalonia.Native/src/OSX/window.mm
  2. 47
      src/Avalonia.Controls/Primitives/ScrollBar.cs
  3. 3
      src/Avalonia.Controls/TextBox.cs
  4. 2
      src/Avalonia.Themes.Default/TextBox.xaml
  5. 3
      src/Avalonia.Themes.Default/TreeViewItem.xaml
  6. 46
      src/Avalonia.X11/X11Window.cs
  7. 26
      tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs

95
native/Avalonia.Native/src/OSX/window.mm

@ -31,9 +31,11 @@ public:
AvnPoint lastPositionSet;
NSString* _lastTitle;
IAvnAppMenu* _mainMenu;
bool _shown;
WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl)
{
_shown = false;
_mainMenu = nullptr;
BaseEvents = events;
_glContext = gl;
@ -115,6 +117,8 @@ public:
[NSApp activateIgnoringOtherApps:YES];
[Window setTitle:_lastTitle];
_shown = true;
return S_OK;
}
@ -400,6 +404,7 @@ protected:
[Window setStyleMask:GetStyle()];
}
public:
virtual void OnResized ()
{
@ -615,57 +620,63 @@ private:
{
_lastWindowState = state;
switch (state) {
case Maximized:
lastPositionSet.X = 0;
lastPositionSet.Y = 0;
if([Window isMiniaturized])
{
[Window deminiaturize:Window];
}
if(!IsZoomed())
{
DoZoom();
}
break;
case Minimized:
[Window miniaturize:Window];
break;
default:
if([Window isMiniaturized])
{
[Window deminiaturize:Window];
}
if(IsZoomed())
{
DoZoom();
}
break;
if(_shown)
{
switch (state) {
case Maximized:
lastPositionSet.X = 0;
lastPositionSet.Y = 0;
if([Window isMiniaturized])
{
[Window deminiaturize:Window];
}
if(!IsZoomed())
{
DoZoom();
}
break;
case Minimized:
[Window miniaturize:Window];
break;
default:
if([Window isMiniaturized])
{
[Window deminiaturize:Window];
}
if(IsZoomed())
{
DoZoom();
}
break;
}
}
return S_OK;
}
}
protected:
virtual void OnResized () override
{
auto windowState = [Window isMiniaturized] ? Minimized
: (IsZoomed() ? Maximized : Normal);
if (windowState != _lastWindowState)
if(_shown)
{
_lastWindowState = windowState;
auto windowState = [Window isMiniaturized] ? Minimized
: (IsZoomed() ? Maximized : Normal);
WindowEvents->WindowStateChanged(windowState);
if (windowState != _lastWindowState)
{
_lastWindowState = windowState;
WindowEvents->WindowStateChanged(windowState);
}
}
}
protected:
virtual NSWindowStyleMask GetStyle() override
{
unsigned long s = NSWindowStyleMaskBorderless;
@ -1360,6 +1371,11 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
}
- (void)windowDidResize:(NSNotification *)notification
{
_parent->OnResized();
}
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
{
return true;
@ -1430,6 +1446,7 @@ protected:
[Window setContentSize:NSSize{x, y}];
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))];
return S_OK;
}
}

47
src/Avalonia.Controls/Primitives/ScrollBar.cs

@ -2,8 +2,6 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reactive;
using System.Reactive.Linq;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Input;
@ -64,13 +62,6 @@ namespace Avalonia.Controls.Primitives
/// </summary>
public ScrollBar()
{
var isVisible = Observable.Merge(
this.GetObservable(MinimumProperty).Select(_ => Unit.Default),
this.GetObservable(MaximumProperty).Select(_ => Unit.Default),
this.GetObservable(ViewportSizeProperty).Select(_ => Unit.Default),
this.GetObservable(VisibilityProperty).Select(_ => Unit.Default))
.Select(_ => CalculateIsVisible());
this.Bind(IsVisibleProperty, isVisible, BindingPriority.Style);
UpdatePseudoClasses(Orientation);
}
@ -105,26 +96,20 @@ namespace Avalonia.Controls.Primitives
public event EventHandler<ScrollEventArgs> Scroll;
/// <summary>
/// Calculates whether the scrollbar should be visible.
/// Calculates and updates whether the scrollbar should be visible.
/// </summary>
/// <returns>The scrollbar's visibility.</returns>
private bool CalculateIsVisible()
private void UpdateIsVisible()
{
switch (Visibility)
var isVisible = Visibility switch
{
case ScrollBarVisibility.Visible:
return true;
case ScrollBarVisibility.Disabled:
case ScrollBarVisibility.Hidden:
return false;
case ScrollBarVisibility.Auto:
return double.IsNaN(ViewportSize) || Maximum > 0;
default:
throw new InvalidOperationException("Invalid value for ScrollBar.Visibility.");
}
ScrollBarVisibility.Visible => true,
ScrollBarVisibility.Disabled => false,
ScrollBarVisibility.Hidden => false,
ScrollBarVisibility.Auto => (double.IsNaN(ViewportSize) || Maximum > 0),
_ => throw new InvalidOperationException("Invalid value for ScrollBar.Visibility.")
};
SetValue(IsVisibleProperty, isVisible, BindingPriority.Style);
}
protected override void OnKeyDown(KeyEventArgs e)
@ -153,6 +138,16 @@ namespace Avalonia.Controls.Primitives
{
UpdatePseudoClasses(newValue.GetValueOrDefault<Orientation>());
}
else
{
if (property == MinimumProperty ||
property == MaximumProperty ||
property == ViewportSizeProperty ||
property == VisibilityProperty)
{
UpdateIsVisible();
}
}
}
protected override void OnTemplateApplied(TemplateAppliedEventArgs e)

3
src/Avalonia.Controls/TextBox.cs

@ -701,7 +701,8 @@ namespace Avalonia.Controls
{
var text = Text;
if (text != null && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
var clickInfo = e.GetCurrentPoint(this);
if (text != null && clickInfo.Properties.IsLeftButtonPressed && !(clickInfo.Pointer?.Captured is Border))
{
var point = e.GetPosition(_presenter);
var index = CaretIndex = _presenter.GetCaretIndex(point);

2
src/Avalonia.Themes.Default/TextBox.xaml

@ -69,7 +69,7 @@
<Style Selector="TextBox:error /template/ Border#border">
<Setter Property="BorderBrush" Value="{DynamicResource ErrorBrush}"/>
</Style>
<Style Selector="TextBox">
<Style Selector="TextBox /template/ DockPanel">
<Setter Property="Cursor" Value="IBeam" />
</Style>
<Style Selector="TextBox:disabled /template/ Border#border">

3
src/Avalonia.Themes.Default/TreeViewItem.xaml

@ -17,8 +17,7 @@
BorderThickness="{TemplateBinding BorderThickness}"
TemplatedControl.IsTemplateFocusTarget="True">
<Grid Name="PART_Header"
ColumnDefinitions="16, Auto"
HorizontalAlignment="Left"
ColumnDefinitions="16, *"
Margin="{TemplateBinding Level, Mode=OneWay, Converter={StaticResource LeftMarginConverter}}" >
<ToggleButton Name="expander"
Focusable="False"

46
src/Avalonia.X11/X11Window.cs

@ -546,14 +546,14 @@ namespace Avalonia.X11
}
else if (value == WindowState.Maximized)
{
SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_HIDDEN, IntPtr.Zero);
SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)1, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT,
ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_HIDDEN);
ChangeWMAtoms(true, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT,
_x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ);
}
else
{
SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_HIDDEN, IntPtr.Zero);
SendNetWMMessage(_x11.Atoms._NET_WM_STATE, (IntPtr)0, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT,
ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_HIDDEN);
ChangeWMAtoms(false, _x11.Atoms._NET_WM_STATE_MAXIMIZED_VERT,
_x11.Atoms._NET_WM_STATE_MAXIMIZED_HORZ);
}
}
@ -989,8 +989,7 @@ namespace Avalonia.X11
public void SetTopmost(bool value)
{
SendNetWMMessage(_x11.Atoms._NET_WM_STATE,
(IntPtr)(value ? 1 : 0), _x11.Atoms._NET_WM_STATE_ABOVE, IntPtr.Zero);
ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE);
}
public void ShowDialog(IWindowImpl parent)
@ -1017,8 +1016,41 @@ namespace Avalonia.X11
public void ShowTaskbarIcon(bool value)
{
ChangeWMAtoms(!value, _x11.Atoms._NET_WM_STATE_SKIP_TASKBAR);
}
void ChangeWMAtoms(bool enable, params IntPtr[] atoms)
{
if (atoms.Length < 1 || atoms.Length > 4)
throw new ArgumentException();
if (!_mapped)
{
XGetWindowProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_STATE, IntPtr.Zero, new IntPtr(256),
false, (IntPtr)Atom.XA_ATOM, out _, out _, out var nitems, out _,
out var prop);
var ptr = (IntPtr*)prop.ToPointer();
var newAtoms = new HashSet<IntPtr>();
for (var c = 0; c < nitems.ToInt64(); c++)
newAtoms.Add(*ptr);
XFree(prop);
foreach(var atom in atoms)
if (enable)
newAtoms.Add(atom);
else
newAtoms.Remove(atom);
XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32,
PropertyMode.Replace, newAtoms.ToArray(), newAtoms.Count);
}
SendNetWMMessage(_x11.Atoms._NET_WM_STATE,
(IntPtr)(value ? 0 : 1), _x11.Atoms._NET_WM_STATE_SKIP_TASKBAR, IntPtr.Zero);
(IntPtr)(enable ? 1 : 0),
atoms[0],
atoms.Length > 1 ? atoms[1] : IntPtr.Zero,
atoms.Length > 2 ? atoms[2] : IntPtr.Zero,
atoms.Length > 3 ? atoms[3] : IntPtr.Zero
);
}
public IPopupPositioner PopupPositioner { get; }

26
tests/Avalonia.Benchmarks/Layout/CalendarBenchmark.cs → tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs

@ -7,12 +7,12 @@ using BenchmarkDotNet.Attributes;
namespace Avalonia.Benchmarks.Layout
{
[MemoryDiagnoser]
public class CalendarBenchmark : IDisposable
public class ControlsBenchmark : IDisposable
{
private readonly IDisposable _app;
private readonly TestRoot _root;
public CalendarBenchmark()
public ControlsBenchmark()
{
_app = UnitTestApplication.Start(
TestServices.StyledWindow.With(
@ -38,6 +38,28 @@ namespace Avalonia.Benchmarks.Layout
_root.LayoutManager.ExecuteLayoutPass();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public void CreateButton()
{
var button = new Button();
_root.Child = button;
_root.LayoutManager.ExecuteLayoutPass();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public void CreateTextBox()
{
var textBox = new TextBox();
_root.Child = textBox;
_root.LayoutManager.ExecuteLayoutPass();
}
public void Dispose()
{
_app.Dispose();
Loading…
Cancel
Save