Merge remote-tracking branch 'remotes/origin/release/1.3' into new-emoji-object-in-editor

This commit is contained in:
Robin Krom 2022-10-09 21:05:38 +02:00
commit c2a5d1c961
No known key found for this signature in database
GPG key ID: BCC01364F1371490
35 changed files with 455 additions and 437 deletions

View file

@ -91,33 +91,34 @@ Source: {#LanguagesDir}\*zh-CN*; Excludes: "*installer*,*website*"; DestDir: {ap
Source: {#LanguagesDir}\*zh-TW*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\zhTW; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#LanguagesDir}\*zh-TW*; Excludes: "*installer*,*website*"; DestDir: {app}\Languages; Components: languages\zhTW; Flags: overwritereadonly ignoreversion replacesameversion;
;Office Plugin ;Office Plugin
Source: {#PluginDir}\Greenshot.Plugin.Office\*.dll; DestDir: {app}\Plugins\Office; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Office\Greenshot.Plugin.Office.dll; DestDir: {app}\Plugins\Office; Components: plugins\office; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
;JIRA Plugin ;JIRA Plugin
Source: {#PluginDir}\Greenshot.Plugin.Jira\*.dll; DestDir: {app}\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Jira\*Jira*.dll; DestDir: {app}\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.Jira\Languages\language_jira*.xml; DestDir: {app}\Languages\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Jira\Languages\language_jira*.xml; DestDir: {app}\Languages\Plugins\Jira; Components: plugins\jira; Flags: overwritereadonly ignoreversion replacesameversion;
;Imgur Plugin ;Imgur Plugin
Source: {#PluginDir}\Greenshot.Plugin.Imgur\*.dll; DestDir: {app}\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Imgur\Greenshot.Plugin.Imgur.dll; DestDir: {app}\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.Imgur\Languages\language_imgur*.xml; DestDir: {app}\Languages\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Imgur\Languages\language_imgur*.xml; DestDir: {app}\Languages\Plugins\Imgur; Components: plugins\imgur; Flags: overwritereadonly ignoreversion replacesameversion;
;Box Plugin ;Box Plugin
Source: {#PluginDir}\Greenshot.Plugin.Box\*.dll; DestDir: {app}\Plugins\Box; Components: plugins\box; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Box\Greenshot.Plugin.Box.dll; DestDir: {app}\Plugins\Box; Components: plugins\box; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.Box\Languages\language_box*.xml; DestDir: {app}\Languages\Plugins\Box; Components: plugins\box; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Box\Languages\language_box*.xml; DestDir: {app}\Languages\Plugins\Box; Components: plugins\box; Flags: overwritereadonly ignoreversion replacesameversion;
;DropBox Plugin ;DropBox Plugin
Source: {#PluginDir}\Greenshot.Plugin.DropBox\*.dll; DestDir: {app}\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.DropBox\Greenshot.Plugin.DropBox.dll; DestDir: {app}\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.DropBox\Languages\language_dropbox*.xml; DestDir: {app}\Languages\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.DropBox\Languages\language_dropbox*.xml; DestDir: {app}\Languages\Plugins\DropBox; Components: plugins\dropbox; Flags: overwritereadonly ignoreversion replacesameversion;
;Flickr Plugin ;Flickr Plugin
Source: {#PluginDir}\Greenshot.Plugin.Flickr\*.dll; DestDir: {app}\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Flickr\Greenshot.Plugin.Flickr.dll; DestDir: {app}\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.Flickr\Languages\language_flickr*.xml; DestDir: {app}\Languages\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Flickr\Languages\language_flickr*.xml; DestDir: {app}\Languages\Plugins\Flickr; Components: plugins\flickr; Flags: overwritereadonly ignoreversion replacesameversion;
;Photobucket Plugin ;Photobucket Plugin
Source: {#PluginDir}\Greenshot.Plugin.Photobucket\*.dll; DestDir: {app}\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Photobucket\Greenshot.Plugin.Photobucket.dll; DestDir: {app}\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.Photobucket\Languages\language_photo*.xml; DestDir: {app}\Languages\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Photobucket\Languages\language_photo*.xml; DestDir: {app}\Languages\Plugins\Photobucket; Components: plugins\photobucket; Flags: overwritereadonly ignoreversion replacesameversion;
;Confluence Plugin ;Confluence Plugin
Source: {#PluginDir}\Greenshot.Plugin.Confluence\*.dll; DestDir: {app}\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Confluence\Greenshot.Plugin.Confluence.dll; DestDir: {app}\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.Confluence\Languages\language_confluence*.xml; DestDir: {app}\Languages\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.Confluence\Languages\language_confluence*.xml; DestDir: {app}\Languages\Plugins\Confluence; Components: plugins\confluence; Flags: overwritereadonly ignoreversion replacesameversion;
;ExternalCommand Plugin ;ExternalCommand Plugin
Source: {#PluginDir}\Greenshot.Plugin.ExternalCommand\*.dll; DestDir: {app}\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.ExternalCommand\Greenshot.Plugin.ExternalCommand.dll; DestDir: {app}\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#BaseDir}\Greenshot.Plugin.ExternalCommand\Languages\language_externalcommand*.xml; DestDir: {app}\Languages\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly ignoreversion replacesameversion; Source: {#BaseDir}\Greenshot.Plugin.ExternalCommand\Languages\language_externalcommand*.xml; DestDir: {app}\Languages\Plugins\ExternalCommand; Components: plugins\externalcommand; Flags: overwritereadonly ignoreversion replacesameversion;
;Win 10 Plugin ;Win 10 Plugin
Source: {#PluginDir}\Greenshot.Plugin.Win10\*.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion; Source: {#PluginDir}\Greenshot.Plugin.Win10\Greenshot.Plugin.Win10.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
Source: {#PluginDir}\Greenshot.Plugin.Win10\Microsoft.Toolkit.Uwp.Notifications.dll; DestDir: {app}\Plugins\Win10; Components: plugins\win10; Flags: overwritereadonly recursesubdirs ignoreversion replacesameversion;
[Setup] [Setup]
; changes associations is used when the installer installs new extensions, it clears the explorer icon cache ; changes associations is used when the installer installs new extensions, it clears the explorer icon cache

View file

@ -1,13 +1,13 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Copyright>Copyright © Greenshot 2004-2021</Copyright> <Copyright>Copyright © Greenshot 2004-2022</Copyright>
<Authors>Greenshot</Authors> <Authors>Greenshot</Authors>
<PackageIconUrl>https://getgreenshot.org/favicon.ico</PackageIconUrl> <PackageIconUrl>https://getgreenshot.org/favicon.ico</PackageIconUrl>
<RepositoryUrl>https://github.com/greenshot/greenshot</RepositoryUrl> <RepositoryUrl>https://github.com/greenshot/greenshot</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<PackageProjectUrl>https://github.com/greenshot/greenshot</PackageProjectUrl> <PackageProjectUrl>https://github.com/greenshot/greenshot</PackageProjectUrl>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression> <PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
<LangVersion>9</LangVersion> <LangVersion>latest</LangVersion>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<RuntimeIdentifiers>win10-x64;win10-x86;win-x64;win-x86</RuntimeIdentifiers> <RuntimeIdentifiers>win10-x64;win10-x86;win-x64;win-x86</RuntimeIdentifiers>
@ -46,7 +46,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="!$(MSBuildProjectName.Contains('Tests')) And $(MSBuildProjectName.StartsWith('Greenshot'))"> <ItemGroup Condition="!$(MSBuildProjectName.Contains('Tests')) And $(MSBuildProjectName.StartsWith('Greenshot'))">
<PackageReference Include="Nerdbank.GitVersioning" Version="3.4.255"> <PackageReference Include="Nerdbank.GitVersioning" Version="3.5.113">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>

View file

@ -386,6 +386,7 @@ EndSelection:<<<<<<<4
/// <returns>IEnumerable{(MemoryStream,string)}</returns> /// <returns>IEnumerable{(MemoryStream,string)}</returns>
private static IEnumerable<(MemoryStream stream,string filename)> IterateClipboardContent(IDataObject dataObject) private static IEnumerable<(MemoryStream stream,string filename)> IterateClipboardContent(IDataObject dataObject)
{ {
if (dataObject == null) yield break;
var fileDescriptors = AvailableFileDescriptors(dataObject); var fileDescriptors = AvailableFileDescriptors(dataObject);
if (fileDescriptors == null) yield break; if (fileDescriptors == null) yield break;
@ -499,6 +500,10 @@ EndSelection:<<<<<<<4
public static Image GetImage() public static Image GetImage()
{ {
IDataObject clipboardData = GetDataObject(); IDataObject clipboardData = GetDataObject();
if (clipboardData == null)
{
return null;
}
// Return the first image // Return the first image
foreach (var clipboardImage in GetImages(clipboardData)) foreach (var clipboardImage in GetImages(clipboardData))
{ {
@ -520,7 +525,7 @@ EndSelection:<<<<<<<4
Bitmap singleImage = GetImage(dataObject); Bitmap singleImage = GetImage(dataObject);
if (singleImage != null) if (singleImage != null)
{ {
Log.InfoFormat($"Got {singleImage.GetType()} from clipboard with size {singleImage.Size}"); Log.Info($"Got {singleImage.GetType()} from clipboard with size {singleImage.Size}");
yield return singleImage; yield return singleImage;
yield break; yield break;
} }

View file

@ -59,7 +59,7 @@ namespace Greenshot.Base.Core
[IniProperty("IEHotkey", Description = "Hotkey for starting the IE capture", DefaultValue = "Shift + Ctrl + PrintScreen")] [IniProperty("IEHotkey", Description = "Hotkey for starting the IE capture", DefaultValue = "Shift + Ctrl + PrintScreen")]
public string IEHotkey { get; set; } public string IEHotkey { get; set; }
[IniProperty("ClipboardHotkey", Description = "Hotkey for opening the clipboard contents into the editor")] [IniProperty("ClipboardHotkey", Description = "Hotkey for opening the clipboard contents into the editor", ExcludeIfNull = true)]
public string ClipboardHotkey { get; set; } public string ClipboardHotkey { get; set; }
[IniProperty("IsFirstLaunch", Description = "Is this the first time launch?", DefaultValue = "true")] [IniProperty("IsFirstLaunch", Description = "Is this the first time launch?", DefaultValue = "true")]
@ -388,89 +388,64 @@ namespace Greenshot.Base.Core
return ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature); return ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature);
} }
private string CreateOutputFilePath()
{
if (IniConfig.IsPortable)
{
string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots");
if (!Directory.Exists(pafOutputFilePath))
{
try
{
Directory.CreateDirectory(pafOutputFilePath);
return pafOutputFilePath;
}
catch (Exception ex)
{
// Problem creating directory, fallback to Desktop
LOG.Warn(ex);
}
}
else
{
return pafOutputFilePath;
}
}
return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
}
/// <summary> /// <summary>
/// Supply values we can't put as defaults /// Supply values we can't put as defaults
/// </summary> /// </summary>
/// <param name="property">The property to return a default for</param> /// <param name="property">The property to return a default for</param>
/// <returns>object with the default value for the supplied property</returns> /// <returns>object with the default value for the supplied property</returns>
public override object GetDefault(string property) public override object GetDefault(string property) =>
{ property switch
switch (property)
{ {
case nameof(ExcludePlugins): nameof(ExcludePlugins) => new List<string>(),
case nameof(IncludePlugins): nameof(IncludePlugins) => new List<string>(),
return new List<string>(); nameof(OutputFileAsFullpath) => IniConfig.IsPortable ? Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png") : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "dummy.png"),
case nameof(OutputFileAsFullpath): nameof(OutputFilePath) => CreateOutputFilePath(),
if (IniConfig.IsPortable) nameof(DWMBackgroundColor) => Color.Transparent,
{ nameof(ActiveTitleFixes) => new List<string> {
return Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png"); "Firefox",
} "IE",
"Chrome"
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "dummy.png"); },
case nameof(OutputFilePath): nameof(TitleFixMatcher) => new Dictionary<string, string> {
if (IniConfig.IsPortable) { "Firefox", " - Mozilla Firefox.*" },
{ { "IE", " - (Microsoft|Windows) Internet Explorer.*" },
string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots"); { "Chrome", " - Google Chrome.*" }
if (!Directory.Exists(pafOutputFilePath)) },
{ nameof(TitleFixReplacer) => new Dictionary<string, string> {
try { "Firefox", string.Empty },
{ { "IE", string.Empty },
Directory.CreateDirectory(pafOutputFilePath); { "Chrome", string.Empty }
return pafOutputFilePath; },
} _ => null
catch (Exception ex) };
{
LOG.Warn(ex);
// Problem creating directory, fallback to Desktop
}
}
else
{
return pafOutputFilePath;
}
}
return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
case nameof(DWMBackgroundColor):
return Color.Transparent;
case nameof(ActiveTitleFixes):
return new List<string>
{
"Firefox",
"IE",
"Chrome"
};
case nameof(TitleFixMatcher):
return new Dictionary<string, string>
{
{
"Firefox", " - Mozilla Firefox.*"
},
{
"IE", " - (Microsoft|Windows) Internet Explorer.*"
},
{
"Chrome", " - Google Chrome.*"
}
};
case nameof(TitleFixReplacer):
return new Dictionary<string, string>
{
{
"Firefox", string.Empty
},
{
"IE", string.Empty
},
{
"Chrome", string.Empty
}
};
}
return null;
}
/// <summary> /// <summary>
/// This method will be called before converting the property, making to possible to correct a certain value /// This method will be called before converting the property, making to possible to correct a certain value
/// Can be used when migration is needed /// Can be used when migration is needed
@ -540,8 +515,9 @@ namespace Greenshot.Base.Core
OutputFileAutoReduceColors = false; OutputFileAutoReduceColors = false;
} }
bool isUpgradeFrom12 = LastSaveWithVersion?.StartsWith("1.2") ?? false;
// Fix for excessive feed checking // Fix for excessive feed checking
if (UpdateCheckInterval != 0 && UpdateCheckInterval <= 7 && LastSaveWithVersion.StartsWith("1.2")) if (UpdateCheckInterval != 0 && UpdateCheckInterval <= 7 && isUpgradeFrom12)
{ {
UpdateCheckInterval = 14; UpdateCheckInterval = 14;
} }

View file

@ -24,6 +24,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using Dapplo.Windows.Icons; using Dapplo.Windows.Icons;
using Greenshot.Base.IniFile; using Greenshot.Base.IniFile;
@ -39,9 +40,9 @@ namespace Greenshot.Base.Core
{ {
private static readonly ILog Log = LogManager.GetLogger(typeof(PluginUtils)); private static readonly ILog Log = LogManager.GetLogger(typeof(PluginUtils));
private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>(); private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection<CoreConfiguration>();
private const string PathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
private static readonly IDictionary<string, Image> ExeIconCache = new Dictionary<string, Image>(); private static readonly IDictionary<string, Image> ExeIconCache = new Dictionary<string, Image>();
private const string PathKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
static PluginUtils() static PluginUtils()
{ {
CoreConfig.PropertyChanged += OnIconSizeChanged; CoreConfig.PropertyChanged += OnIconSizeChanged;
@ -84,7 +85,7 @@ namespace Greenshot.Base.Core
if (key != null) if (key != null)
{ {
// "" is the default key, which should point to the requested location // "" is the default key, which should point to the requested location
return (string) key.GetValue(string.Empty); return (string)key.GetValue(string.Empty);
} }
} }

View file

@ -42,8 +42,6 @@ namespace Greenshot.Base.Core
{ {
private const string AppWindowClass = "Windows.UI.Core.CoreWindow"; //Used for Windows 8(.1) private const string AppWindowClass = "Windows.UI.Core.CoreWindow"; //Used for Windows 8(.1)
private const string AppFrameWindowClass = "ApplicationFrameWindow"; // Windows 10 uses ApplicationFrameWindow private const string AppFrameWindowClass = "ApplicationFrameWindow"; // Windows 10 uses ApplicationFrameWindow
private const string ApplauncherClass = "ImmersiveLauncher";
private const string GutterClass = "ImmersiveGutter";
private static readonly IList<string> IgnoreClasses = new List<string>(new[] private static readonly IList<string> IgnoreClasses = new List<string>(new[]
{ {
@ -89,13 +87,7 @@ namespace Greenshot.Base.Core
private IntPtr _parentHandle = IntPtr.Zero; private IntPtr _parentHandle = IntPtr.Zero;
private WindowDetails _parent; private WindowDetails _parent;
private bool _frozen; private bool _frozen;
/// <summary>
/// This checks if the window is a Windows 8 App
/// For Windows 10 most normal code works, as it's hosted inside "ApplicationFrameWindow"
/// </summary>
public bool IsApp => AppWindowClass.Equals(ClassName);
/// <summary> /// <summary>
/// This checks if the window is a Windows 10 App /// This checks if the window is a Windows 10 App
/// For Windows 10 apps are hosted inside "ApplicationFrameWindow" /// For Windows 10 apps are hosted inside "ApplicationFrameWindow"
@ -108,20 +100,6 @@ namespace Greenshot.Base.Core
public bool IsBackgroundWin10App => WindowsVersion.IsWindows10OrLater && AppFrameWindowClass.Equals(ClassName) && public bool IsBackgroundWin10App => WindowsVersion.IsWindows10OrLater && AppFrameWindowClass.Equals(ClassName) &&
!Children.Any(window => string.Equals(window.ClassName, AppWindowClass)); !Children.Any(window => string.Equals(window.ClassName, AppWindowClass));
/// <summary>
/// Check if the window is the metro gutter (sizeable separator)
/// </summary>
public bool IsGutter => GutterClass.Equals(ClassName);
/// <summary>
/// Test if this window is for the App-Launcher
/// </summary>
public bool IsAppLauncher => ApplauncherClass.Equals(ClassName);
/// <summary>
/// Check if this window is the window of a metro app
/// </summary>
public bool IsMetroApp => IsAppLauncher || IsApp;
/// <summary> /// <summary>
/// To allow items to be compared, the hash code /// To allow items to be compared, the hash code
@ -226,12 +204,6 @@ namespace Greenshot.Base.Core
Log.Warn(ex); Log.Warn(ex);
} }
if (IsMetroApp)
{
// No method yet to get the metro icon
return null;
}
try try
{ {
return PluginUtils.GetCachedExeIcon(ProcessPath, 0); return PluginUtils.GetCachedExeIcon(ProcessPath, 0);
@ -467,11 +439,6 @@ namespace Greenshot.Base.Core
{ {
get get
{ {
if (IsMetroApp)
{
return !Visible;
}
return User32Api.IsIconic(Handle) || Location.X <= -32000; return User32Api.IsIconic(Handle) || Location.X <= -32000;
} }
set set
@ -494,22 +461,6 @@ namespace Greenshot.Base.Core
{ {
get get
{ {
if (IsApp)
{
if (Visible)
{
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
{
if (WindowRectangle.Equals(displayInfo.Bounds))
{
return true;
}
}
}
return false;
}
return User32Api.IsZoomed(Handle); return User32Api.IsZoomed(Handle);
} }
set set
@ -546,50 +497,6 @@ namespace Greenshot.Base.Core
return false; return false;
} }
if (IsApp)
{
var windowRectangle = WindowRectangle;
foreach (var displayInfo in DisplayInfo.AllDisplayInfos)
{
if (!displayInfo.Bounds.Contains(windowRectangle)) continue;
if (windowRectangle.Equals(displayInfo.Bounds))
{
// Fullscreen, it's "visible" when AppVisibilityOnMonitor says yes
// Although it might be the other App, this is not "very" important
NativeRect rect = displayInfo.Bounds;
IntPtr monitor = User32Api.MonitorFromRect(ref rect, MonitorFrom.DefaultToNull);
if (monitor != IntPtr.Zero)
{
MONITOR_APP_VISIBILITY? monitorAppVisibility = AppVisibility?.GetAppVisibilityOnMonitor(monitor);
//LOG.DebugFormat("App {0} visible: {1} on {2}", Text, monitorAppVisibility, screen.Bounds);
if (monitorAppVisibility == MONITOR_APP_VISIBILITY.MAV_APP_VISIBLE)
{
return true;
}
}
}
else
{
// Is only partly on the screen, when this happens the app is always visible!
return true;
}
}
return false;
}
if (IsGutter)
{
// gutter is only made available when it's visible
return true;
}
if (IsAppLauncher)
{
return IsAppLauncherVisible;
}
return User32Api.IsWindowVisible(Handle); return User32Api.IsWindowVisible(Handle);
} }
} }
@ -643,69 +550,56 @@ namespace Greenshot.Base.Core
{ {
// Try to return a cached value // Try to return a cached value
long now = DateTime.Now.Ticks; long now = DateTime.Now.Ticks;
if (_previousWindowRectangle.IsEmpty || !_frozen) if (!_previousWindowRectangle.IsEmpty && _frozen) return _previousWindowRectangle;
{
if (!_previousWindowRectangle.IsEmpty && now - _lastWindowRectangleRetrieveTime <= CacheTime)
{
return _previousWindowRectangle;
}
NativeRect windowRect = new();
if (DwmApi.IsDwmEnabled)
{
bool gotFrameBounds = GetExtendedFrameBounds(out windowRect);
if (IsApp)
{
// Pre-Cache for maximized call, this is only on Windows 8 apps (full screen)
if (gotFrameBounds)
{
_previousWindowRectangle = windowRect;
_lastWindowRectangleRetrieveTime = now;
}
}
if (gotFrameBounds && WindowsVersion.IsWindows10OrLater && !Maximised) if (!_previousWindowRectangle.IsEmpty && now - _lastWindowRectangleRetrieveTime <= CacheTime)
{
return _previousWindowRectangle;
}
NativeRect windowRect = new();
if (DwmApi.IsDwmEnabled)
{
bool gotFrameBounds = GetExtendedFrameBounds(out windowRect);
if (IsWin10App)
{
// Pre-Cache for maximized call, this is only on Windows 8 apps (full screen)
if (gotFrameBounds)
{ {
// Somehow DWM doesn't calculate it correctly, there is a 1 pixel border around the capture
// Remove this border, currently it's fixed but TODO: Make it depend on the OS?
windowRect = windowRect.Inflate(Conf.Win10BorderCrop);
_previousWindowRectangle = windowRect; _previousWindowRectangle = windowRect;
_lastWindowRectangleRetrieveTime = now; _lastWindowRectangleRetrieveTime = now;
return windowRect;
} }
} }
if (windowRect.IsEmpty) if (gotFrameBounds && WindowsVersion.IsWindows10OrLater && !Maximised)
{ {
if (!GetWindowRect(out windowRect)) // Somehow DWM doesn't calculate it correctly, there is a 1 pixel border around the capture
{ // Remove this border, currently it's fixed but TODO: Make it depend on the OS?
Win32Error error = Win32.GetLastErrorCode(); windowRect = windowRect.Inflate(Conf.Win10BorderCrop);
Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error)); _previousWindowRectangle = windowRect;
} _lastWindowRectangleRetrieveTime = now;
return windowRect;
} }
// Correction for maximized windows, only if it's not an app
if (!HasParent && !IsApp && Maximised)
{
// Only if the border size can be retrieved
if (GetBorderSize(out var size))
{
windowRect = new NativeRect(windowRect.X + size.Width, windowRect.Y + size.Height, windowRect.Width - (2 * size.Width),
windowRect.Height - (2 * size.Height));
}
}
_lastWindowRectangleRetrieveTime = now;
// Try to return something valid, by getting returning the previous size if the window doesn't have a NativeRect anymore
if (windowRect.IsEmpty)
{
return _previousWindowRectangle;
}
_previousWindowRectangle = windowRect;
return windowRect;
} }
return _previousWindowRectangle; if (windowRect.IsEmpty)
{
if (!GetWindowRect(out windowRect))
{
Win32Error error = Win32.GetLastErrorCode();
Log.WarnFormat("Couldn't retrieve the windows rectangle: {0}", Win32.GetMessage(error));
}
}
_lastWindowRectangleRetrieveTime = now;
// Try to return something valid, by getting returning the previous size if the window doesn't have a NativeRect anymore
if (windowRect.IsEmpty)
{
return _previousWindowRectangle;
}
_previousWindowRectangle = windowRect;
return windowRect;
} }
} }
@ -928,7 +822,7 @@ namespace Greenshot.Base.Core
{ {
// if GDI is allowed.. (a screenshot won't be better than we comes if we continue) // if GDI is allowed.. (a screenshot won't be better than we comes if we continue)
using Process thisWindowProcess = Process; using Process thisWindowProcess = Process;
if (!IsMetroApp && WindowCapture.IsGdiAllowed(thisWindowProcess)) if (WindowCapture.IsGdiAllowed(thisWindowProcess))
{ {
// we return null which causes the capturing code to try another method. // we return null which causes the capturing code to try another method.
return null; return null;
@ -973,11 +867,8 @@ namespace Greenshot.Base.Core
tempForm.BackColor = Color.Black; tempForm.BackColor = Color.Black;
// Make sure everything is visible // Make sure everything is visible
tempForm.Refresh(); tempForm.Refresh();
if (!IsMetroApp) // Make sure the application window is active, so the colors & buttons are right
{ ToForeground();
// Make sure the application window is active, so the colors & buttons are right
ToForeground();
}
// Make sure all changes are processed and visible // Make sure all changes are processed and visible
Application.DoEvents(); Application.DoEvents();
@ -1013,11 +904,8 @@ namespace Greenshot.Base.Core
// Make sure everything is visible // Make sure everything is visible
tempForm.Refresh(); tempForm.Refresh();
if (!IsMetroApp) // Make sure the application window is active, so the colors & buttons are right
{ ToForeground();
// Make sure the application window is active, so the colors & buttons are right
ToForeground();
}
// Make sure all changes are processed and visible // Make sure all changes are processed and visible
Application.DoEvents(); Application.DoEvents();
@ -1154,6 +1042,13 @@ namespace Greenshot.Base.Core
return targetBuffer.UnlockAndReturnBitmap(); return targetBuffer.UnlockAndReturnBitmap();
} }
/// <summary>
/// If a window is hidden (Iconic), it also has the specified dimensions.
/// </summary>
/// <param name="rect">NativeRect</param>
/// <returns>bool true if hidden</returns>
private bool IsHidden(NativeRect rect) => rect.Width == 65535 && rect.Height == 65535 && rect.Left == 32767 && rect.Top == 32767;
/// <summary> /// <summary>
/// Helper method to get the window size for DWM Windows /// Helper method to get the window size for DWM Windows
/// </summary> /// </summary>
@ -1164,6 +1059,10 @@ namespace Greenshot.Base.Core
var result = DwmApi.DwmGetWindowAttribute(Handle, DwmWindowAttributes.ExtendedFrameBounds, out NativeRect rect, Marshal.SizeOf(typeof(NativeRect))); var result = DwmApi.DwmGetWindowAttribute(Handle, DwmWindowAttributes.ExtendedFrameBounds, out NativeRect rect, Marshal.SizeOf(typeof(NativeRect)));
if (result.Succeeded()) if (result.Succeeded())
{ {
if (IsHidden(rect))
{
rect = NativeRect.Empty;
}
rectangle = rect; rectangle = rect;
return true; return true;
} }
@ -1196,7 +1095,14 @@ namespace Greenshot.Base.Core
var windowInfo = new WindowInfo(); var windowInfo = new WindowInfo();
// Get the Window Info for this window // Get the Window Info for this window
bool result = User32Api.GetWindowInfo(Handle, ref windowInfo); bool result = User32Api.GetWindowInfo(Handle, ref windowInfo);
rectangle = result ? windowInfo.Bounds : NativeRect.Empty; if (IsHidden(windowInfo.Bounds))
{
rectangle = NativeRect.Empty;
}
else
{
rectangle = result ? windowInfo.Bounds : NativeRect.Empty;
}
return result; return result;
} }
@ -1577,7 +1483,7 @@ namespace Greenshot.Base.Core
// Skip everything which is not rendered "normally", trying to fix BUG-2017 // Skip everything which is not rendered "normally", trying to fix BUG-2017
var exWindowStyle = window.ExtendedWindowStyle; var exWindowStyle = window.ExtendedWindowStyle;
if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) if (!window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0)
{ {
return false; return false;
} }
@ -1592,13 +1498,6 @@ namespace Greenshot.Base.Core
public static IEnumerable<WindowDetails> GetVisibleWindows() public static IEnumerable<WindowDetails> GetVisibleWindows()
{ {
var screenBounds = DisplayInfo.ScreenBounds; var screenBounds = DisplayInfo.ScreenBounds;
foreach (var window in GetAppWindows())
{
if (IsVisible(window, screenBounds))
{
yield return window;
}
}
foreach (var window in GetAllWindows()) foreach (var window in GetAllWindows())
{ {
@ -1609,38 +1508,6 @@ namespace Greenshot.Base.Core
} }
} }
/// <summary>
/// Get the WindowDetails for all Metro Apps
/// These are all Windows with Classname "Windows.UI.Core.CoreWindow"
/// </summary>
/// <returns>List WindowDetails with visible metro apps</returns>
public static IEnumerable<WindowDetails> GetAppWindows()
{
// if the appVisibility != null we have Windows 8.
if (AppVisibility == null)
{
yield break;
}
var nextHandle = User32Api.FindWindow(AppWindowClass, null);
while (nextHandle != IntPtr.Zero)
{
var metroApp = new WindowDetails(nextHandle);
yield return metroApp;
// Check if we have a gutter!
if (metroApp.Visible && !metroApp.Maximised)
{
var gutterHandle = User32Api.FindWindow(GutterClass, null);
if (gutterHandle != IntPtr.Zero)
{
yield return new WindowDetails(gutterHandle);
}
}
nextHandle = User32Api.FindWindowEx(IntPtr.Zero, nextHandle, AppWindowClass, null);
}
}
/// <summary> /// <summary>
/// Check if the window is a top level /// Check if the window is a top level
/// </summary> /// </summary>
@ -1671,7 +1538,7 @@ namespace Greenshot.Base.Core
} }
// Skip everything which is not rendered "normally", trying to fix BUG-2017 // Skip everything which is not rendered "normally", trying to fix BUG-2017
if (!window.IsApp && !window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0) if (!window.IsWin10App && (exWindowStyle & ExtendedWindowStyleFlags.WS_EX_NOREDIRECTIONBITMAP) != 0)
{ {
return false; return false;
} }
@ -1707,14 +1574,6 @@ namespace Greenshot.Base.Core
/// <returns>List WindowDetails with all the top level windows</returns> /// <returns>List WindowDetails with all the top level windows</returns>
public static IEnumerable<WindowDetails> GetTopLevelWindows() public static IEnumerable<WindowDetails> GetTopLevelWindows()
{ {
foreach (var possibleTopLevel in GetAppWindows())
{
if (IsTopLevel(possibleTopLevel))
{
yield return possibleTopLevel;
}
}
foreach (var possibleTopLevel in GetAllWindows()) foreach (var possibleTopLevel in GetAllWindows())
{ {
if (IsTopLevel(possibleTopLevel)) if (IsTopLevel(possibleTopLevel))
@ -1790,27 +1649,6 @@ namespace Greenshot.Base.Core
} }
} }
/// <summary>
/// Get the AppLauncher
/// </summary>
/// <returns></returns>
public static WindowDetails GetAppLauncher()
{
// Only if Windows 8 (or higher)
if (AppVisibility == null)
{
return null;
}
IntPtr appLauncher = User32Api.FindWindow(ApplauncherClass, null);
if (appLauncher != IntPtr.Zero)
{
return new WindowDetails(appLauncher);
}
return null;
}
/// <summary> /// <summary>
/// Return true if the metro-app-launcher is visible /// Return true if the metro-app-launcher is visible
/// </summary> /// </summary>
@ -1842,7 +1680,6 @@ namespace Greenshot.Base.Core
result.AppendLine($"Size: {WindowRectangle.Size}"); result.AppendLine($"Size: {WindowRectangle.Size}");
result.AppendLine($"HasParent: {HasParent}"); result.AppendLine($"HasParent: {HasParent}");
result.AppendLine($"IsWin10App: {IsWin10App}"); result.AppendLine($"IsWin10App: {IsWin10App}");
result.AppendLine($"IsApp: {IsApp}");
result.AppendLine($"Visible: {Visible}"); result.AppendLine($"Visible: {Visible}");
result.AppendLine($"IsWindowVisible: {User32Api.IsWindowVisible(Handle)}"); result.AppendLine($"IsWindowVisible: {User32Api.IsWindowVisible(Handle)}");
result.AppendLine($"IsCloaked: {IsCloaked}"); result.AppendLine($"IsCloaked: {IsCloaked}");

View file

@ -5,16 +5,16 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Dapplo.HttpExtensions.JsonNet" Version="1.0.18" /> <PackageReference Include="Dapplo.HttpExtensions.JsonNet" Version="1.1.2" />
<PackageReference Include="Dapplo.Windows.Clipboard" Version="1.0.25" /> <PackageReference Include="Dapplo.Windows.Clipboard" Version="1.0.28" />
<PackageReference Include="Dapplo.Windows.Dpi" Version="1.0.25" /> <PackageReference Include="Dapplo.Windows.Dpi" Version="1.0.28" />
<PackageReference Include="Dapplo.Windows.Gdi32" Version="1.0.25" /> <PackageReference Include="Dapplo.Windows.Gdi32" Version="1.0.28" />
<PackageReference Include="Dapplo.Windows.Icons" Version="1.0.25" /> <PackageReference Include="Dapplo.Windows.Icons" Version="1.0.28" />
<PackageReference Include="Dapplo.Windows.Kernel32" Version="1.0.25" /> <PackageReference Include="Dapplo.Windows.Kernel32" Version="1.0.28" />
<PackageReference Include="Dapplo.Windows.Multimedia" Version="1.0.25" /> <PackageReference Include="Dapplo.Windows.Multimedia" Version="1.0.28" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.42" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
<PackageReference Include="log4net" version="2.0.14" /> <PackageReference Include="log4net" version="2.0.15" />
<PackageReference Include="Svg" Version="3.4.2" /> <PackageReference Include="Svg" Version="3.4.3" />
<Reference Include="Accessibility" /> <Reference Include="Accessibility" />
<Reference Include="CustomMarshalers" /> <Reference Include="CustomMarshalers" />
</ItemGroup> </ItemGroup>

View file

@ -103,7 +103,7 @@ namespace Greenshot.Editor.Drawing.Adorners
var scaleOptions = (Owner as IHaveScaleOptions)?.GetScaleOptions(); var scaleOptions = (Owner as IHaveScaleOptions)?.GetScaleOptions();
// calculate scaled rectangle // calculate scaled rectangle
_boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Position, new PointF(mouseEventArgs.X, mouseEventArgs.Y), scaleOptions); _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Position, new NativePointFloat(mouseEventArgs.X, mouseEventArgs.Y), scaleOptions);
// apply scaled bounds to this DrawableContainer // apply scaled bounds to this DrawableContainer
Owner.ApplyBounds(_boundsAfterResize); Owner.ApplyBounds(_boundsAfterResize);

View file

@ -247,10 +247,11 @@ namespace Greenshot.Editor.Drawing
_boundsAfterResize = new NativeRectFloat( _boundsAfterResize = new NativeRectFloat(
_boundsBeforeResize.Left, _boundsBeforeResize.Top, _boundsBeforeResize.Left, _boundsBeforeResize.Top,
x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); x - _boundsAfterResize.Left, y - _boundsAfterResize.Top);
_boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y, GetAngleRoundProcessor());
break; break;
} }
} }
_boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, Positions.TopLeft, x, y, GetAngleRoundProcessor());
// apply scaled bounds to this DrawableContainer // apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize); ApplyBounds(_boundsAfterResize);

View file

@ -534,7 +534,7 @@ namespace Greenshot.Editor.Drawing
_boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); _boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top);
var scaleOptions = (this as IHaveScaleOptions)?.GetScaleOptions(); var scaleOptions = (this as IHaveScaleOptions)?.GetScaleOptions();
_boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Positions.TopLeft, x, y,GetAngleRoundProcessor(), scaleOptions); _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y,GetAngleRoundProcessor(), scaleOptions);
// apply scaled bounds to this DrawableContainer // apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize); ApplyBounds(_boundsAfterResize);
@ -667,9 +667,9 @@ namespace Greenshot.Editor.Drawing
Height = points[1].Y - points[0].Y; Height = points[1].Y - points[0].Y;
} }
protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() protected virtual IDoubleProcessor GetAngleRoundProcessor()
{ {
return ScaleHelper.ShapeAngleRoundBehavior.INSTANCE; return ShapeAngleRoundBehavior.INSTANCE;
} }
public virtual bool HasContextMenu => true; public virtual bool HasContextMenu => true;

