From 04a78a02d3daa51ea6f471e9dc328f5a2af345bb Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Wed, 16 Nov 2016 18:33:01 +0100
Subject: [PATCH 01/11] Add NotificationFlags for easier configuration of the
 notification window

---
 Core/FormBrowser.cs             |  6 +++---
 Core/FormNotification.cs        | 20 +++++++++++---------
 Core/Other/FormSettings.cs      |  3 ++-
 Core/Utils/NotificationFlags.cs | 11 +++++++++++
 TweetDck.csproj                 |  1 +
 5 files changed, 28 insertions(+), 13 deletions(-)
 create mode 100644 Core/Utils/NotificationFlags.cs

diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 05c4ded1..02657219 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -44,7 +44,7 @@ public FormBrowser(PluginManager pluginManager){
             this.plugins.Reloaded += plugins_Reloaded;
             this.plugins.PluginChangedState += plugins_PluginChangedState;
 
-            FormNotification notification = CreateNotificationForm(true);
+            FormNotification notification = CreateNotificationForm(NotificationFlags.AutoHide);
             notification.CanMoveWindow = () => false;
             notification.Show();
 
@@ -87,8 +87,8 @@ private void ForceClose(){
             Close();
         }
 
-        public FormNotification CreateNotificationForm(bool autoHide){
-            return new FormNotification(this, plugins, autoHide);
+        public FormNotification CreateNotificationForm(NotificationFlags flags){
+            return new FormNotification(this, plugins, flags);
         }
 
         // window setup
diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs
index 091ddea8..09505292 100644
--- a/Core/FormNotification.cs
+++ b/Core/FormNotification.cs
@@ -25,7 +25,7 @@ sealed partial class FormNotification : Form{
         private readonly ChromiumWebBrowser browser;
 
         private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4);
-        private readonly bool autoHide;
+        private readonly NotificationFlags flags;
         private int timeLeft, totalTime;
         
         private readonly NativeMethods.HookProc mouseHookDelegate;
@@ -82,22 +82,24 @@ private static int BaseClientHeight{
             }
         }
 
-        public FormNotification(FormBrowser owner, PluginManager pluginManager, bool autoHide){
+        public FormNotification(FormBrowser owner, PluginManager pluginManager, NotificationFlags flags){
             InitializeComponent();
 
             Text = Program.BrandName;
 
             this.owner = owner;
             this.plugins = pluginManager;
-            this.autoHide = autoHide;
+            this.flags = flags;
 
             owner.FormClosed += (sender, args) => Close();
 
-            notificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
-            pluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile);
+            if (!flags.HasFlag(NotificationFlags.DisableScripts)){
+                notificationJS = ScriptLoader.LoadResource(NotificationScriptFile);
+                pluginJS = ScriptLoader.LoadResource(PluginManager.PluginNotificationScriptFile);
+            }
 
             browser = new ChromiumWebBrowser("about:blank"){
-                MenuHandler = new ContextMenuNotification(this, autoHide),
+                MenuHandler = new ContextMenuNotification(this, !flags.HasFlag(NotificationFlags.DisableContextMenu)),
                 LifeSpanHandler = new LifeSpanHandler()
             };
 
@@ -112,7 +114,7 @@ public FormNotification(FormBrowser owner, PluginManager pluginManager, bool aut
 
             panelBrowser.Controls.Add(browser);
 
-            if (autoHide){
+            if (flags.HasFlag(NotificationFlags.AutoHide)){
                 Program.UserConfig.MuteToggled += Config_MuteToggled;
                 Disposed += (sender, args) => Program.UserConfig.MuteToggled -= Config_MuteToggled;
             }
@@ -197,7 +199,7 @@ private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
                     Initialized(this, new EventArgs());
                 }
             }
-            else if (notificationJS != null && browser.Address != "about:blank"){
+            else if (notificationJS != null && browser.Address != "about:blank" && !flags.HasFlag(NotificationFlags.DisableScripts)){
                 ScriptLoader.ExecuteScript(e.Frame, notificationJS, NotificationScriptIdentifier);
 
                 if (plugins.HasAnyPlugin(PluginEnvironment.Notification)){
@@ -269,7 +271,7 @@ public void FinishCurrentTweet(){
             if (tweetQueue.Count > 0){
                 LoadNextNotification();
             }
-            else if (autoHide){
+            else if (flags.HasFlag(NotificationFlags.AutoHide)){
                 HideNotification(true);
             }
             else{
diff --git a/Core/Other/FormSettings.cs b/Core/Other/FormSettings.cs
index 4dcdd191..905d552c 100644
--- a/Core/Other/FormSettings.cs
+++ b/Core/Other/FormSettings.cs
@@ -3,6 +3,7 @@
 using System.Linq;
 using System.Windows.Forms;
 using TweetDck.Core.Other.Settings;
+using TweetDck.Core.Utils;
 using TweetDck.Plugins;
 using TweetDck.Updates;
 
@@ -17,7 +18,7 @@ public FormSettings(FormBrowser browserForm, PluginManager plugins, UpdateHandle
 
             this.tabPanel.SetupTabPanel(100);
             this.tabPanel.AddButton("General", SelectTab<TabSettingsGeneral>);
-            this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browserForm.CreateNotificationForm(false))));
+            this.tabPanel.AddButton("Notifications", () => SelectTab(() => new TabSettingsNotifications(browserForm.CreateNotificationForm(NotificationFlags.DisableContextMenu))));
             this.tabPanel.AddButton("Updates", () => SelectTab(() => new TabSettingsUpdates(updates)));
             this.tabPanel.AddButton("Advanced", () => SelectTab(() => new TabSettingsAdvanced(browserForm.ReloadBrowser, plugins)));
             this.tabPanel.SelectTab(tabPanel.Buttons.First());
diff --git a/Core/Utils/NotificationFlags.cs b/Core/Utils/NotificationFlags.cs
new file mode 100644
index 00000000..2fb722ef
--- /dev/null
+++ b/Core/Utils/NotificationFlags.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace TweetDck.Core.Utils{
+    [Flags]
+    public enum NotificationFlags{
+        None = 0,
+        AutoHide = 1,
+        DisableScripts = 2,
+        DisableContextMenu = 4
+    }
+}
diff --git a/TweetDck.csproj b/TweetDck.csproj
index cb9b90a3..045d0c35 100644
--- a/TweetDck.csproj
+++ b/TweetDck.csproj
@@ -178,6 +178,7 @@
     </Compile>
     <Compile Include="Core\Utils\CommandLineArgs.cs" />
     <Compile Include="Core\Utils\CommandLineArgsParser.cs" />
+    <Compile Include="Core\Utils\NotificationFlags.cs" />
     <Compile Include="Core\Utils\WindowState.cs" />
     <Compile Include="Core\Utils\WindowsUtils.cs" />
     <Compile Include="Core\Handling\TweetDeckBridge.cs" />

From 7a1e7637ffc93d62585b62abb98734c3719bc00f Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Wed, 16 Nov 2016 18:33:30 +0100
Subject: [PATCH 02/11] Add a parameter to toggle custom CSS in
 TweetNotification.GenerateHtml

---
 Core/Handling/TweetNotification.cs | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/Core/Handling/TweetNotification.cs b/Core/Handling/TweetNotification.cs
index f8d70612..d3c327f6 100644
--- a/Core/Handling/TweetNotification.cs
+++ b/Core/Handling/TweetNotification.cs
@@ -99,16 +99,20 @@ public int GetDisplayDuration(int value){
             return 2000+Math.Max(1000, value*characters);
         }
 
-        public string GenerateHtml(){
+        public string GenerateHtml(bool enableCustomCSS = true){
             StringBuilder build = new StringBuilder();
             build.Append("<!DOCTYPE html>");
             build.Append("<html class='os-windows txt-base-").Append(FontSizeClass ?? DefaultFontSizeClass).Append("'>");
-            build.Append("<head>").Append(HeadTag ?? DefaultHeadTag).Append("<style type='text/css'>").Append(CustomCSS).Append("</style>");
+            build.Append("<head>").Append(HeadTag ?? DefaultHeadTag);
             
-            if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){
-                build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>");
-            }
+            if (enableCustomCSS){
+                build.Append("<style type='text/css'>").Append(CustomCSS).Append("</style>");
 
+                if (!string.IsNullOrEmpty(Program.UserConfig.CustomNotificationCSS)){
+                    build.Append("<style type='text/css'>").Append(Program.UserConfig.CustomNotificationCSS).Append("</style>");
+                }
+            }
+            
             build.Append("</head>");
             build.Append("<body class='hearty'").Append(isExample ? " td-example-notification" : "").Append("><div class='app-columns-container'><div class='column scroll-styled-v' style='width:100%;overflow-y:auto'>");
             build.Append(html);

From c3db3ce0f233634fb5fb5612eab624892e1f9750 Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Wed, 16 Nov 2016 18:39:30 +0100
Subject: [PATCH 03/11] Push WIP tweet screenshot functionality

---
 Core/FormBrowser.cs                 | 15 ++++++++++++
 Core/FormNotification.cs            | 38 ++++++++++++++++++++++++++++-
 Core/Handling/ContextMenuBrowser.cs |  6 +++++
 Core/Handling/TweetDeckBridge.cs    |  4 +++
 Resources/Scripts/code.js           | 18 ++++++++++++++
 5 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 02657219..47b58faf 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -291,6 +291,17 @@ public void OnTweetNotification(){
             }
         }
 
+        public void OnTweetScreenshotReady(string html, int width, int height){
+            FormNotification dummyWindow = CreateNotificationForm(NotificationFlags.DisableScripts | NotificationFlags.DisableContextMenu);
+
+            dummyWindow.ShowNotificationForScreenshot(new TweetNotification(html, string.Empty, 0), width, height, () => {
+                // TODO DrawToBitmap does not work here
+                dummyWindow.Dispose(); // TODO something freezes the program sometimes
+            });
+
+            dummyWindow.Show();
+        }
+
         public void DisplayTooltip(string text){
             if (string.IsNullOrEmpty(text)){
                 toolTip.Hide(this);
@@ -310,6 +321,10 @@ public void OnImagePastedFinish(){
             browser.ExecuteScriptAsync("TDGF_tryPasteImageFinish()");
         }
 
+        public void TriggerTweetScreenshot(){
+            browser.ExecuteScriptAsync("TDGF_triggerScreenshot()");
+        }
+
         public void ReloadBrowser(){
             browser.ExecuteScriptAsync("window.location.reload()");
         }
diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs
index 09505292..3b9d3bef 100644
--- a/Core/FormNotification.cs
+++ b/Core/FormNotification.cs
@@ -5,6 +5,7 @@
 using CefSharp;
 using CefSharp.WinForms;
 using TweetDck.Configuration;
+using TweetDck.Core.Controls;
 using TweetDck.Core.Handling;
 using TweetDck.Resources;
 using TweetDck.Core.Utils;
@@ -23,9 +24,9 @@ sealed partial class FormNotification : Form{
         private readonly Form owner;
         private readonly PluginManager plugins;
         private readonly ChromiumWebBrowser browser;
+        private readonly NotificationFlags flags;
 
         private readonly Queue<TweetNotification> tweetQueue = new Queue<TweetNotification>(4);
-        private readonly NotificationFlags flags;
         private int timeLeft, totalTime;
         
         private readonly NativeMethods.HookProc mouseHookDelegate;
@@ -248,6 +249,41 @@ public void ShowNotificationForSettings(bool reset){
             }
         }
 
+        public void ShowNotificationForScreenshot(TweetNotification tweet, int width, int height, Action callback){
+            browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new ScreenshotBridge(() => this.InvokeSafe(callback)));
+
+            browser.FrameLoadEnd += (sender, args) => {
+                if (args.Frame.IsMain){
+                    args.Frame.ExecuteJavaScriptAsync("$TD_NotificationScreenshot.trigger()");
+                }
+            };
+
+            browser.LoadHtml(tweet.GenerateHtml(false), "http://tweetdeck.twitter.com/?"+DateTime.Now.Ticks);
+            
+            ClientSize = new Size(width, height);
+            progressBarTimer.Visible = false;
+            panelBrowser.Height = height;
+
+            // TODO
+
+            Screen screen = Screen.FromControl(this);
+            Location = new Point(screen.WorkingArea.X+8, screen.WorkingArea.Y+8);
+
+            // TODO start a timer on 10 seconds to close the window if anything fails or takes too long
+        }
+
+        private sealed class ScreenshotBridge{
+            private readonly Action safeCallback;
+
+            public ScreenshotBridge(Action safeCallback){
+                this.safeCallback = safeCallback;
+            }
+
+            public void Trigger(){
+                safeCallback();
+            }
+        }
+
         public void HideNotification(bool loadBlank){
             if (loadBlank || Program.UserConfig.NotificationLegacyLoad){
                 browser.LoadHtml("", "about:blank");
diff --git a/Core/Handling/ContextMenuBrowser.cs b/Core/Handling/ContextMenuBrowser.cs
index d4c29cbf..00afd2e2 100644
--- a/Core/Handling/ContextMenuBrowser.cs
+++ b/Core/Handling/ContextMenuBrowser.cs
@@ -15,6 +15,7 @@ class ContextMenuBrowser : ContextMenuBase{
         private const int MenuCopyTweetUrl = 26611;
         private const int MenuOpenQuotedTweetUrl = 26612;
         private const int MenuCopyQuotedTweetUrl = 26613;
+        private const int MenuScreenshotTweet = 26614;
 
         private readonly FormBrowser form;
 
@@ -45,6 +46,7 @@ public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser br
             if (!string.IsNullOrEmpty(lastHighlightedTweet) && (parameters.TypeFlags & (ContextMenuType.Editable | ContextMenuType.Selection)) == 0){
                 model.AddItem((CefMenuCommand)MenuOpenTweetUrl, "Open tweet in browser");
                 model.AddItem((CefMenuCommand)MenuCopyTweetUrl, "Copy tweet address");
+                model.AddItem((CefMenuCommand)MenuScreenshotTweet, "Screenshot tweet to clipboard");
 
                 if (!string.IsNullOrEmpty(lastHighlightedQuotedTweet)){
                     model.AddSeparator();
@@ -109,6 +111,10 @@ public override bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser b
                     Clipboard.SetText(lastHighlightedTweet, TextDataFormat.UnicodeText);
                     return true;
 
+                case MenuScreenshotTweet:
+                    form.InvokeSafe(form.TriggerTweetScreenshot);
+                    return true;
+
                 case MenuOpenQuotedTweetUrl:
                     BrowserUtils.OpenExternalBrowser(lastHighlightedQuotedTweet);
                     return true;
diff --git a/Core/Handling/TweetDeckBridge.cs b/Core/Handling/TweetDeckBridge.cs
index 6d645876..b4669bc6 100644
--- a/Core/Handling/TweetDeckBridge.cs
+++ b/Core/Handling/TweetDeckBridge.cs
@@ -154,6 +154,10 @@ public void ClickUploadImage(int offsetX, int offsetY){
             });
         }
 
+        public void ScreenshotTweet(string html, int width, int height){
+            form.InvokeSafe(() => form.OnTweetScreenshotReady(html, width, height));
+        }
+
         public void OpenBrowser(string url){
             BrowserUtils.OpenExternalBrowser(url);
         }
diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js
index 71b454fc..af79c688 100644
--- a/Resources/Scripts/code.js
+++ b/Resources/Scripts/code.js
@@ -304,6 +304,24 @@
     });
   })();
   
+  //
+  // Block: Screenshot tweet to clipboard.
+  //
+  (function(){
+    var selectedTweet;
+    
+    app.delegate("article.js-stream-item", "contextmenu", function(){
+      selectedTweet = $(this);
+    });
+    
+    window.TDGF_triggerScreenshot = function(){
+      if (selectedTweet){
+        selectedTweet.find("footer").last().remove();
+        $TD.screenshotTweet(selectedTweet.html(), selectedTweet.width(), selectedTweet.height());
+      }
+    };
+  })();
+  
   //
   // Block: Paste images when tweeting.
   //

From a1b483d20ad414b223f899022e55e53e4e852398 Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 13:40:30 +0100
Subject: [PATCH 04/11] Implement printscreen simulation and a timeout to
 screenshot notification

---
 Core/FormBrowser.cs      | 6 ++++--
 Core/FormNotification.cs | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 47b58faf..342fd46c 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -295,8 +295,10 @@ public void OnTweetScreenshotReady(string html, int width, int height){
             FormNotification dummyWindow = CreateNotificationForm(NotificationFlags.DisableScripts | NotificationFlags.DisableContextMenu);
 
             dummyWindow.ShowNotificationForScreenshot(new TweetNotification(html, string.Empty, 0), width, height, () => {
-                // TODO DrawToBitmap does not work here
-                dummyWindow.Dispose(); // TODO something freezes the program sometimes
+                dummyWindow.Activate();
+                SendKeys.SendWait("%{PRTSC}");
+                dummyWindow.Close();
+                // dummyWindow.Dispose(); // TODO something freezes the program sometimes
             });
 
             dummyWindow.Show();
diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs
index 3b9d3bef..0636e7f5 100644
--- a/Core/FormNotification.cs
+++ b/Core/FormNotification.cs
@@ -254,7 +254,7 @@ public void ShowNotificationForScreenshot(TweetNotification tweet, int width, in
 
             browser.FrameLoadEnd += (sender, args) => {
                 if (args.Frame.IsMain){
-                    args.Frame.ExecuteJavaScriptAsync("$TD_NotificationScreenshot.trigger()");
+                    ScriptLoader.ExecuteScript(args.Frame, "window.setTimeout(() => $TD_NotificationScreenshot.trigger(), 25)", "gen:screenshot");
                 }
             };
 

From 7f7c5ab35b597c4ad3f6b650dcead9e562bf19fa Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 14:07:47 +0100
Subject: [PATCH 05/11] Update CefSharp to 53.0.1

---
 Configuration/packages.config |  8 ++++----
 TweetDck.csproj               | 30 ++++++++++++++----------------
 2 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/Configuration/packages.config b/Configuration/packages.config
index d299e8fe..02c2fd46 100644
--- a/Configuration/packages.config
+++ b/Configuration/packages.config
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
-  <package id="cef.redist.x64" version="3.2785.1478" targetFramework="net452" />
-  <package id="cef.redist.x86" version="3.2785.1478" targetFramework="net452" />
-  <package id="CefSharp.Common" version="53.0.0-pre01" targetFramework="net452" />
-  <package id="CefSharp.WinForms" version="53.0.0-pre01" targetFramework="net452" />
+  <package id="cef.redist.x64" version="3.2785.1486" targetFramework="net452" />
+  <package id="cef.redist.x86" version="3.2785.1486" targetFramework="net452" />
+  <package id="CefSharp.Common" version="53.0.1" targetFramework="net452" />
+  <package id="CefSharp.WinForms" version="53.0.1" targetFramework="net452" />
   <package id="Microsoft.VC120.CRT.JetBrains" version="12.0.21005.2" targetFramework="net452" />
 </packages>
\ No newline at end of file
diff --git a/TweetDck.csproj b/TweetDck.csproj
index 045d0c35..af6c8f59 100644
--- a/TweetDck.csproj
+++ b/TweetDck.csproj
@@ -1,9 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props')" />
-  <Import Project="packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props')" />
-  <Import Project="packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.49.0.0-pre02\build\CefSharp.WinForms.props')" />
-  <Import Project="packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.49.0.0-pre02\build\CefSharp.Common.props')" />
+  <Import Project="packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props')" />
+  <Import Project="packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props')" />
   <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -16,7 +14,7 @@
     <AssemblyName Condition=" '$(Configuration)' == 'Release' ">TweetDuck</AssemblyName>
     <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
-    <NuGetPackageImportStamp>e83161d1</NuGetPackageImportStamp>
+    <NuGetPackageImportStamp>783c0e30</NuGetPackageImportStamp>
     <TargetFrameworkProfile>
     </TargetFrameworkProfile>
     <PublishUrl>publish\</PublishUrl>
@@ -305,12 +303,12 @@
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets'))" />
-    <Error Condition="!Exists('packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets'))" />
-    <Error Condition="!Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.props'))" />
-    <Error Condition="!Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets'))" />
-    <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.props'))" />
-    <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets'))" />
+    <Error Condition="!Exists('packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets'))" />
+    <Error Condition="!Exists('packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets'))" />
+    <Error Condition="!Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props'))" />
+    <Error Condition="!Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets'))" />
+    <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props'))" />
+    <Error Condition="!Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets'))" />
   </Target>
   <PropertyGroup>
     <PostBuildEvent>del "$(TargetPath).config"
@@ -331,10 +329,10 @@ xcopy "$(ProjectDir)Resources\Plugins\*" "$(TargetDir)plugins\official\" /E /Y
 rmdir "$(ProjectDir)\bin\Debug"
 rmdir "$(ProjectDir)\bin\Release"</PostBuildEvent>
   </PropertyGroup>
-  <Import Project="packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.2785.1478\build\cef.redist.x86.targets')" />
-  <Import Project="packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.2785.1478\build\cef.redist.x64.targets')" />
-  <Import Project="packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.53.0.0-pre01\build\CefSharp.Common.targets')" />
-  <Import Project="packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.53.0.0-pre01\build\CefSharp.WinForms.targets')" />
+  <Import Project="packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets" Condition="Exists('packages\cef.redist.x86.3.2785.1486\build\cef.redist.x86.targets')" />
+  <Import Project="packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets" Condition="Exists('packages\cef.redist.x64.3.2785.1486\build\cef.redist.x64.targets')" />
+  <Import Project="packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.targets')" />
+  <Import Project="packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.targets')" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

From 61359c2faa9e952d63ffbcc9ac485917ef2564c2 Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 14:26:59 +0100
Subject: [PATCH 06/11] Refactor NotificationFlags and inner screenshot bridge
 class to a separate namespace

---
 Core/FormBrowser.cs                           |  1 +
 Core/FormNotification.cs                      | 15 ++-------------
 Core/Other/FormSettings.cs                    |  2 +-
 Core/Utils/Notification/CallbackBridge.cs     | 19 +++++++++++++++++++
 .../{ => Notification}/NotificationFlags.cs   |  2 +-
 5 files changed, 24 insertions(+), 15 deletions(-)
 create mode 100644 Core/Utils/Notification/CallbackBridge.cs
 rename Core/Utils/{ => Notification}/NotificationFlags.cs (79%)

diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 342fd46c..6d868c79 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -9,6 +9,7 @@
 using TweetDck.Core.Controls;
 using System.Drawing;
 using TweetDck.Core.Utils;
+using TweetDck.Core.Utils.Notification;
 using TweetDck.Updates;
 using TweetDck.Plugins;
 using TweetDck.Plugins.Enums;
diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs
index 0636e7f5..0c5c504c 100644
--- a/Core/FormNotification.cs
+++ b/Core/FormNotification.cs
@@ -9,6 +9,7 @@
 using TweetDck.Core.Handling;
 using TweetDck.Resources;
 using TweetDck.Core.Utils;
+using TweetDck.Core.Utils.Notification;
 using TweetDck.Plugins;
 using TweetDck.Plugins.Enums;
 
@@ -250,7 +251,7 @@ public void ShowNotificationForSettings(bool reset){
         }
 
         public void ShowNotificationForScreenshot(TweetNotification tweet, int width, int height, Action callback){
-            browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new ScreenshotBridge(() => this.InvokeSafe(callback)));
+            browser.RegisterAsyncJsObject("$TD_NotificationScreenshot", new CallbackBridge(this, callback));
 
             browser.FrameLoadEnd += (sender, args) => {
                 if (args.Frame.IsMain){
@@ -272,18 +273,6 @@ public void ShowNotificationForScreenshot(TweetNotification tweet, int width, in
             // TODO start a timer on 10 seconds to close the window if anything fails or takes too long
         }
 
-        private sealed class ScreenshotBridge{
-            private readonly Action safeCallback;
-
-            public ScreenshotBridge(Action safeCallback){
-                this.safeCallback = safeCallback;
-            }
-
-            public void Trigger(){
-                safeCallback();
-            }
-        }
-
         public void HideNotification(bool loadBlank){
             if (loadBlank || Program.UserConfig.NotificationLegacyLoad){
                 browser.LoadHtml("", "about:blank");
diff --git a/Core/Other/FormSettings.cs b/Core/Other/FormSettings.cs
index 905d552c..55b1a144 100644
--- a/Core/Other/FormSettings.cs
+++ b/Core/Other/FormSettings.cs
@@ -3,7 +3,7 @@
 using System.Linq;
 using System.Windows.Forms;
 using TweetDck.Core.Other.Settings;
-using TweetDck.Core.Utils;
+using TweetDck.Core.Utils.Notification;
 using TweetDck.Plugins;
 using TweetDck.Updates;
 
diff --git a/Core/Utils/Notification/CallbackBridge.cs b/Core/Utils/Notification/CallbackBridge.cs
new file mode 100644
index 00000000..6c6c2fbf
--- /dev/null
+++ b/Core/Utils/Notification/CallbackBridge.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Windows.Forms;
+using TweetDck.Core.Controls;
+
+namespace TweetDck.Core.Utils.Notification{
+    sealed class CallbackBridge{
+        private readonly Control owner;
+        private readonly Action safeCallback;
+
+        public CallbackBridge(Control owner, Action safeCallback){
+            this.owner = owner;
+            this.safeCallback = safeCallback;
+        }
+
+        public void Trigger(){
+            owner.InvokeSafe(safeCallback);
+        }
+    }
+}
diff --git a/Core/Utils/NotificationFlags.cs b/Core/Utils/Notification/NotificationFlags.cs
similarity index 79%
rename from Core/Utils/NotificationFlags.cs
rename to Core/Utils/Notification/NotificationFlags.cs
index 2fb722ef..6efa12e9 100644
--- a/Core/Utils/NotificationFlags.cs
+++ b/Core/Utils/Notification/NotificationFlags.cs
@@ -1,6 +1,6 @@
 using System;
 
-namespace TweetDck.Core.Utils{
+namespace TweetDck.Core.Utils.Notification{
     [Flags]
     public enum NotificationFlags{
         None = 0,

From 3a37ee719b66c7a4c7cb17fd77bbe560e77ccbbd Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 14:29:23 +0100
Subject: [PATCH 07/11] Fix csproj file after previous refactor commit

---
 TweetDck.csproj | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/TweetDck.csproj b/TweetDck.csproj
index af6c8f59..833d59a8 100644
--- a/TweetDck.csproj
+++ b/TweetDck.csproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props" Condition="Exists('packages\CefSharp.WinForms.53.0.1\build\CefSharp.WinForms.props')" />
   <Import Project="packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props" Condition="Exists('packages\CefSharp.Common.53.0.1\build\CefSharp.Common.props')" />
@@ -174,9 +174,10 @@
     <Compile Include="Core\Other\Settings\TabSettingsUpdates.Designer.cs">
       <DependentUpon>TabSettingsUpdates.cs</DependentUpon>
     </Compile>
+    <Compile Include="Core\Utils\Notification\CallbackBridge.cs" />
     <Compile Include="Core\Utils\CommandLineArgs.cs" />
     <Compile Include="Core\Utils\CommandLineArgsParser.cs" />
-    <Compile Include="Core\Utils\NotificationFlags.cs" />
+    <Compile Include="Core\Utils\Notification\NotificationFlags.cs" />
     <Compile Include="Core\Utils\WindowState.cs" />
     <Compile Include="Core\Utils\WindowsUtils.cs" />
     <Compile Include="Core\Handling\TweetDeckBridge.cs" />

From 9b983de8c9e59b8d33c6546cf9b69e5c7063a3b1 Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 14:52:48 +0100
Subject: [PATCH 08/11] Ensure notification window visibility when taking
 screenshots, refactor MoveToVisibleLocation

---
 Core/FormBrowser.cs      |  4 ++--
 Core/FormNotification.cs | 49 ++++++++++++++++++++++------------------
 2 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 6d868c79..36828a61 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -296,8 +296,8 @@ public void OnTweetScreenshotReady(string html, int width, int height){
             FormNotification dummyWindow = CreateNotificationForm(NotificationFlags.DisableScripts | NotificationFlags.DisableContextMenu);
 
             dummyWindow.ShowNotificationForScreenshot(new TweetNotification(html, string.Empty, 0), width, height, () => {
-                dummyWindow.Activate();
-                SendKeys.SendWait("%{PRTSC}");
+                dummyWindow.TakeScreenshot();
+                dummyWindow.Hide();
                 dummyWindow.Close();
                 // dummyWindow.Dispose(); // TODO something freezes the program sometimes
             });
diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs
index 0c5c504c..8a3c00da 100644
--- a/Core/FormNotification.cs
+++ b/Core/FormNotification.cs
@@ -246,7 +246,7 @@ public void ShowNotificationForSettings(bool reset){
                 LoadTweet(TweetNotification.ExampleTweet);
             }
             else{
-                MoveToVisibleLocation();
+                PrepareAndDisplayWindow();
             }
         }
 
@@ -261,18 +261,20 @@ public void ShowNotificationForScreenshot(TweetNotification tweet, int width, in
 
             browser.LoadHtml(tweet.GenerateHtml(false), "http://tweetdeck.twitter.com/?"+DateTime.Now.Ticks);
             
+            Location = new Point(-32000, -32000);
             ClientSize = new Size(width, height);
             progressBarTimer.Visible = false;
             panelBrowser.Height = height;
 
-            // TODO
-
-            Screen screen = Screen.FromControl(this);
-            Location = new Point(screen.WorkingArea.X+8, screen.WorkingArea.Y+8);
-
             // TODO start a timer on 10 seconds to close the window if anything fails or takes too long
         }
 
+        public void TakeScreenshot(){
+            MoveToVisibleLocation();
+            Activate();
+            SendKeys.SendWait("%{PRTSC}");
+        }
+
         public void HideNotification(bool loadBlank){
             if (loadBlank || Program.UserConfig.NotificationLegacyLoad){
                 browser.LoadHtml("", "about:blank");
@@ -288,7 +290,7 @@ public void HideNotification(bool loadBlank){
 
         public void OnNotificationReady(){
             UpdateTitle();
-            MoveToVisibleLocation();
+            PrepareAndDisplayWindow();
             timerProgress.Start();
         }
 
@@ -326,21 +328,6 @@ private void LoadTweet(TweetNotification tweet){
         private void MoveToVisibleLocation(){
             UserConfig config = Program.UserConfig;
 
-            if (RequiresResize){
-                RequiresResize = false;
-
-                if (config.DisplayNotificationTimer){
-                    ClientSize = new Size(BaseClientWidth, BaseClientHeight+4);
-                    progressBarTimer.Visible = true;
-                }
-                else{
-                    ClientSize = new Size(BaseClientWidth, BaseClientHeight);
-                    progressBarTimer.Visible = false;
-                }
-
-                panelBrowser.Height = BaseClientHeight;
-            }
-            
             Screen screen = Screen.FromControl(owner);
 
             if (config.NotificationDisplay > 0 && config.NotificationDisplay <= Screen.AllScreens.Length){
@@ -380,7 +367,25 @@ private void MoveToVisibleLocation(){
             if (needsReactivating){
                 NativeMethods.SetFormPos(this, NativeMethods.HWND_TOPMOST, NativeMethods.SWP_NOACTIVATE);
             }
+        }
 
+        private void PrepareAndDisplayWindow(){
+            if (RequiresResize){
+                RequiresResize = false;
+
+                if (Program.UserConfig.DisplayNotificationTimer){
+                    ClientSize = new Size(BaseClientWidth, BaseClientHeight+4);
+                    progressBarTimer.Visible = true;
+                }
+                else{
+                    ClientSize = new Size(BaseClientWidth, BaseClientHeight);
+                    progressBarTimer.Visible = false;
+                }
+
+                panelBrowser.Height = BaseClientHeight;
+            }
+            
+            MoveToVisibleLocation();
             StartMouseHook();
         }
 

From 68fa3294d46178819f13e91f569b613e5c25f5cc Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 14:56:16 +0100
Subject: [PATCH 09/11] Update CefSharp version in README

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index e21fcb48..c6f6e77a 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 The program was build using Visual Studio 2013. After opening the solution, make sure you have **CefSharp.WinForms** and **Microsoft.VC120.CRT.JetBrains** included - if not, download them using NuGet. For **CefSharp**, you will need version 53 or newer currently available as a pre-release.
 ```
-PM> Install-Package CefSharp.WinForms -Pre -Version 53.0.0-pre01
+PM> Install-Package CefSharp.WinForms -Version 53.0.1
 PM> Install-Package Microsoft.VC120.CRT.JetBrains
 ```
 

From cac6d1f889a21efe761978bf1314dbf0da457aeb Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 15:13:34 +0100
Subject: [PATCH 10/11] Swap notification windows when taking a screenshot, and
 make screenshot window unmovable

---
 Core/FormBrowser.cs      | 26 ++++++++++++++++++++++----
 Core/FormNotification.cs |  7 ++++++-
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 36828a61..d8af3be1 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -28,6 +28,7 @@ private static UserConfig Config{
         private readonly ChromiumWebBrowser browser;
         private readonly PluginManager plugins;
         private readonly UpdateHandler updates;
+        private readonly FormNotification notification;
 
         private FormSettings currentFormSettings;
         private FormAbout currentFormAbout;
@@ -45,9 +46,9 @@ public FormBrowser(PluginManager pluginManager){
             this.plugins.Reloaded += plugins_Reloaded;
             this.plugins.PluginChangedState += plugins_PluginChangedState;
 
-            FormNotification notification = CreateNotificationForm(NotificationFlags.AutoHide);
-            notification.CanMoveWindow = () => false;
-            notification.Show();
+            this.notification = CreateNotificationForm(NotificationFlags.AutoHide);
+            this.notification.CanMoveWindow = () => false;
+            this.notification.Show();
 
             this.browser = new ChromiumWebBrowser("https://tweetdeck.twitter.com/"){
                 MenuHandler = new ContextMenuBrowser(this),
@@ -296,12 +297,29 @@ public void OnTweetScreenshotReady(string html, int width, int height){
             FormNotification dummyWindow = CreateNotificationForm(NotificationFlags.DisableScripts | NotificationFlags.DisableContextMenu);
 
             dummyWindow.ShowNotificationForScreenshot(new TweetNotification(html, string.Empty, 0), width, height, () => {
+                Point? prevNotificationLocation = null;
+                bool prevFreezeTimer = false;
+
+                if (notification.IsNotificationVisible){
+                    prevNotificationLocation = notification.Location;
+                    prevFreezeTimer = notification.FreezeTimer;
+
+                    notification.Location = new Point(-32000, -32000);
+                    notification.FreezeTimer = true;
+                }
+
                 dummyWindow.TakeScreenshot();
                 dummyWindow.Hide();
                 dummyWindow.Close();
                 // dummyWindow.Dispose(); // TODO something freezes the program sometimes
-            });
 
+                if (prevNotificationLocation.HasValue){
+                    notification.Location = prevNotificationLocation.Value;
+                    notification.FreezeTimer = prevFreezeTimer;
+                }
+            });
+            
+            dummyWindow.CanMoveWindow = () => false;
             dummyWindow.Show();
         }
 
diff --git a/Core/FormNotification.cs b/Core/FormNotification.cs
index 8a3c00da..e2f04dce 100644
--- a/Core/FormNotification.cs
+++ b/Core/FormNotification.cs
@@ -5,7 +5,6 @@
 using CefSharp;
 using CefSharp.WinForms;
 using TweetDck.Configuration;
-using TweetDck.Core.Controls;
 using TweetDck.Core.Handling;
 using TweetDck.Resources;
 using TweetDck.Core.Utils;
@@ -22,6 +21,12 @@ sealed partial class FormNotification : Form{
 
         public Func<bool> CanMoveWindow = () => true;
 
+        public bool IsNotificationVisible{
+            get{
+                return Location.X != -32000;
+            }
+        }
+
         private readonly Form owner;
         private readonly PluginManager plugins;
         private readonly ChromiumWebBrowser browser;

From 02e8dc34404666bc359ab24a0b9e2e4c1fedb983 Mon Sep 17 00:00:00 2001
From: chylex <info@chylex.com>
Date: Fri, 23 Dec 2016 15:29:33 +0100
Subject: [PATCH 11/11] Fix screenshot script modifying original elements and
 missing html classes

---
 Resources/Scripts/code.js | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js
index af79c688..2591971b 100644
--- a/Resources/Scripts/code.js
+++ b/Resources/Scripts/code.js
@@ -316,8 +316,14 @@
     
     window.TDGF_triggerScreenshot = function(){
       if (selectedTweet){
+        var realWidth = selectedTweet.width();
+        var realHeight = selectedTweet.height()-selectedTweet.find("footer").last().height();
+        
+        selectedTweet = selectedTweet.clone();
+        selectedTweet.children().first().addClass($(document.documentElement).attr("class"));
         selectedTweet.find("footer").last().remove();
-        $TD.screenshotTweet(selectedTweet.html(), selectedTweet.width(), selectedTweet.height());
+        
+        $TD.screenshotTweet(selectedTweet.html(), realWidth, realHeight);
       }
     };
   })();