1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-04-23 12:15:48 +02:00

Add option for browser throttling w/ default when covered by larger window

This commit is contained in:
chylex 2018-07-06 06:26:50 +02:00
parent 0355a5c646
commit 4e52102c5c
7 changed files with 155 additions and 7 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.IO;
using TweetDuck.Core;
using TweetDuck.Data.Serialization;
namespace TweetDuck.Configuration{
@ -16,6 +17,8 @@ sealed class SystemConfig{
public bool ClearCacheAutomatically { get; set; } = true;
public int ClearCacheThreshold { get; set; } = 250;
public FormBrowser.ThrottleBehavior ThrottleBehavior { get; set; } = FormBrowser.ThrottleBehavior.Covered;
// SPECIAL PROPERTIES
public bool HardwareAcceleration{

View File

@ -27,6 +27,7 @@ private void InitializeComponent() {
this.trayIcon = new TweetDuck.Core.Other.TrayIcon(this.components);
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.timerResize = new System.Windows.Forms.Timer(this.components);
this.timerThrottle = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// timerResize
@ -34,6 +35,10 @@ private void InitializeComponent() {
this.timerResize.Interval = 500;
this.timerResize.Tick += new System.EventHandler(this.timerResize_Tick);
//
// timerThrottle
//
this.timerThrottle.Tick += new System.EventHandler(this.timerThrottle_Tick);
//
// FormBrowser
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -46,6 +51,7 @@ private void InitializeComponent() {
this.Name = "FormBrowser";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Activated += new System.EventHandler(this.FormBrowser_Activated);
this.Deactivate += new System.EventHandler(this.FormBrowser_Deactivate);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormBrowser_FormClosed);
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
@ -60,6 +66,7 @@ private void InitializeComponent() {
private TweetDuck.Core.Other.TrayIcon trayIcon;
private System.Windows.Forms.ToolTip toolTip;
private System.Windows.Forms.Timer timerResize;
private System.Windows.Forms.Timer timerThrottle;
}
}

View File

@ -19,6 +19,10 @@
namespace TweetDuck.Core{
sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{
public enum ThrottleBehavior{ // keep order
Minimized, Covered, Unfocused
}
private static UserConfig Config => Program.UserConfig;
public bool IsWaiting{
@ -96,7 +100,7 @@ public FormBrowser(){
Config.TrayBehaviorChanged += Config_TrayBehaviorChanged;
UpdateTray();
if (Config.MuteNotifications){
UpdateFormIcon();
}
@ -145,6 +149,34 @@ private void timerResize_Tick(object sender, EventArgs e){
FormBrowser_ResizeEnd(this, e); // also stops timer
}
private void timerThrottle_Tick(object sender, EventArgs e){
if (!browser.Ready){
timerThrottle.Interval = 5000;
return;
}
bool shouldThrottle;
switch(Program.SystemConfig.ThrottleBehavior){
case ThrottleBehavior.Covered:
shouldThrottle = WindowState != FormWindowState.Minimized && NativeMethods.IsFormCoveredByLargerWindow(this);
break;
case ThrottleBehavior.Unfocused:
shouldThrottle = !FormManager.HasAnyDialogs;
break;
default:
timerThrottle.Stop();
return;
}
if (shouldThrottle){
browser.SetThrottle(true);
timerThrottle.Stop();
}
}
private void FormBrowser_Activated(object sender, EventArgs e){
if (!isLoaded)return;
@ -153,6 +185,15 @@ private void FormBrowser_Activated(object sender, EventArgs e){
if (!browser.Enabled){ // when taking a screenshot, the window is unfocused and
browser.Enabled = true; // the browser is disabled; if the user clicks back into
} // the window, enable the browser again
timerThrottle.Stop();
browser.SetThrottle(false);
}
private void FormBrowser_Deactivate(object sender, EventArgs e){
timerThrottle.Stop();
timerThrottle.Interval = Program.SystemConfig.ThrottleBehavior == ThrottleBehavior.Covered ? 30000 : 1000;
timerThrottle.Start();
}
private void FormBrowser_LocationChanged(object sender, EventArgs e){

View File

@ -43,6 +43,8 @@ private void InitializeComponent() {
this.panelConfiguration = new System.Windows.Forms.Panel();
this.labelConfiguration = new System.Windows.Forms.Label();
this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
this.labelThrottle = new System.Windows.Forms.Label();
this.comboBoxThrottle = new System.Windows.Forms.ComboBox();
((System.ComponentModel.ISupportInitialize)(this.numClearCacheThreshold)).BeginInit();
this.panelAppButtons.SuspendLayout();
this.panelClearCacheAuto.SuspendLayout();
@ -209,7 +211,7 @@ private void InitializeComponent() {
this.labelPerformance.Location = new System.Drawing.Point(0, 102);
this.labelPerformance.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelPerformance.Name = "labelPerformance";
this.labelPerformance.Size = new System.Drawing.Size(93, 20);
this.labelPerformance.Size = new System.Drawing.Size(92, 20);
this.labelPerformance.TabIndex = 2;
this.labelPerformance.Text = "Performance";
//
@ -219,7 +221,7 @@ private void InitializeComponent() {
this.panelClearCacheAuto.Controls.Add(this.checkClearCacheAuto);
this.panelClearCacheAuto.Controls.Add(this.numClearCacheThreshold);
this.panelClearCacheAuto.Location = new System.Drawing.Point(0, 207);
this.panelClearCacheAuto.Margin = new System.Windows.Forms.Padding(0);
this.panelClearCacheAuto.Margin = new System.Windows.Forms.Padding(0, 0, 0, 2);
this.panelClearCacheAuto.Name = "panelClearCacheAuto";
this.panelClearCacheAuto.Size = new System.Drawing.Size(322, 28);
this.panelClearCacheAuto.TabIndex = 6;
@ -240,7 +242,7 @@ private void InitializeComponent() {
this.panelConfiguration.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panelConfiguration.Controls.Add(this.btnEditCSS);
this.panelConfiguration.Controls.Add(this.btnEditCefArgs);
this.panelConfiguration.Location = new System.Drawing.Point(0, 275);
this.panelConfiguration.Location = new System.Drawing.Point(0, 333);
this.panelConfiguration.Margin = new System.Windows.Forms.Padding(0);
this.panelConfiguration.Name = "panelConfiguration";
this.panelConfiguration.Size = new System.Drawing.Size(322, 31);
@ -250,7 +252,7 @@ private void InitializeComponent() {
//
this.labelConfiguration.AutoSize = true;
this.labelConfiguration.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelConfiguration.Location = new System.Drawing.Point(0, 255);
this.labelConfiguration.Location = new System.Drawing.Point(0, 313);
this.labelConfiguration.Margin = new System.Windows.Forms.Padding(0, 20, 0, 0);
this.labelConfiguration.Name = "labelConfiguration";
this.labelConfiguration.Size = new System.Drawing.Size(100, 20);
@ -269,22 +271,46 @@ private void InitializeComponent() {
this.flowPanel.Controls.Add(this.labelCache);
this.flowPanel.Controls.Add(this.btnClearCache);
this.flowPanel.Controls.Add(this.panelClearCacheAuto);
this.flowPanel.Controls.Add(this.labelThrottle);
this.flowPanel.Controls.Add(this.comboBoxThrottle);
this.flowPanel.Controls.Add(this.labelConfiguration);
this.flowPanel.Controls.Add(this.panelConfiguration);
this.flowPanel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.flowPanel.Location = new System.Drawing.Point(9, 9);
this.flowPanel.Name = "flowPanel";
this.flowPanel.Size = new System.Drawing.Size(322, 307);
this.flowPanel.Size = new System.Drawing.Size(322, 364);
this.flowPanel.TabIndex = 0;
this.flowPanel.WrapContents = false;
//
// labelThrottle
//
this.labelThrottle.AutoSize = true;
this.labelThrottle.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.labelThrottle.Location = new System.Drawing.Point(3, 249);
this.labelThrottle.Margin = new System.Windows.Forms.Padding(3, 12, 3, 0);
this.labelThrottle.Name = "labelThrottle";
this.labelThrottle.Size = new System.Drawing.Size(92, 15);
this.labelThrottle.TabIndex = 9;
this.labelThrottle.Text = "Throttle When...";
//
// comboBoxThrottle
//
this.comboBoxThrottle.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxThrottle.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.comboBoxThrottle.FormattingEnabled = true;
this.comboBoxThrottle.Location = new System.Drawing.Point(5, 267);
this.comboBoxThrottle.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3);
this.comboBoxThrottle.Name = "comboBoxThrottle";
this.comboBoxThrottle.Size = new System.Drawing.Size(173, 23);
this.comboBoxThrottle.TabIndex = 10;
//
// TabSettingsAdvanced
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.flowPanel);
this.Name = "TabSettingsAdvanced";
this.Size = new System.Drawing.Size(340, 325);
this.Size = new System.Drawing.Size(340, 382);
((System.ComponentModel.ISupportInitialize)(this.numClearCacheThreshold)).EndInit();
this.panelAppButtons.ResumeLayout(false);
this.panelClearCacheAuto.ResumeLayout(false);
@ -317,5 +343,7 @@ private void InitializeComponent() {
private Controls.NumericUpDownEx numClearCacheThreshold;
private System.Windows.Forms.CheckBox checkClearCacheAuto;
private System.Windows.Forms.FlowLayoutPanel flowPanel;
private System.Windows.Forms.Label labelThrottle;
private System.Windows.Forms.ComboBox comboBoxThrottle;
}
}

View File

@ -29,6 +29,8 @@ public TabSettingsAdvanced(Action<string> reinjectBrowserCSS){
toolTip.SetToolTip(btnClearCache, "Clearing cache will free up space taken by downloaded images and other resources.");
toolTip.SetToolTip(checkClearCacheAuto, "Automatically clears cache when its size exceeds the set threshold. Note that cache can only be cleared when closing TweetDuck.");
toolTip.SetToolTip(comboBoxThrottle, "Decides when to stop rendering and throttle the browser to improve performance and battery life.");
toolTip.SetToolTip(btnEditCefArgs, "Set custom command line arguments for Chromium Embedded Framework.");
toolTip.SetToolTip(btnEditCSS, "Set custom CSS for browser and notification windows.");
@ -48,6 +50,11 @@ public TabSettingsAdvanced(Action<string> reinjectBrowserCSS){
string text = task.Status == TaskStatus.RanToCompletion ? (int)Math.Ceiling(task.Result/(1024.0*1024.0))+" MB" : "unknown";
this.InvokeSafe(() => btnClearCache.Text = $"Clear Cache ({text})");
});
comboBoxThrottle.Items.Add("Minimized (Naive)");
comboBoxThrottle.Items.Add("Covered (Smart)");
comboBoxThrottle.Items.Add("Unfocused (Aggressive)");
comboBoxThrottle.SelectedIndex = Math.Min(Math.Max((int)SysConfig.ThrottleBehavior, 0), comboBoxThrottle.Items.Count-1);
}
public override void OnReady(){
@ -60,6 +67,8 @@ public override void OnReady(){
btnClearCache.Click += btnClearCache_Click;
checkClearCacheAuto.CheckedChanged += checkClearCacheAuto_CheckedChanged;
comboBoxThrottle.SelectedIndexChanged += comboBoxThrottle_SelectedIndexChanged;
btnEditCefArgs.Click += btnEditCefArgs_Click;
btnEditCSS.Click += btnEditCSS_Click;
@ -86,6 +95,10 @@ private void checkHardwareAcceleration_CheckedChanged(object sender, EventArgs e
PromptRestart(); // calls OnClosing
}
private void comboBoxThrottle_SelectedIndexChanged(object sender, EventArgs e){
SysConfig.ThrottleBehavior = (FormBrowser.ThrottleBehavior)comboBoxThrottle.SelectedIndex;
}
private void btnEditCefArgs_Click(object sender, EventArgs e){
DialogSettingsCefArgs form = new DialogSettingsCefArgs();

View File

@ -87,6 +87,16 @@ public void Focus(){
browser.Focus();
}
public void SetThrottle(bool throttle){
if (throttle && browser.Dock == DockStyle.Fill){
browser.Dock = DockStyle.None;
browser.Size = Size.Empty;
}
else if (!throttle && browser.Dock == DockStyle.None){
browser.Dock = DockStyle.Fill;
}
}
public void Dispose(){
Program.UserConfig.MuteToggled -= UserConfig_MuteToggled;
Program.UserConfig.ZoomLevelChanged -= UserConfig_ZoomLevelChanged;

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Runtime.InteropServices;
@ -14,6 +15,7 @@ static class NativeMethods{
public const int HWND_TOPMOST = -1;
public const uint SWP_NOACTIVATE = 0x0010;
public const int WS_DISABLED = 0x08000000;
public const int GW_HWNDPREV = 3;
public const int GWL_STYLE = -16;
public const int SB_HORZ = 0;
@ -23,6 +25,7 @@ static class NativeMethods{
public const int WM_XBUTTONDOWN = 0x020B;
public const int WM_XBUTTONUP = 0x020C;
public const int WM_PARENTNOTIFY = 0x0210;
[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO{
@ -38,6 +41,14 @@ private struct POINT{
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT{
public POINT pt;
@ -93,6 +104,17 @@ private struct MSLLHOOKSTRUCT{
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, [Out] out RECT lpRect);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd);
public static void SetFormPos(Form form, int hWndOrder, uint flags){
SetWindowPos(form.Handle.ToInt32(), hWndOrder, form.Left, form.Top, form.Width, form.Height, flags);
}
@ -106,6 +128,30 @@ public static void SetFormDisabled(Form form, bool disabled){
}
}
public static bool IsFormCoveredByLargerWindow(Form form){
IntPtr handle = form.Handle;
if (!IsWindowVisible(handle)){
return false;
}
HashSet<IntPtr> visited = new HashSet<IntPtr>{ handle };
GetWindowRect(handle, out RECT thisRect);
while((handle = GetWindow(handle, GW_HWNDPREV)) != IntPtr.Zero && visited.Add(handle)){
if (IsWindowVisible(handle) &&
GetWindowRect(handle, out RECT otherRect) &&
otherRect.left <= thisRect.left &&
otherRect.top <= thisRect.top &&
otherRect.right >= thisRect.right &&
otherRect.bottom >= thisRect.bottom){
return true;
}
}
return false;
}
public static void BroadcastMessage(uint msg, uint wParam, int lParam){
PostMessage(HWND_BROADCAST, msg, new UIntPtr(wParam), new IntPtr(lParam));
}