View file

@ -166,9 +166,9 @@ namespace Greenshot.Editor.Drawing
return image; return image;
} }
public ScaleHelper.ScaleOptions GetScaleOptions() public ScaleOptions GetScaleOptions()
{ {
return ScaleHelper.ScaleOptions.Rational; return ScaleOptions.Rational;
} }
} }
} }

View file

@ -115,9 +115,9 @@ namespace Greenshot.Editor.Drawing
return false; return false;
} }
protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() protected override IDoubleProcessor GetAngleRoundProcessor()
{ {
return ScaleHelper.LineAngleRoundBehavior.INSTANCE; return LineAngleRoundBehavior.INSTANCE;
} }
} }
} }

View file

@ -100,8 +100,7 @@ namespace Greenshot.Editor.FileFormatHandlers
bitmap = new Bitmap(infoHeader.Width, infoHeader.Height, bitmap = new Bitmap(infoHeader.Width, infoHeader.Height,
-(int)(infoHeader.SizeImage / infoHeader.Height), -(int)(infoHeader.SizeImage / infoHeader.Height),
infoHeader.BitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb, infoHeader.BitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels + IntPtr.Add(handle.AddrOfPinnedObject(), (int)infoHeader.OffsetToPixels + (infoHeader.Height - 1) * (int)(infoHeader.SizeImage / infoHeader.Height))
(infoHeader.Height - 1) * (int)(infoHeader.SizeImage / infoHeader.Height))
); );
} }
catch (Exception ex) catch (Exception ex)

View file

@ -0,0 +1,28 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Greenshot.Editor.Helpers
{
public interface IDoubleProcessor
{
double Process(double d);
}
}

View file

@ -23,6 +23,6 @@ namespace Greenshot.Editor.Helpers
{ {
public interface IHaveScaleOptions public interface IHaveScaleOptions
{ {
ScaleHelper.ScaleOptions GetScaleOptions(); ScaleOptions GetScaleOptions();
} }
} }

View file

@ -0,0 +1,39 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Editor.Helpers
{
public class LineAngleRoundBehavior : IDoubleProcessor
{
public static readonly LineAngleRoundBehavior INSTANCE = new();
private LineAngleRoundBehavior()
{
}
public double Process(double angle)
{
return Math.Round(angle / 15) * 15;
}
}
}

View file

@ -33,26 +33,7 @@ namespace Greenshot.Editor.Helpers
/// </summary> /// </summary>
public static class ScaleHelper public static class ScaleHelper
{ {
[Flags]
public enum ScaleOptions
{
/// <summary> /// <summary>
/// Default scale behavior.
/// </summary>
Default = 0x00,
/// <summary>
/// Scale a rectangle in two our four directions, mirrored at it's center coordinates
/// </summary>
Centered = 0x01,
/// <summary>
/// Scale a rectangle maintaining it's aspect ratio
/// </summary>
Rational = 0x02
}
/// <summary>
/// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio /// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio
/// </summary> /// </summary>
/// <param name="currentSize">the size of the element to be resized</param> /// <param name="currentSize">the size of the element to be resized</param>
@ -231,16 +212,14 @@ namespace Greenshot.Editor.Helpers
/// Scale the boundsBeforeResize with the specified position and new location, using the angle angleRoundBehavior /// Scale the boundsBeforeResize with the specified position and new location, using the angle angleRoundBehavior
/// </summary> /// </summary>
/// <param name="boundsBeforeResize">NativeRect</param> /// <param name="boundsBeforeResize">NativeRect</param>
/// <param name="gripperPosition">Positions</param>
/// <param name="cursorX">int</param> /// <param name="cursorX">int</param>
/// <param name="cursorY">int</param> /// <param name="cursorY">int</param>
/// <param name="angleRoundBehavior">IDoubleProcessor</param> /// <param name="angleRoundBehavior">IDoubleProcessor</param>
/// <param name="options">ScaleOptionsProcessor</param> /// <param name="options">ScaleOptionsProcessor</param>
/// <returns>NativeRectFloat</returns> /// <returns>NativeRectFloat</returns>
public static NativeRectFloat Scale(NativeRect boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? options = null) public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? options = null)
{ {
options ??= GetScaleOptions(); options ??= GetScaleOptions();
NativeRectFloat result = boundsBeforeResize; NativeRectFloat result = boundsBeforeResize;
bool rationalScale = (options & ScaleOptions.Rational) == ScaleOptions.Rational; bool rationalScale = (options & ScaleOptions.Rational) == ScaleOptions.Rational;
bool centeredScale = (options & ScaleOptions.Centered) == ScaleOptions.Centered; bool centeredScale = (options & ScaleOptions.Centered) == ScaleOptions.Centered;
@ -281,38 +260,5 @@ namespace Greenshot.Editor.Helpers
if (maintainAspectRatio) opts |= ScaleOptions.Rational; if (maintainAspectRatio) opts |= ScaleOptions.Rational;
return opts; return opts;
} }
public interface IDoubleProcessor
{
double Process(double d);
} }
public class ShapeAngleRoundBehavior : IDoubleProcessor
{
public static readonly ShapeAngleRoundBehavior INSTANCE = new();
private ShapeAngleRoundBehavior()
{
}
public double Process(double angle)
{
return Math.Round((angle + 45) / 90) * 90 - 45;
}
}
public class LineAngleRoundBehavior : IDoubleProcessor
{
public static readonly LineAngleRoundBehavior INSTANCE = new();
private LineAngleRoundBehavior()
{
}
public double Process(double angle)
{
return Math.Round(angle / 15) * 15;
}
}
}
} }

View file

@ -0,0 +1,44 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Editor.Helpers
{
[Flags]
public enum ScaleOptions
{
/// <summary>
/// Default scale behavior.
/// </summary>
Default = 0x00,
/// <summary>
/// Scale a rectangle in two our four directions, mirrored at it's center coordinates
/// </summary>
Centered = 0x01,
/// <summary>
/// Scale a rectangle maintaining it's aspect ratio
/// </summary>
Rational = 0x02
}
}

View file

@ -0,0 +1,39 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: https://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Editor.Helpers
{
public class ShapeAngleRoundBehavior : IDoubleProcessor
{
public static readonly ShapeAngleRoundBehavior INSTANCE = new();
private ShapeAngleRoundBehavior()
{
}
public double Process(double angle)
{
return Math.Round((angle + 45) / 90) * 90 - 45;
}
}
}

View file

@ -21,6 +21,7 @@
using System; using System;
using System.Windows.Forms; using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums; using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile; using Greenshot.Base.IniFile;
using Greenshot.Plugin.Box.Forms; using Greenshot.Plugin.Box.Forms;
@ -75,5 +76,20 @@ namespace Greenshot.Plugin.Box
return false; return false;
} }
/// <summary>
/// Upgrade certain values
/// </summary>
public override void AfterLoad()
{
var coreConfiguration = IniConfig.GetIniSection<CoreConfiguration>();
bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false;
// Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421
if (!isUpgradeFrom12) return;
// We have an upgrade, remove all previous credentials.
RefreshToken = null;
AccessToken = null;
}
} }
} }

View file

@ -21,6 +21,7 @@
using System; using System;
using System.Windows.Forms; using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums; using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile; using Greenshot.Base.IniFile;
using Greenshot.Plugin.Dropbox.Forms; using Greenshot.Plugin.Dropbox.Forms;
@ -69,5 +70,20 @@ namespace Greenshot.Plugin.Dropbox
return false; return false;
} }
/// <summary>
/// Upgrade certain values
/// </summary>
public override void AfterLoad()
{
var coreConfiguration = IniConfig.GetIniSection<CoreConfiguration>();
bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false;
// Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421
if (!isUpgradeFrom12) return;
// We have an upgrade, remove all previous credentials.
RefreshToken = null;
AccessToken = null;
}
} }
} }

View file

@ -20,6 +20,7 @@
*/ */
using System.Windows.Forms; using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums; using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile; using Greenshot.Base.IniFile;
using Greenshot.Plugin.Flickr.Forms; using Greenshot.Plugin.Flickr.Forms;
@ -86,5 +87,21 @@ namespace Greenshot.Plugin.Flickr
return false; return false;
} }
/// <summary>
/// Upgrade certain values
/// </summary>
public override void AfterLoad()
{
var coreConfiguration = IniConfig.GetIniSection<CoreConfiguration>();
bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false;
// Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421
if (!isUpgradeFrom12) return;
// We have an upgrade, remove all previous credentials.
FlickrToken = null;
FlickrTokenSecret = null;
}
} }
} }

View file

@ -22,6 +22,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using Greenshot.Base.Core;
using Greenshot.Base.Core.Enums; using Greenshot.Base.Core.Enums;
using Greenshot.Base.IniFile; using Greenshot.Base.IniFile;
using Greenshot.Plugin.Imgur.Forms; using Greenshot.Plugin.Imgur.Forms;
@ -84,6 +85,22 @@ namespace Greenshot.Plugin.Imgur
public Dictionary<string, ImgurInfo> runtimeImgurHistory = new Dictionary<string, ImgurInfo>(); public Dictionary<string, ImgurInfo> runtimeImgurHistory = new Dictionary<string, ImgurInfo>();
public int Credits { get; set; } public int Credits { get; set; }
/// <summary>
/// Upgrade certain values
/// </summary>
public override void AfterLoad()
{
var coreConfiguration = IniConfig.GetIniSection<CoreConfiguration>();
bool isUpgradeFrom12 = coreConfiguration.LastSaveWithVersion?.StartsWith("1.2") ?? false;
// Clear token when we upgrade from 1.2 to 1.3 as it is no longer valid, discussed in #421
if (!isUpgradeFrom12) return;
// We have an upgrade, remove all previous credentials.
AccessToken = null;
RefreshToken = null;
AccessTokenExpires = default;
}
/// <summary> /// <summary>
/// Supply values we can't put as defaults /// Supply values we can't put as defaults
/// </summary> /// </summary>
@ -92,7 +109,7 @@ namespace Greenshot.Plugin.Imgur
public override object GetDefault(string property) => public override object GetDefault(string property) =>
property switch property switch
{ {
"ImgurUploadHistory" => new Dictionary<string, string>(), nameof(ImgurUploadHistory) => new Dictionary<string, string>(),
_ => null _ => null
}; };

View file

@ -6,7 +6,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Greenshot.Base\Greenshot.Base.csproj" /> <ProjectReference Include="..\Greenshot.Base\Greenshot.Base.csproj" />
<PackageReference Include="Dapplo.Jira" version="1.1.44" /> <PackageReference Include="Dapplo.Jira" version="1.1.46" />
<PackageReference Include="Dapplo.Jira.SvgWinForms" Version="1.1.44" /> <PackageReference Include="Dapplo.Jira.SvgWinForms" Version="1.1.46" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -42,7 +42,8 @@ namespace Greenshot.Plugin.Office.Destinations
static ExcelDestination() static ExcelDestination()
{ {
ExePath = PluginUtils.GetExePath("EXCEL.EXE"); ExePath = OfficeUtils.GetOfficeExePath("EXCEL.EXE") ?? PluginUtils.GetExePath("EXCEL.EXE");
if (ExePath != null && File.Exists(ExePath)) if (ExePath != null && File.Exists(ExePath))
{ {
WindowDetails.AddProcessToExcludeFromFreeze("excel"); WindowDetails.AddProcessToExcludeFromFreeze("excel");

View file

@ -41,7 +41,7 @@ namespace Greenshot.Plugin.Office.Destinations
static OneNoteDestination() static OneNoteDestination()
{ {
exePath = PluginUtils.GetExePath("ONENOTE.EXE"); exePath = OfficeUtils.GetOfficeExePath("ONENOTE.EXE") ?? PluginUtils.GetExePath("ONENOTE.EXE");
if (exePath != null && File.Exists(exePath)) if (exePath != null && File.Exists(exePath))
{ {
WindowDetails.AddProcessToExcludeFromFreeze("onenote"); WindowDetails.AddProcessToExcludeFromFreeze("onenote");

View file

@ -58,8 +58,7 @@ namespace Greenshot.Plugin.Office.Destinations
{ {
IsActiveFlag = true; IsActiveFlag = true;
} }
ExePath = OfficeUtils.GetOfficeExePath("OUTLOOK.EXE") ?? PluginUtils.GetExePath("OUTLOOK.EXE");
ExePath = PluginUtils.GetExePath("OUTLOOK.EXE");
if (ExePath != null && File.Exists(ExePath)) if (ExePath != null && File.Exists(ExePath))
{ {
WindowDetails.AddProcessToExcludeFromFreeze("outlook"); WindowDetails.AddProcessToExcludeFromFreeze("outlook");

View file

@ -45,7 +45,7 @@ namespace Greenshot.Plugin.Office.Destinations
static PowerpointDestination() static PowerpointDestination()
{ {
ExePath = PluginUtils.GetExePath("POWERPNT.EXE"); ExePath = OfficeUtils.GetOfficeExePath("POWERPNT.EXE") ?? PluginUtils.GetExePath("POWERPNT.EXE");
if (ExePath != null && File.Exists(ExePath)) if (ExePath != null && File.Exists(ExePath))
{ {
WindowDetails.AddProcessToExcludeFromFreeze("powerpnt"); WindowDetails.AddProcessToExcludeFromFreeze("powerpnt");

View file

@ -46,7 +46,7 @@ namespace Greenshot.Plugin.Office.Destinations
static WordDestination() static WordDestination()
{ {
ExePath = PluginUtils.GetExePath("WINWORD.EXE"); ExePath = OfficeUtils.GetOfficeExePath("WINWORD.EXE") ?? PluginUtils.GetExePath("WINWORD.EXE");
if (ExePath != null && !File.Exists(ExePath)) if (ExePath != null && !File.Exists(ExePath))
{ {
ExePath = null; ExePath = null;
@ -118,7 +118,7 @@ namespace Greenshot.Plugin.Office.Destinations
if (!manuallyInitiated) if (!manuallyInitiated)
{ {
var documents = _wordExporter.GetWordDocuments().ToList(); var documents = _wordExporter.GetWordDocuments().ToList();
if (documents != null && documents.Count > 0) if (documents is { Count: > 0 })
{ {
var destinations = new List<IDestination> var destinations = new List<IDestination>
{ {

View file

@ -78,23 +78,23 @@
</ItemGroup> </ItemGroup>
</Target> </Target>
<ItemGroup> <ItemGroup>
<PackageReference Include="Interop.Microsoft.Office.Interop.OneNote" Version="1.1.0"> <PackageReference Include="Interop.Microsoft.Office.Interop.OneNote" Version="1.1.0.2">
<EmbedInteropTypes>true</EmbedInteropTypes> <EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets> <ExcludeAssets>runtime</ExcludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Office.Interop.Excel" Version="15.0.4795.1000"> <PackageReference Include="Microsoft.Office.Interop.Excel" Version="15.0.4795.1001">
<EmbedInteropTypes>true</EmbedInteropTypes> <EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets> <ExcludeAssets>runtime</ExcludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Office.Interop.Outlook" Version="15.0.4797.1003"> <PackageReference Include="Microsoft.Office.Interop.Outlook" Version="15.0.4797.1004">
<EmbedInteropTypes>true</EmbedInteropTypes> <EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets> <ExcludeAssets>runtime</ExcludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Office.Interop.PowerPoint" Version="15.0.4420.1017"> <PackageReference Include="Microsoft.Office.Interop.PowerPoint" Version="15.0.4420.1018">
<EmbedInteropTypes>true</EmbedInteropTypes> <EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets> <ExcludeAssets>runtime</ExcludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Office.Interop.Word" Version="15.0.4797.1003"> <PackageReference Include="Microsoft.Office.Interop.Word" Version="15.0.4797.1004">
<EmbedInteropTypes>true</EmbedInteropTypes> <EmbedInteropTypes>true</EmbedInteropTypes>
<ExcludeAssets>runtime</ExcludeAssets> <ExcludeAssets>runtime</ExcludeAssets>
</PackageReference> </PackageReference>

View file

@ -0,0 +1,43 @@
using System.Linq;
using Microsoft.Win32;
namespace Greenshot.Plugin.Office;
/// <summary>
/// A small utility class for helping with office
/// </summary>
internal static class OfficeUtils
{
private static readonly string[] OfficeRootKeys = { @"SOFTWARE\Microsoft\Office", @"SOFTWARE\WOW6432Node\Microsoft\Office" };
/// <summary>
/// Get the path to the office exe
/// </summary>
/// <param name="exeName">Name of the office executable</param>
public static string GetOfficeExePath(string exeName)
{
string strKeyName = exeName switch
{
"WINWORD.EXE" => "Word",
"EXCEL.EXE" => "Excel",
"POWERPNT.EXE" => "PowerPoint",
"OUTLOOK.EXE" => "Outlook",
"ONENOTE.EXE" => "OneNote",
_ => ""
};
foreach (string strRootKey in OfficeRootKeys)
{
using RegistryKey rootKey = Registry.LocalMachine.OpenSubKey(strRootKey);
if (rootKey is null) continue;
foreach (string officeVersion in rootKey.GetSubKeyNames().Where(r => r.Contains(".")).Reverse())
{
using RegistryKey installRootKey = Registry.LocalMachine.OpenSubKey($@"{strRootKey}\{officeVersion}\{strKeyName}\InstallRoot");
if (installRootKey == null) continue;
return $@"{installRootKey.GetValue("Path")}\{exeName}";
}
}
return null;
}
}

View file

@ -11,8 +11,7 @@
<loadFromRemoteSources enabled="true" /> <loadFromRemoteSources enabled="true" />
<relativeBindForResources enabled="true" /> <relativeBindForResources enabled="true" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Addons" /> <probing privatePath="Addons,App\Greenshot" />
<probing privatePath="App\Greenshot" />
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
</configuration> </configuration>

View file

@ -197,7 +197,7 @@ namespace Greenshot.Forms
private void CaptureForm_Resize(object sender, EventArgs e) private void CaptureForm_Resize(object sender, EventArgs e)
{ {
Log.DebugFormat("Resize was called, new size: {0}", this.Bounds); Log.DebugFormat("Resize was called, new size: {0}", this.Bounds);
if (Bounds.Equals(_capture.ScreenBounds)) if (_capture.ScreenBounds.Equals(Bounds))
{ {
// We have the correct size // We have the correct size
return; return;
@ -425,9 +425,11 @@ namespace Greenshot.Forms
else if (_captureRect.Height > 0 && _captureRect.Width > 0) else if (_captureRect.Height > 0 && _captureRect.Width > 0)
{ {
// correct the GUI width to real width if Region mode // correct the GUI width to real width if Region mode
if (_captureMode == CaptureMode.Region || _captureMode == CaptureMode.Text) if (_captureMode is CaptureMode.Region or CaptureMode.Text)
{ {
_captureRect = _captureRect.Inflate(1, 1); // Correct the rectangle size, by making it 1 pixel bigger
// We cannot use inflate, this would make the rect bigger to all sizes.
_captureRect = new NativeRect(_captureRect.Left, _captureRect.Top, _captureRect.Width+1, _captureRect.Height+1);
} }
// Go and process the capture // Go and process the capture

View file

@ -17,7 +17,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Tools.InnoSetup" version="6.2.0" GeneratePathProperty="true" /> <PackageReference Include="Tools.InnoSetup" version="6.2.1" GeneratePathProperty="true" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -564,14 +564,6 @@ namespace Greenshot.Helpers
{ {
_windows = new List<WindowDetails>(); _windows = new List<WindowDetails>();
// If the App Launcher is visible, no other windows are active
WindowDetails appLauncherWindow = WindowDetails.GetAppLauncher();
if (appLauncherWindow != null && appLauncherWindow.Visible)
{
_windows.Add(appLauncherWindow);
return null;
}
Thread getWindowDetailsThread = new Thread(RetrieveWindowDetails) Thread getWindowDetailsThread = new Thread(RetrieveWindowDetails)
{ {
Name = "Retrieve window details", Name = "Retrieve window details",
@ -984,7 +976,7 @@ namespace Greenshot.Helpers
else else
{ {
// Change to GDI, if allowed // Change to GDI, if allowed
if (!windowToCapture.IsMetroApp && WindowCapture.IsGdiAllowed(process)) if (WindowCapture.IsGdiAllowed(process))
{ {
if (!dwmEnabled && IsWpf(process)) if (!dwmEnabled && IsWpf(process))
{ {
@ -1000,7 +992,7 @@ namespace Greenshot.Helpers
// Change to DWM, if enabled and allowed // Change to DWM, if enabled and allowed
if (dwmEnabled) if (dwmEnabled)
{ {
if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process)) if (WindowCapture.IsDwmAllowed(process))
{ {
windowCaptureMode = WindowCaptureMode.Aero; windowCaptureMode = WindowCaptureMode.Aero;
} }
@ -1009,7 +1001,7 @@ namespace Greenshot.Helpers
} }
else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent) else if (windowCaptureMode == WindowCaptureMode.Aero || windowCaptureMode == WindowCaptureMode.AeroTransparent)
{ {
if (!dwmEnabled || (!windowToCapture.IsMetroApp && !WindowCapture.IsDwmAllowed(process))) if (!dwmEnabled || !WindowCapture.IsDwmAllowed(process))
{ {
// Take default screen // Take default screen
windowCaptureMode = WindowCaptureMode.Screen; windowCaptureMode = WindowCaptureMode.Screen;
@ -1115,7 +1107,7 @@ namespace Greenshot.Helpers
break; break;
case WindowCaptureMode.Aero: case WindowCaptureMode.Aero:
case WindowCaptureMode.AeroTransparent: case WindowCaptureMode.AeroTransparent:
if (windowToCapture.IsMetroApp || WindowCapture.IsDwmAllowed(process)) if (WindowCapture.IsDwmAllowed(process))
{ {
tmpCapture = windowToCapture.CaptureDwmWindow(captureForWindow, windowCaptureMode, isAutoMode); tmpCapture = windowToCapture.CaptureDwmWindow(captureForWindow, windowCaptureMode, isAutoMode);
} }