├── Helpers ├── Helpers.rc ├── Helpers.vcxproj.user ├── Helpers.h ├── dllmain.cpp ├── ..svnbridge │ ├── .svnbridge │ ├── Helpers.aps │ └── Helpers.rc ├── targetver.h ├── stdafx.h ├── resource.h ├── Helpers.vcxproj.filters └── Helpers.cpp ├── GlobalShellHook ├── GlobalShellHook.rc ├── GlobalShellHook.vcxproj.user ├── GlobalShellHook.h ├── targetver.h ├── resource.h ├── stdafx.h ├── dllmain.c ├── GlobalShellHook.c └── GlobalShellHook.vcxproj.filters ├── SystemTrayHook ├── SystemTrayHook.rc ├── SystemTrayHook.vcxproj.user ├── ..svnbridge │ ├── .svnbridge │ ├── SystemTrayHook.aps │ └── SystemTrayHook.rc ├── SystemTrayHook.h ├── targetver.h ├── dllmain.c ├── stdafx.h ├── resource.h ├── SystemTrayHook.c └── SystemTrayHook.vcxproj.filters ├── Windawesome ├── Images │ ├── Icon missing.png │ └── ..svnbridge │ │ └── Icon missing.png ├── app.config ├── IPlugin.cs ├── ..svnbridge │ └── .svnbridge ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── IBar.cs ├── Windawesome.csproj.user ├── ILayout.cs ├── FloatingLayout.cs ├── UpdateChecker.cs ├── SeparatorWidget.cs ├── InputLanguageChangerPlugin.cs ├── IWidget.cs ├── SystemAndProcessInformation.cs ├── HashMultiSet.cs ├── CurrentlyPlayingWidget.cs ├── RamMonitorWidget.cs ├── CPUMonitorWidget.cs ├── LayoutWidget.cs ├── NetworkMonitorWidget.cs ├── Program.cs ├── LaptopBatteryMonitorWidget.cs ├── FullScreenLayout.cs ├── LanguageBarWidget.cs ├── LoggerPlugin.cs ├── Utilities.cs ├── SystemSettingsChanger.cs └── WorkspacesWidget.cs ├── WindowSubclassing ├── WindowSubclassing.aps ├── WindowSubclassing.rc ├── WindowSubclassing.vcxproj.user ├── ..svnbridge │ ├── .svnbridge │ ├── WindowSubclassing.aps │ └── WindowSubclassing.rc ├── WindowSubclassing.h ├── stdafx.cpp ├── targetver.h ├── stdafx.h ├── resource.h ├── dllmain.c ├── WindowSubclassing.vcxproj.filters └── WindowSubclassing.c ├── app_version.xml ├── lib ├── Needed files.txt └── ..svnbridge │ └── .svnbridge ├── TileLayout ├── ..svnbridge │ └── .svnbridge ├── Properties │ └── AssemblyInfo.cs ├── TileLayout.csproj └── TileLayout.cs ├── ShortcutsManager ├── ..svnbridge │ └── .svnbridge ├── Properties │ └── AssemblyInfo.cs ├── ShortcutsManager.csproj └── ShortcutsManager.cs ├── WindowSubclassingCSharp ├── ..svnbridge │ └── .svnbridge ├── Properties │ └── AssemblyInfo.cs ├── WindowSubclassing.cs └── WindowSubclassingCSharp.csproj ├── CONTRIBUTORS.txt ├── .hgignore ├── ..svnbridge └── .svnbridge ├── README.md ├── Widgets └── DateTimeWidget.rb ├── Config ├── 2-Program Rules.py ├── 1-General Settings.py └── 3-Hotkeys.rb ├── Docs └── API.txt └── Windawesome.sln /Helpers/Helpers.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boris-petrov/windawesome/HEAD/Helpers/Helpers.rc -------------------------------------------------------------------------------- /GlobalShellHook/GlobalShellHook.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boris-petrov/windawesome/HEAD/GlobalShellHook/GlobalShellHook.rc -------------------------------------------------------------------------------- /SystemTrayHook/SystemTrayHook.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boris-petrov/windawesome/HEAD/SystemTrayHook/SystemTrayHook.rc -------------------------------------------------------------------------------- /Windawesome/Images/Icon missing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boris-petrov/windawesome/HEAD/Windawesome/Images/Icon missing.png -------------------------------------------------------------------------------- /WindowSubclassing/WindowSubclassing.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boris-petrov/windawesome/HEAD/WindowSubclassing/WindowSubclassing.aps -------------------------------------------------------------------------------- /WindowSubclassing/WindowSubclassing.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boris-petrov/windawesome/HEAD/WindowSubclassing/WindowSubclassing.rc -------------------------------------------------------------------------------- /app_version.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1.4.2 4 | http://windawesome.codeplex.com 5 | 6 | -------------------------------------------------------------------------------- /lib/Needed files.txt: -------------------------------------------------------------------------------- 1 | IronPython.dll 2 | IronPython.Modules.dll 3 | IronRuby.dll 4 | IronRuby.Libraries.dll 5 | Microsoft.Dynamic.dll 6 | Microsoft.Scripting.dll 7 | -------------------------------------------------------------------------------- /Helpers/Helpers.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /GlobalShellHook/GlobalShellHook.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /SystemTrayHook/SystemTrayHook.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Windawesome/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WindowSubclassing/WindowSubclassing.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Windawesome/IPlugin.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Windawesome 3 | { 4 | public interface IPlugin 5 | { 6 | void InitializePlugin(Windawesome windawesome); 7 | 8 | void Dispose(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Helpers/Helpers.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #define HELPERS_API __declspec(dllexport) 5 | 6 | extern "C" { 7 | HELPERS_API void __cdecl RunApplicationNonElevated(const WCHAR*, const WCHAR*); 8 | } 9 | 10 | #undef HELPERS_API 11 | -------------------------------------------------------------------------------- /Helpers/dllmain.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | 4 | BOOL APIENTRY DllMain( HMODULE hModule, 5 | DWORD ul_reason_for_call, 6 | LPVOID lpReserved 7 | ) 8 | { 9 | return TRUE; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /Helpers/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignorebin 2 | -------------------------------------------------------------------------------- /SystemTrayHook/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignorebin 2 | -------------------------------------------------------------------------------- /WindowSubclassing/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignorebin 2 | -------------------------------------------------------------------------------- /SystemTrayHook/SystemTrayHook.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #define SYSTEMTRAYHOOK_API __declspec(dllexport) 5 | 6 | SYSTEMTRAYHOOK_API BOOL __cdecl RegisterSystemTrayHook(HWND hWnd); 7 | SYSTEMTRAYHOOK_API BOOL __cdecl UnregisterSystemTrayHook(); 8 | 9 | #undef SYSTEMTRAYHOOK_API 10 | -------------------------------------------------------------------------------- /TileLayout/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignorebin 2 | obj 3 | -------------------------------------------------------------------------------- /Windawesome/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignorebin 2 | obj 3 | -------------------------------------------------------------------------------- /Helpers/..svnbridge/Helpers.aps: -------------------------------------------------------------------------------- 1 | svn:mime-typeapplication/octet-stream -------------------------------------------------------------------------------- /Helpers/..svnbridge/Helpers.rc: -------------------------------------------------------------------------------- 1 | svn:mime-typeapplication/octet-stream -------------------------------------------------------------------------------- /ShortcutsManager/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignorebin 2 | obj 3 | -------------------------------------------------------------------------------- /GlobalShellHook/GlobalShellHook.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #define GLOBALSHELLHOOK_API __declspec(dllexport) 5 | 6 | GLOBALSHELLHOOK_API BOOL __cdecl RegisterGlobalShellHook(HWND handle); 7 | GLOBALSHELLHOOK_API BOOL __cdecl UnregisterGlobalShellHook(); 8 | 9 | #undef GLOBALSHELLHOOK_API 10 | -------------------------------------------------------------------------------- /Windawesome/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WindowSubclassingCSharp/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignorebin 2 | obj 3 | -------------------------------------------------------------------------------- /SystemTrayHook/..svnbridge/SystemTrayHook.aps: -------------------------------------------------------------------------------- 1 | svn:mime-typeapplication/octet-stream -------------------------------------------------------------------------------- /SystemTrayHook/..svnbridge/SystemTrayHook.rc: -------------------------------------------------------------------------------- 1 | svn:mime-typeapplication/octet-stream -------------------------------------------------------------------------------- /Windawesome/Images/..svnbridge/Icon missing.png: -------------------------------------------------------------------------------- 1 | svn:mime-typeapplication/octet-stream -------------------------------------------------------------------------------- /WindowSubclassing/..svnbridge/WindowSubclassing.aps: -------------------------------------------------------------------------------- 1 | svn:mime-typeapplication/octet-stream -------------------------------------------------------------------------------- /WindowSubclassing/..svnbridge/WindowSubclassing.rc: -------------------------------------------------------------------------------- 1 | svn:mime-typeapplication/octet-stream -------------------------------------------------------------------------------- /WindowSubclassing/WindowSubclassing.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #define WINDOWSUBCLASSING_API __declspec(dllexport) 5 | 6 | WINDOWSUBCLASSING_API BOOL __cdecl SubclassWindow(HWND hWnd, HWND window); 7 | WINDOWSUBCLASSING_API BOOL __cdecl UnsubclassWindow(HWND window); 8 | 9 | #undef WINDOWSUBCLASSING_API 10 | -------------------------------------------------------------------------------- /CONTRIBUTORS.txt: -------------------------------------------------------------------------------- 1 | THANKS TO: 2 | 3 | weiwen - network monitor widget implementation 4 | mkocubinski - xmonad-like functionality for multiple monitors 5 | vOSHoHpC - RAM monitor widget implementation 6 | daedric - reported a language bar widget bug 7 | joankaradimov - system tray widget refactoring and IronPython/IronRuby integration -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | lib/IronPython.Modules.dll 2 | lib/IronPython.dll 3 | lib/IronRuby.Libraries.dll 4 | lib/IronRuby.dll 5 | lib/Microsoft.Dynamic.dll 6 | lib/Microsoft.Scripting.dll 7 | bin/x64 8 | ShortcutsManager/obj 9 | TileLayout/obj 10 | Windawesome/obj 11 | WindowSubclassingCSharp/obj 12 | Windawesome.opensdf 13 | Windawesome.sdf 14 | -------------------------------------------------------------------------------- /WindowSubclassing/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GlobalHooksCPP.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /Helpers/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /GlobalShellHook/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /SystemTrayHook/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /WindowSubclassing/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /Helpers/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | // Windows Header Files: 11 | #include 12 | #include 13 | #include 14 | #include 15 | -------------------------------------------------------------------------------- /lib/..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignoreIronPython.Modules.dll 2 | IronPython.dll 3 | IronRuby.Libraries.dll 4 | IronRuby.dll 5 | Microsoft.Dynamic.dll 6 | Microsoft.Scripting.dll 7 | -------------------------------------------------------------------------------- /WindowSubclassing/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | -------------------------------------------------------------------------------- /SystemTrayHook/dllmain.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | 4 | extern HINSTANCE hInstance; 5 | 6 | BOOL APIENTRY DllMain( HMODULE hModule, 7 | DWORD ul_reason_for_call, 8 | LPVOID lpReserved 9 | ) 10 | { 11 | switch (ul_reason_for_call) 12 | { 13 | case DLL_PROCESS_ATTACH: 14 | hInstance = hModule; 15 | break; 16 | } 17 | return TRUE; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /SystemTrayHook/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | #include 14 | -------------------------------------------------------------------------------- /Windawesome/IBar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Windawesome 4 | { 5 | public interface IBar 6 | { 7 | void InitializeBar(Windawesome windawesome); 8 | void Dispose(); 9 | 10 | IntPtr Handle { get; } 11 | 12 | Monitor Monitor { get; } 13 | 14 | int GetBarHeight(); 15 | 16 | void OnClientWidthChanging(int newWidth); 17 | 18 | void Show(); 19 | void Hide(); 20 | 21 | void Refresh(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Helpers/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Helpers.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /SystemTrayHook/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by SystemTrayHook.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /WindowSubclassing/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by WindowSubclassing.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /GlobalShellHook/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by GlobalShellHook.rc 4 | // 5 | 6 | // Next default values for new objects 7 | // 8 | #ifdef APSTUDIO_INVOKED 9 | #ifndef APSTUDIO_READONLY_SYMBOLS 10 | #define _APS_NEXT_RESOURCE_VALUE 101 11 | #define _APS_NEXT_COMMAND_VALUE 40001 12 | #define _APS_NEXT_CONTROL_VALUE 1001 13 | #define _APS_NEXT_SYMED_VALUE 101 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /GlobalShellHook/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | 14 | 15 | 16 | // TODO: reference additional headers your program requires here 17 | -------------------------------------------------------------------------------- /Windawesome/Windawesome.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | publish\ 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | -------------------------------------------------------------------------------- /GlobalShellHook/dllmain.c: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "stdafx.h" 3 | 4 | extern HINSTANCE hInstance; 5 | 6 | BOOL APIENTRY DllMain( HMODULE hModule, 7 | DWORD ul_reason_for_call, 8 | LPVOID lpReserved 9 | ) 10 | { 11 | switch (ul_reason_for_call) 12 | { 13 | case DLL_PROCESS_ATTACH: 14 | hInstance = hModule; 15 | break; 16 | case DLL_THREAD_ATTACH: 17 | case DLL_THREAD_DETACH: 18 | case DLL_PROCESS_DETACH: 19 | break; 20 | } 21 | return TRUE; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /WindowSubclassing/dllmain.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | 4 | extern HINSTANCE hInstance; 5 | extern UINT START_WINDOW_PROC_MESSAGE; 6 | extern UINT STOP_WINDOW_PROC_MESSAGE; 7 | 8 | BOOL APIENTRY DllMain( HMODULE hModule, 9 | DWORD ul_reason_for_call, 10 | LPVOID lpReserved 11 | ) 12 | { 13 | switch (ul_reason_for_call) 14 | { 15 | case DLL_PROCESS_ATTACH: 16 | hInstance = hModule; 17 | if (!START_WINDOW_PROC_MESSAGE) 18 | { 19 | START_WINDOW_PROC_MESSAGE = RegisterWindowMessage(TEXT("START_WINDOW_PROC")); 20 | STOP_WINDOW_PROC_MESSAGE = RegisterWindowMessage(TEXT("STOP_WINDOW_PROC")); 21 | } 22 | break; 23 | } 24 | return TRUE; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /..svnbridge/.svnbridge: -------------------------------------------------------------------------------- 1 | svn:ignore*.sdf 2 | Old 3 | Windawesome.suo 4 | bin 5 | lib 6 | svn:ignore*.sdf 7 | Old 8 | Windawesome.opensdf 9 | Windawesome.suo 10 | bin 11 | lib 12 | svn:ignore*.sdf 13 | Old 14 | Windawesome.opensdf 15 | Windawesome.suo 16 | bin 17 | ipch 18 | lib 19 | svn:ignore*.sdf 20 | Old 21 | Windawesome.5.1.ReSharper 22 | Windawesome.5.1.ReSharper.user 23 | Windawesome.opensdf 24 | Windawesome.suo 25 | bin 26 | ipch 27 | lib 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Windawesome (pronounced - contrary to what you would expect from the way it is written - Windows-om, not Wind-awesome) is a highly customizable tiling/dynamic window manager with multi-monitor support for Windows, which works on top of explorer.exe and *not* as a shell replacement. It is heavily inspired by [bug.n](http://www.autohotkey.net/~joten/bug.n.html), but tries to go further. Windawesome is (mostly) written in C# and is scriptable and pluggable in IronRuby, IronPython and any .NET language that compiles down to an assembly. Requires .NET Framework 4 Client Profile, Visual C++ 2010 Redistributable and IronRuby/IronPython DLLs. The main bundle comes with 3 configuration files (2 in Python, 1 in Ruby), 3 layouts (2 built-in and one as a C# DLL), a couple of Plugins and many Widgets, one of which is written in Ruby. Works with 32- and 64-bit versions of Windows XP, Vista, 7, 8 and 8.1. Goes under the GNU General Public License version 2. 2 | -------------------------------------------------------------------------------- /Windawesome/ILayout.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Windawesome 3 | { 4 | public interface ILayout 5 | { 6 | string LayoutSymbol(); 7 | string LayoutName(); 8 | 9 | void Initialize(Workspace workspace); 10 | void Dispose(); 11 | 12 | /* 13 | * Should return whether Windawesome should restore a shared window's position if there 14 | * are no changes to the workspace. If there are, Reposition will be called anyway 15 | */ 16 | bool ShouldSaveAndRestoreSharedWindowsPosition(); 17 | 18 | /* 19 | * This is guaranteed to be called only when the workspace is visible 20 | */ 21 | void Reposition(); 22 | 23 | /* 24 | * The next four functions can be called when the workspace is visible, as well 25 | * as invisible 26 | */ 27 | void WindowMinimized(Window window); 28 | void WindowRestored(Window window); 29 | void WindowCreated(Window window); 30 | void WindowDestroyed(Window window); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Windawesome/FloatingLayout.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Windawesome 3 | { 4 | public sealed class FloatingLayout : ILayout 5 | { 6 | #region ILayout Members 7 | 8 | string ILayout.LayoutSymbol() 9 | { 10 | return "><>"; 11 | } 12 | 13 | public string LayoutName() 14 | { 15 | return "Floating"; 16 | } 17 | 18 | void ILayout.Initialize(Workspace workspace) 19 | { 20 | } 21 | 22 | void ILayout.Dispose() 23 | { 24 | } 25 | 26 | bool ILayout.ShouldSaveAndRestoreSharedWindowsPosition() 27 | { 28 | return true; 29 | } 30 | 31 | void ILayout.Reposition() 32 | { 33 | } 34 | 35 | void ILayout.WindowMinimized(Window window) 36 | { 37 | } 38 | 39 | void ILayout.WindowRestored(Window window) 40 | { 41 | } 42 | 43 | void ILayout.WindowCreated(Window window) 44 | { 45 | } 46 | 47 | void ILayout.WindowDestroyed(Window window) 48 | { 49 | } 50 | 51 | #endregion 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Windawesome/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.1 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Windawesome.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GlobalShellHook/GlobalShellHook.c: -------------------------------------------------------------------------------- 1 | // GlobalShellHook.cpp : Defines the exported functions for the DLL application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "GlobalShellHook.h" 6 | 7 | #pragma data_seg(".shared") 8 | #pragma comment(linker, "/SECTION:.shared,RWS") 9 | 10 | HWND applicationHandle = NULL; 11 | UINT globalShellHookMessage = 0; 12 | 13 | #pragma data_seg() 14 | 15 | HINSTANCE hInstance = NULL; 16 | static HHOOK hook = NULL; 17 | 18 | static LRESULT CALLBACK ShellHookProc(int code, WPARAM wParam, LPARAM lParam); 19 | 20 | BOOL RegisterGlobalShellHook(HWND hWnd) 21 | { 22 | applicationHandle = hWnd; 23 | 24 | globalShellHookMessage = RegisterWindowMessage(TEXT("GLOBAL_SHELL_HOOK")); 25 | 26 | return (hook = SetWindowsHookEx(WH_SHELL, (HOOKPROC) ShellHookProc, hInstance, 0)) != NULL; 27 | } 28 | 29 | BOOL UnregisterGlobalShellHook() 30 | { 31 | return hook != NULL ? UnhookWindowsHookEx(hook) : TRUE; 32 | } 33 | 34 | static LRESULT CALLBACK ShellHookProc(int code, WPARAM wParam, LPARAM lParam) 35 | { 36 | if (code == HSHELL_LANGUAGE) 37 | { 38 | PostMessage(applicationHandle, globalShellHookMessage, wParam, lParam); 39 | } 40 | 41 | return CallNextHookEx(NULL, code, wParam, lParam); 42 | } 43 | -------------------------------------------------------------------------------- /Windawesome/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Windawesome")] 8 | [assembly: AssemblyDescription("Dynamic Window Manager for Windows")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Boris Petrov")] 11 | [assembly: AssemblyProduct("Windawesome")] 12 | [assembly: AssemblyCopyright("Copyleft 2012")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("8b54cfff-9ef6-450f-8d22-5ce2c322c2d1")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.4.2.0")] 35 | [assembly: AssemblyFileVersion("1.4.2.0")] 36 | -------------------------------------------------------------------------------- /TileLayout/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Windawesome Tile Layout")] 9 | [assembly: AssemblyDescription("Tile Layout for Windawesome WM")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Boris Petrov")] 12 | [assembly: AssemblyProduct("Windawesome Tile Layout")] 13 | [assembly: AssemblyCopyright("Copyleft 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("10c42791-b4a2-4434-a0ab-6afeec30a1d1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.4.2.0")] 36 | [assembly: AssemblyFileVersion("1.4.0.0")] 37 | -------------------------------------------------------------------------------- /WindowSubclassingCSharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Windawesome Window Subclassing Plugin")] 9 | [assembly: AssemblyDescription("A Plugin for Windawesome WM")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Boris Petrov")] 12 | [assembly: AssemblyProduct("Windawesome Window Subclassing Plugin")] 13 | [assembly: AssemblyCopyright("Copyright © 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c363a771-9bf4-4bea-a878-b4896ffc2db9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.18.0")] 36 | [assembly: AssemblyFileVersion("1.0.18.0")] 37 | -------------------------------------------------------------------------------- /ShortcutsManager/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Windawesome ShortcutsManager Plugin")] 9 | [assembly: AssemblyDescription("Plugin for keyboard shortcuts for Windawesome WM")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Boris Petrov")] 12 | [assembly: AssemblyProduct("Windawesome ShortcutsManager Plugin")] 13 | [assembly: AssemblyCopyright("Copyleft 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("32df9c5e-9c0f-465b-8778-d3391234e897")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.4.2.0")] 36 | [assembly: AssemblyFileVersion("1.4.0.0")] 37 | -------------------------------------------------------------------------------- /Helpers/Helpers.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Resource Files 42 | 43 | 44 | -------------------------------------------------------------------------------- /SystemTrayHook/SystemTrayHook.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | #include "SystemTrayHook.h" 4 | 5 | #pragma data_seg(".shared") 6 | #pragma comment(linker, "/SECTION:.shared,RWS") 7 | 8 | HWND applicationHandle = NULL; 9 | 10 | #pragma data_seg() 11 | 12 | static HHOOK hook = NULL; 13 | HINSTANCE hInstance = NULL; 14 | 15 | static LRESULT CALLBACK HookCallback(int code, WPARAM wParam, LPARAM lParam); 16 | 17 | BOOL RegisterSystemTrayHook(HWND hWnd) 18 | { 19 | HWND hShell = FindWindow(L"Shell_TrayWnd", NULL); 20 | DWORD shellThread = GetWindowThreadProcessId(hShell, NULL); 21 | 22 | applicationHandle = hWnd; 23 | 24 | return (hook = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC) HookCallback, hInstance, shellThread)) != NULL; 25 | } 26 | 27 | BOOL UnregisterSystemTrayHook() 28 | { 29 | return hook != NULL ? UnhookWindowsHookEx(hook) : TRUE; 30 | } 31 | 32 | #define SH_TRAY_DATA 1 33 | 34 | typedef struct 35 | { 36 | DWORD dwHz; 37 | DWORD dwMessage; 38 | NOTIFYICONDATA nid; // this is a 64-bit structure, when running in 64-bit mode, but should be 32! 39 | } SHELLTRAYDATA; 40 | 41 | static LRESULT CALLBACK HookCallback(int code, WPARAM wParam, LPARAM lParam) 42 | { 43 | if (code >= 0) 44 | { 45 | CWPRETSTRUCT *pInfo = (CWPRETSTRUCT*) lParam; 46 | 47 | if (pInfo->message == WM_COPYDATA) 48 | { 49 | COPYDATASTRUCT* copyDataStruct = (COPYDATASTRUCT*) pInfo->lParam; 50 | if (copyDataStruct->dwData == SH_TRAY_DATA && 51 | ((SHELLTRAYDATA*) copyDataStruct->lpData)->dwHz == 0x34753423) 52 | { 53 | SendMessageTimeout(applicationHandle, WM_COPYDATA, pInfo->wParam, pInfo->lParam, 54 | SMTO_ABORTIFHUNG, 10000, NULL); 55 | } 56 | } 57 | } 58 | 59 | return CallNextHookEx(NULL, code, wParam, lParam); 60 | } 61 | -------------------------------------------------------------------------------- /SystemTrayHook/SystemTrayHook.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Resource Files 42 | 43 | 44 | -------------------------------------------------------------------------------- /WindowSubclassing/WindowSubclassing.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Resource Files 42 | 43 | 44 | -------------------------------------------------------------------------------- /Windawesome/UpdateChecker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Windows.Forms; 4 | using System.Xml; 5 | 6 | namespace Windawesome 7 | { 8 | public static class UpdateChecker 9 | { 10 | public static void CheckForUpdate() 11 | { 12 | const string xmlUrl = "https://raw.githubusercontent.com/boris-petrov/windawesome/master/app_version.xml"; 13 | 14 | Task.Factory.StartNew(() => 15 | { 16 | Version newVersion = null; 17 | string url = null; 18 | 19 | try 20 | { 21 | var xmlDocument = new XmlDocument(); 22 | xmlDocument.Load(xmlUrl); 23 | 24 | var versionNode = xmlDocument.SelectNodes("/Windawesome/version")[0]; 25 | newVersion = new Version(versionNode.InnerText); 26 | 27 | var urlNode = xmlDocument.SelectNodes("/Windawesome/url")[0]; 28 | url = urlNode.InnerText; 29 | } 30 | catch 31 | { 32 | } 33 | 34 | return Tuple.Create(newVersion, url); 35 | }).ContinueWith(t => 36 | { 37 | var newVersion = t.Result.Item1; 38 | var url = t.Result.Item2; 39 | 40 | if (newVersion != null) 41 | { 42 | var currentVersion = new Version(Application.ProductVersion); 43 | 44 | if (currentVersion.CompareTo(newVersion) < 0) 45 | { 46 | var result = MessageBox.Show( 47 | "There is a new version of Windawesome. Would you like to open the website to download it?", 48 | "New version available", 49 | MessageBoxButtons.YesNo, 50 | MessageBoxIcon.Question); 51 | if (result == DialogResult.Yes) 52 | { 53 | Utilities.RunApplication(url); 54 | } 55 | } 56 | } 57 | }, TaskScheduler.FromCurrentSynchronizationContext()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Windawesome/SeparatorWidget.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace Windawesome 6 | { 7 | public sealed class SeparatorWidget : IFixedWidthWidget 8 | { 9 | private Label label; 10 | private bool isLeft; 11 | private readonly string separator; 12 | private readonly Color backgroundColor; 13 | private readonly Color foregroundColor; 14 | 15 | public SeparatorWidget(string separator = "|", Color? backgroundColor = null, Color? foregroundColor = null) 16 | { 17 | this.separator = separator; 18 | 19 | this.backgroundColor = backgroundColor ?? Color.White; 20 | this.foregroundColor = foregroundColor ?? Color.Black; 21 | } 22 | 23 | #region IWidget Members 24 | 25 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 26 | { 27 | } 28 | 29 | void IWidget.InitializeWidget(Bar bar) 30 | { 31 | label = bar.CreateLabel(separator, 0); 32 | label.BackColor = backgroundColor; 33 | label.ForeColor = foregroundColor; 34 | label.TextAlign = ContentAlignment.MiddleCenter; 35 | } 36 | 37 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 38 | { 39 | this.isLeft = isLeft; 40 | 41 | return new[] { label }; 42 | } 43 | 44 | public void RepositionControls(int left, int right) 45 | { 46 | this.label.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.label.Width, 0); 47 | } 48 | 49 | int IWidget.GetLeft() 50 | { 51 | return label.Left; 52 | } 53 | 54 | int IWidget.GetRight() 55 | { 56 | return label.Right; 57 | } 58 | 59 | void IWidget.StaticDispose() 60 | { 61 | } 62 | 63 | void IWidget.Dispose() 64 | { 65 | } 66 | 67 | void IWidget.Refresh() 68 | { 69 | } 70 | 71 | #endregion 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /GlobalShellHook/GlobalShellHook.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | 43 | 44 | Resource Files 45 | 46 | 47 | -------------------------------------------------------------------------------- /Windawesome/InputLanguageChangerPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Windawesome 5 | { 6 | public class InputLanguageChangerPlugin : IPlugin 7 | { 8 | private readonly HashSet classNamesSet; 9 | private readonly Dictionary inputLanguages; 10 | private IntPtr currentForeground; 11 | 12 | public InputLanguageChangerPlugin(IEnumerable windowClassNames) 13 | { 14 | classNamesSet = new HashSet(windowClassNames); 15 | inputLanguages = new Dictionary(5); 16 | 17 | Workspace.WindowActivatedEvent += OnWindowActivatedEvent; 18 | } 19 | 20 | private void OnWindowActivatedEvent(IntPtr hWnd) 21 | { 22 | if (currentForeground != IntPtr.Zero) 23 | { 24 | SaveLayoutForWindow(currentForeground); 25 | } 26 | 27 | var className = NativeMethods.GetWindowClassName(hWnd); 28 | 29 | if (classNamesSet.Contains(className)) 30 | { 31 | IntPtr keyboardLayout; 32 | if (inputLanguages.TryGetValue(hWnd, out keyboardLayout)) 33 | { 34 | NativeMethods.SendNotifyMessage(hWnd, NativeMethods.WM_INPUTLANGCHANGEREQUEST, 35 | UIntPtr.Zero, keyboardLayout); 36 | } 37 | else 38 | { 39 | SaveLayoutForWindow(hWnd); 40 | } 41 | 42 | currentForeground = hWnd; 43 | } 44 | else 45 | { 46 | currentForeground = IntPtr.Zero; 47 | } 48 | } 49 | 50 | private void SaveLayoutForWindow(IntPtr window) 51 | { 52 | var keyboardLayout = NativeMethods.GetKeyboardLayout( 53 | NativeMethods.GetWindowThreadProcessId(window, IntPtr.Zero)); 54 | 55 | inputLanguages[window] = keyboardLayout; 56 | } 57 | 58 | #region IPlugin Members 59 | 60 | void IPlugin.InitializePlugin(Windawesome windawesome) 61 | { 62 | } 63 | 64 | void IPlugin.Dispose() 65 | { 66 | } 67 | 68 | #endregion 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Helpers/Helpers.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | #include "Helpers.h" 4 | 5 | static IShellDispatch2 *psd = NULL; 6 | 7 | void RunApplicationNonElevated(const WCHAR* path, const WCHAR* arguments) 8 | { 9 | if (psd == NULL) 10 | { 11 | IShellWindows *psw; 12 | if (!SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw)))) 13 | { 14 | return ; 15 | } 16 | HWND hwnd; 17 | IDispatch* pdisp; 18 | VARIANT vEmpty = {}; // VT_EMPTY 19 | if (S_OK != psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*) &hwnd, SWFO_NEEDDISPATCH, &pdisp)) 20 | { 21 | return ; 22 | } 23 | IShellBrowser *psb; 24 | 25 | if (!SUCCEEDED(IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb)))) 26 | { 27 | return ; 28 | } 29 | IShellView *psv; 30 | psb->QueryActiveShellView(&psv); 31 | 32 | IDispatch *pdispBackground; 33 | if (!SUCCEEDED(psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground)))) 34 | { 35 | return ; 36 | } 37 | IShellFolderViewDual *psfvd; 38 | if (!SUCCEEDED(pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd)))) 39 | { 40 | return ; 41 | } 42 | if (!SUCCEEDED(psfvd->get_Application(&pdisp))) 43 | { 44 | return ; 45 | } 46 | if (!SUCCEEDED(pdisp->QueryInterface(IID_PPV_ARGS(&psd)))) 47 | { 48 | return ; 49 | } 50 | } 51 | 52 | VARIANT args; 53 | VariantInit(&args); 54 | args.vt = VT_BSTR; 55 | args.bstrVal = SysAllocString(arguments); 56 | 57 | VARIANT dir; 58 | VariantInit(&dir); 59 | 60 | VARIANT operation; 61 | VariantInit(&operation); 62 | operation.vt = VT_BSTR; 63 | operation.bstrVal = SysAllocString(L"open"); 64 | 65 | VARIANT show; 66 | VariantInit(&show); 67 | show.vt = VT_INT; 68 | show.intVal = SW_SHOWDEFAULT; 69 | 70 | BSTR p = SysAllocString(path); 71 | psd->ShellExecuteW(p, args, dir, operation, show); 72 | 73 | SysFreeString(p); 74 | SysFreeString(operation.bstrVal); 75 | SysFreeString(args.bstrVal); 76 | } 77 | -------------------------------------------------------------------------------- /Widgets/DateTimeWidget.rb: -------------------------------------------------------------------------------- 1 | 2 | class DateTimeWidget 3 | include Windawesome::IFixedWidthWidget 4 | include System 5 | include System::Drawing 6 | include System::Windows::Forms 7 | include System::Linq 8 | 9 | def initialize string, prefix = " ", suffix = " ", back_color = nil, fore_color = nil, update_time = 30000, click = nil 10 | @background_color = back_color || Color.from_argb(0xC0, 0xC0, 0xC0) 11 | @foreground_color = fore_color || Color.black 12 | @string = string 13 | @click = click 14 | @prefix = prefix 15 | @suffix = suffix 16 | 17 | @update_timer = Timer.new 18 | @update_timer.interval = update_time 19 | @update_timer.tick do |s, ea| 20 | old_left = @label.left 21 | old_right = @label.right 22 | old_width = @label.width 23 | @label.text = @prefix + DateTime.now.to_string(@string) + @suffix 24 | @label.width = TextRenderer.measure_text(@label.text, @label.font).width 25 | if old_width != @label.width 26 | self.reposition_controls old_left, old_right 27 | @bar.do_fixed_width_widget_width_changed self 28 | end 29 | end 30 | end 31 | 32 | def static_initialize_widget windawesome; end 33 | 34 | def initialize_widget bar 35 | @bar = bar 36 | 37 | @label = bar.create_label @prefix + DateTime.now.to_string(@string) + @suffix, 0 38 | 39 | @label.text_align = ContentAlignment.middle_center 40 | @label.back_color = @background_color 41 | @label.fore_color = @foreground_color 42 | @label.click.add @click if @click 43 | 44 | @update_timer.start 45 | end 46 | 47 | def get_initial_controls is_left 48 | @is_left = is_left 49 | 50 | Enumerable.repeat @label, 1 51 | end 52 | 53 | def reposition_controls left, right 54 | @label.location = @is_left ? Point.new(left, 0) : Point.new(right - @label.width, 0) 55 | end 56 | 57 | def get_left 58 | @label.left 59 | end 60 | 61 | def get_right 62 | @label.right 63 | end 64 | 65 | def static_dispose; end 66 | 67 | def dispose; end 68 | 69 | def refresh; end 70 | 71 | end 72 | -------------------------------------------------------------------------------- /Windawesome/IWidget.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Windows.Forms; 3 | 4 | namespace Windawesome 5 | { 6 | public interface IWidget 7 | { 8 | /* 9 | * This is guaranteed to be called exactly once for every Widget type. Useful for 10 | * initializing any static data 11 | */ 12 | void StaticInitializeWidget(Windawesome windawesome); 13 | 14 | /* 15 | * This is called for every instance of the Widget and is given its Bar 16 | */ 17 | void InitializeWidget(Bar bar); 18 | 19 | void RepositionControls(int left, int right); 20 | 21 | /* 22 | * One should save left and right from the values in RepositionControls 23 | * as the Bar can request them at any point. Even more - the Bar gives -1 for one of the 24 | * two values if the Widget is with FixedWidth, but the Bar will expect valid values for 25 | * both, so make sure you save and initialize them properly 26 | */ 27 | int GetLeft(); 28 | 29 | int GetRight(); 30 | 31 | /* 32 | * This is guaranteed to be called exactly once for every Widget type. Useful for 33 | * disposing of some shared resources 34 | */ 35 | void StaticDispose(); 36 | 37 | /* 38 | * This is called for every instance of the Widget and is given its Bar 39 | */ 40 | void Dispose(); 41 | 42 | void Refresh(); 43 | } 44 | 45 | public interface ISpanWidget : IWidget 46 | { 47 | /* 48 | * GetInitialControls is called only once in the beginning. After that, 49 | * when any changes occur, RepositionControls will be called 50 | */ 51 | IEnumerable GetInitialControls(); 52 | } 53 | 54 | public interface IFixedWidthWidget : IWidget 55 | { 56 | /* 57 | * GetInitialControls is called only once in the beginning. After that, 58 | * when any changes occur, RepositionControls will be called 59 | * 60 | * The argument isLeft specifies whether the Widget is on the left or the right side of the Bar 61 | */ 62 | IEnumerable GetInitialControls(bool isLeft); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Windawesome/SystemAndProcessInformation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace Windawesome 6 | { 7 | public static class SystemAndProcessInformation 8 | { 9 | public static readonly bool isRunningElevated; 10 | public static readonly bool isAtLeastVista; 11 | public static readonly bool isAtLeast7; 12 | public static readonly Size smallIconSize; 13 | public static readonly IntPtr taskbarButtonsWindowHandle; 14 | public static readonly IntPtr taskbarHandle; 15 | public static readonly IntPtr startButtonHandle; 16 | public static readonly IntPtr trayHandle; 17 | public static readonly IntPtr hiddenTrayHandle; 18 | 19 | static SystemAndProcessInformation() 20 | { 21 | isAtLeastVista = Environment.OSVersion.Version.Major >= 6; 22 | isAtLeast7 = isAtLeastVista && Environment.OSVersion.Version.Minor >= 1; 23 | 24 | isRunningElevated = NativeMethods.IsCurrentProcessElevatedInRespectToShell(); 25 | 26 | smallIconSize = SystemInformation.SmallIconSize; 27 | 28 | taskbarButtonsWindowHandle = taskbarHandle; 29 | taskbarButtonsWindowHandle = NativeMethods.FindWindowEx(taskbarButtonsWindowHandle, IntPtr.Zero, "ReBarWindow32", ""); 30 | taskbarButtonsWindowHandle = NativeMethods.FindWindowEx(taskbarButtonsWindowHandle, IntPtr.Zero, "MSTaskSwWClass", "Running Applications"); 31 | 32 | taskbarHandle = NativeMethods.FindWindow("Shell_TrayWnd", null); 33 | if (isAtLeastVista) 34 | { 35 | startButtonHandle = NativeMethods.FindWindow("Button", "Start"); 36 | } 37 | 38 | trayHandle = FindTrayHandle(); 39 | if (isAtLeast7) 40 | { 41 | hiddenTrayHandle = FindHiddenTrayHandle(); 42 | } 43 | } 44 | 45 | private static IntPtr FindTrayHandle() 46 | { 47 | var hWnd = NativeMethods.FindWindowEx(taskbarHandle, IntPtr.Zero, "TrayNotifyWnd", null); 48 | hWnd = NativeMethods.FindWindowEx(hWnd, IntPtr.Zero, "SysPager", null); 49 | return NativeMethods.FindWindowEx(hWnd, IntPtr.Zero, "ToolbarWindow32", null); 50 | } 51 | 52 | private static IntPtr FindHiddenTrayHandle() 53 | { 54 | var hWnd = NativeMethods.FindWindow("NotifyIconOverflowWindow", null); 55 | return NativeMethods.FindWindowEx(hWnd, IntPtr.Zero, "ToolbarWindow32", null); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Windawesome/HashMultiSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Windawesome 4 | { 5 | public sealed class HashMultiSet : IEnumerable 6 | { 7 | private readonly Dictionary set; 8 | private sealed class BoxedInt 9 | { 10 | public int i = 1; 11 | } 12 | 13 | public HashMultiSet(IEqualityComparer comparer = null) 14 | { 15 | set = new Dictionary(comparer); 16 | } 17 | 18 | public AddResult Add(T item) 19 | { 20 | BoxedInt count; 21 | if (set.TryGetValue(item, out count)) 22 | { 23 | count.i++; 24 | return AddResult.Added; 25 | } 26 | else 27 | { 28 | set[item] = new BoxedInt(); 29 | return AddResult.AddedFirst; 30 | } 31 | } 32 | 33 | public AddResult AddUnique(T item) 34 | { 35 | if (set.ContainsKey(item)) 36 | { 37 | return AddResult.AlreadyContained; 38 | } 39 | else 40 | { 41 | set[item] = new BoxedInt(); 42 | return AddResult.AddedFirst; 43 | } 44 | } 45 | 46 | public RemoveResult Remove(T item) 47 | { 48 | BoxedInt count; 49 | if (set.TryGetValue(item, out count)) 50 | { 51 | if (count.i == 1) 52 | { 53 | set.Remove(item); 54 | return RemoveResult.RemovedLast; 55 | } 56 | else 57 | { 58 | count.i--; 59 | return RemoveResult.Removed; 60 | } 61 | } 62 | 63 | return RemoveResult.NotFound; 64 | } 65 | 66 | public RemoveResult RemoveAll(T item) 67 | { 68 | return set.Remove(item) ? RemoveResult.RemovedLast : RemoveResult.NotFound; 69 | } 70 | 71 | public bool Contains(T item) 72 | { 73 | return set.ContainsKey(item); 74 | } 75 | 76 | public enum AddResult : byte 77 | { 78 | AddedFirst, 79 | Added, 80 | AlreadyContained 81 | } 82 | 83 | public enum RemoveResult : byte 84 | { 85 | NotFound, 86 | RemovedLast, 87 | Removed 88 | } 89 | 90 | public void Clear() 91 | { 92 | set.Clear(); 93 | } 94 | 95 | #region IEnumerable Members 96 | 97 | public IEnumerator GetEnumerator() 98 | { 99 | return set.Keys.GetEnumerator(); 100 | } 101 | 102 | #endregion 103 | 104 | #region IEnumerable Members 105 | 106 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 107 | { 108 | return set.Keys.GetEnumerator(); 109 | } 110 | 111 | #endregion 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Windawesome/CurrentlyPlayingWidget.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace Windawesome 6 | { 7 | public sealed class CurrentlyPlayingWidget : IFixedWidthWidget 8 | { 9 | private Bar bar; 10 | 11 | private Label label; 12 | private bool isLeft; 13 | private readonly string windowClassName; 14 | private readonly Color backgroundColor; 15 | private readonly Color foregroundColor; 16 | 17 | public CurrentlyPlayingWidget(string windowClassName = "{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}", 18 | Color? backgroundColor = null, Color? foregroundColor = null) 19 | { 20 | this.windowClassName = windowClassName; 21 | 22 | this.backgroundColor = backgroundColor ?? Color.White; 23 | this.foregroundColor = foregroundColor ?? Color.Black; 24 | } 25 | 26 | private void WindawesomeOnWindowTitleOrIconChanged(Workspace workspace, Window window, string newText, Bitmap newIcon) 27 | { 28 | if (window.className == windowClassName) 29 | { 30 | var oldLeft = label.Left; 31 | var oldRight = label.Right; 32 | 33 | var oldWidth = label.Width; 34 | var newWidth = TextRenderer.MeasureText(newText, label.Font).Width; 35 | 36 | label.Text = newText; 37 | label.Width = newWidth; 38 | 39 | if (oldWidth != newWidth) 40 | { 41 | this.RepositionControls(oldLeft, oldRight); 42 | bar.DoFixedWidthWidgetWidthChanged(this); 43 | } 44 | } 45 | } 46 | 47 | #region IWidget Members 48 | 49 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 50 | { 51 | } 52 | 53 | void IWidget.InitializeWidget(Bar bar) 54 | { 55 | this.bar = bar; 56 | 57 | Windawesome.WindowTitleOrIconChanged += WindawesomeOnWindowTitleOrIconChanged; 58 | 59 | var hWnd = NativeMethods.FindWindow(windowClassName, null); 60 | var text = NativeMethods.GetText(hWnd); 61 | label = bar.CreateLabel(text, 0); 62 | label.BackColor = backgroundColor; 63 | label.ForeColor = foregroundColor; 64 | label.TextAlign = ContentAlignment.MiddleCenter; 65 | } 66 | 67 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 68 | { 69 | this.isLeft = isLeft; 70 | 71 | return new[] { label }; 72 | } 73 | 74 | public void RepositionControls(int left, int right) 75 | { 76 | this.label.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.label.Width, 0); 77 | } 78 | 79 | int IWidget.GetLeft() 80 | { 81 | return label.Left; 82 | } 83 | 84 | int IWidget.GetRight() 85 | { 86 | return label.Right; 87 | } 88 | 89 | void IWidget.StaticDispose() 90 | { 91 | } 92 | 93 | void IWidget.Dispose() 94 | { 95 | } 96 | 97 | void IWidget.Refresh() 98 | { 99 | } 100 | 101 | #endregion 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Windawesome/RamMonitorWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | namespace Windawesome 8 | { 9 | public sealed class RamMonitorWidget : IFixedWidthWidget 10 | { 11 | private Bar bar; 12 | 13 | private Label label; 14 | private bool isLeft; 15 | private readonly PerformanceCounter counter; 16 | private readonly Timer updateTimer; 17 | private readonly string prefix; 18 | private readonly string postfix; 19 | private readonly Color backgroundColor; 20 | private readonly Color foregroundColor; 21 | 22 | public RamMonitorWidget(string prefix = "RAM:", string postfix = "%", int updateTime = 1000, 23 | Color? backgroundColor = null, Color? foregroundColor = null) 24 | { 25 | updateTimer = new Timer { Interval = updateTime }; 26 | updateTimer.Tick += OnTimerTick; 27 | 28 | this.prefix = prefix; 29 | this.postfix = postfix; 30 | 31 | this.backgroundColor = backgroundColor ?? Color.White; 32 | this.foregroundColor = foregroundColor ?? Color.Black; 33 | 34 | counter = new PerformanceCounter("Memory", "% Committed Bytes In Use"); 35 | } 36 | 37 | private void OnTimerTick(object sender, EventArgs e) 38 | { 39 | var oldLeft = label.Left; 40 | var oldRight = label.Right; 41 | var nextValue = counter.NextValue(); 42 | 43 | label.Text = prefix + nextValue.ToString("00") + postfix; 44 | 45 | if (Math.Abs(nextValue - 100) < 0.00001) 46 | { 47 | this.RepositionControls(oldLeft, oldRight); 48 | bar.DoFixedWidthWidgetWidthChanged(this); 49 | } 50 | } 51 | 52 | #region IWidget Members 53 | 54 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 55 | { 56 | } 57 | 58 | void IWidget.InitializeWidget(Bar bar) 59 | { 60 | this.bar = bar; 61 | 62 | label = bar.CreateLabel(prefix + counter.NextValue().ToString("00") + postfix, 0); 63 | label.BackColor = backgroundColor; 64 | label.ForeColor = foregroundColor; 65 | label.TextAlign = ContentAlignment.MiddleCenter; 66 | 67 | bar.BarShown += () => updateTimer.Start(); 68 | bar.BarHidden += () => updateTimer.Stop(); 69 | } 70 | 71 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 72 | { 73 | this.isLeft = isLeft; 74 | 75 | return new[] { label }; 76 | } 77 | 78 | public void RepositionControls(int left, int right) 79 | { 80 | this.label.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.label.Width, 0); 81 | } 82 | 83 | int IWidget.GetLeft() 84 | { 85 | return label.Left; 86 | } 87 | 88 | int IWidget.GetRight() 89 | { 90 | return label.Right; 91 | } 92 | 93 | void IWidget.StaticDispose() 94 | { 95 | } 96 | 97 | void IWidget.Dispose() 98 | { 99 | } 100 | 101 | void IWidget.Refresh() 102 | { 103 | } 104 | 105 | #endregion 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Windawesome/CPUMonitorWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | namespace Windawesome 8 | { 9 | public sealed class CpuMonitorWidget : IFixedWidthWidget 10 | { 11 | private Bar bar; 12 | 13 | private Label label; 14 | private bool isLeft; 15 | private readonly PerformanceCounter counter; 16 | private readonly Timer updateTimer; 17 | private readonly string prefix; 18 | private readonly string postfix; 19 | private readonly Color backgroundColor; 20 | private readonly Color foregroundColor; 21 | 22 | public CpuMonitorWidget(string prefix = "CPU:", string postfix = "%", int updateTime = 1000, 23 | Color? backgroundColor = null, Color? foregroundColor = null) 24 | { 25 | updateTimer = new Timer { Interval = updateTime }; 26 | updateTimer.Tick += OnTimerTick; 27 | 28 | this.prefix = prefix; 29 | this.postfix = postfix; 30 | 31 | this.backgroundColor = backgroundColor ?? Color.White; 32 | this.foregroundColor = foregroundColor ?? Color.Black; 33 | 34 | counter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); 35 | } 36 | 37 | private void OnTimerTick(object sender, EventArgs e) 38 | { 39 | var oldLeft = label.Left; 40 | var oldRight = label.Right; 41 | var nextValue = counter.NextValue(); 42 | 43 | label.Text = prefix + nextValue.ToString("00") + postfix; 44 | 45 | if (Math.Abs(nextValue - 100) < 0.00001) 46 | { 47 | this.RepositionControls(oldLeft, oldRight); 48 | bar.DoFixedWidthWidgetWidthChanged(this); 49 | } 50 | } 51 | 52 | #region IWidget Members 53 | 54 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 55 | { 56 | } 57 | 58 | void IWidget.InitializeWidget(Bar bar) 59 | { 60 | this.bar = bar; 61 | 62 | label = bar.CreateLabel(prefix + counter.NextValue().ToString("00") + postfix, 0); 63 | label.BackColor = backgroundColor; 64 | label.ForeColor = foregroundColor; 65 | label.TextAlign = ContentAlignment.MiddleCenter; 66 | 67 | bar.BarShown += () => updateTimer.Start(); 68 | bar.BarHidden += () => updateTimer.Stop(); 69 | } 70 | 71 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 72 | { 73 | this.isLeft = isLeft; 74 | 75 | return new[] { label }; 76 | } 77 | 78 | public void RepositionControls(int left, int right) 79 | { 80 | this.label.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.label.Width, 0); 81 | } 82 | 83 | int IWidget.GetLeft() 84 | { 85 | return label.Left; 86 | } 87 | 88 | int IWidget.GetRight() 89 | { 90 | return label.Right; 91 | } 92 | 93 | void IWidget.StaticDispose() 94 | { 95 | } 96 | 97 | void IWidget.Dispose() 98 | { 99 | } 100 | 101 | void IWidget.Refresh() 102 | { 103 | } 104 | 105 | #endregion 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Windawesome/LayoutWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | namespace Windawesome 7 | { 8 | public sealed class LayoutWidget : IFixedWidthWidget 9 | { 10 | private Label layoutLabel; 11 | private readonly Color backgroundColor; 12 | private readonly Color foregroundColor; 13 | private readonly Action onClick; 14 | private Bar bar; 15 | private bool isLeft; 16 | 17 | public LayoutWidget(Color? backgroundColor = null, Color? foregroundColor = null, Action onClick = null) 18 | { 19 | this.backgroundColor = backgroundColor ?? Color.FromArgb(0x99, 0xB4, 0xD1); 20 | this.foregroundColor = foregroundColor ?? Color.Black; 21 | 22 | this.onClick = onClick; 23 | } 24 | 25 | private void OnWorkspaceLayoutChanged(Workspace workspace) 26 | { 27 | if (workspace.Monitor == bar.Monitor && workspace.IsWorkspaceVisible) 28 | { 29 | var oldLeft = layoutLabel.Left; 30 | var oldRight = layoutLabel.Right; 31 | var oldWidth = layoutLabel.Width; 32 | layoutLabel.Text = workspace.Layout.LayoutSymbol(); 33 | layoutLabel.Width = TextRenderer.MeasureText(layoutLabel.Text, layoutLabel.Font).Width; 34 | if (layoutLabel.Width != oldWidth) 35 | { 36 | this.RepositionControls(oldLeft, oldRight); 37 | bar.DoFixedWidthWidgetWidthChanged(this); 38 | } 39 | } 40 | } 41 | 42 | #region IWidget Members 43 | 44 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 45 | { 46 | } 47 | 48 | void IWidget.InitializeWidget(Bar bar) 49 | { 50 | this.bar = bar; 51 | 52 | bar.BarShown += () => OnWorkspaceLayoutChanged(bar.Monitor.CurrentVisibleWorkspace); 53 | 54 | Workspace.LayoutUpdated += () => OnWorkspaceLayoutChanged(bar.Monitor.CurrentVisibleWorkspace); 55 | Workspace.WorkspaceShown += OnWorkspaceLayoutChanged; 56 | Workspace.WorkspaceLayoutChanged += (ws, _) => OnWorkspaceLayoutChanged(ws); 57 | 58 | layoutLabel = bar.CreateLabel("", 0); 59 | layoutLabel.TextAlign = ContentAlignment.MiddleCenter; 60 | layoutLabel.BackColor = backgroundColor; 61 | layoutLabel.ForeColor = foregroundColor; 62 | if (onClick != null) 63 | { 64 | layoutLabel.Click += (unused1, unused2) => onClick(); 65 | } 66 | } 67 | 68 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 69 | { 70 | this.isLeft = isLeft; 71 | 72 | return new Control[] { layoutLabel }; 73 | } 74 | 75 | public void RepositionControls(int left, int right) 76 | { 77 | this.layoutLabel.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.layoutLabel.Width, 0); 78 | } 79 | 80 | int IWidget.GetLeft() 81 | { 82 | return layoutLabel.Left; 83 | } 84 | 85 | int IWidget.GetRight() 86 | { 87 | return layoutLabel.Right; 88 | } 89 | 90 | void IWidget.StaticDispose() 91 | { 92 | } 93 | 94 | void IWidget.Dispose() 95 | { 96 | } 97 | 98 | void IWidget.Refresh() 99 | { 100 | } 101 | 102 | #endregion 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Windawesome/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.1 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Windawesome.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Windawesome.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | internal static System.Drawing.Bitmap Icon_missing { 64 | get { 65 | object obj = ResourceManager.GetObject("Icon_missing", resourceCulture); 66 | return ((System.Drawing.Bitmap)(obj)); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /WindowSubclassing/WindowSubclassing.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | #include "WindowSubclassing.h" 4 | 5 | #pragma data_seg(".shared") 6 | #pragma comment(linker, "/SECTION:.shared,RWS") 7 | 8 | HWND applicationHandle = NULL; 9 | 10 | UINT START_WINDOW_PROC_MESSAGE = 0; 11 | UINT STOP_WINDOW_PROC_MESSAGE = 0; 12 | 13 | #pragma data_seg() 14 | 15 | HINSTANCE hInstance; 16 | static WNDPROC oldWndProc = NULL; 17 | static BOOL isListening; 18 | 19 | static LRESULT CALLBACK CallWndRetProc(int code, WPARAM wParam, LPARAM lParam); 20 | static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 21 | 22 | BOOL SubclassWindow(HWND hWnd, HWND window) 23 | { 24 | HHOOK hook = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC) CallWndRetProc, hInstance, GetWindowThreadProcessId(window, NULL)); 25 | if (!hook) 26 | { 27 | return FALSE; 28 | } 29 | applicationHandle = hWnd; 30 | SendMessage(window, START_WINDOW_PROC_MESSAGE, 0, 0); 31 | UnhookWindowsHookEx(hook); 32 | return TRUE; 33 | } 34 | 35 | BOOL UnsubclassWindow(HWND window) 36 | { 37 | HHOOK hook = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC) CallWndRetProc, hInstance, GetWindowThreadProcessId(window, NULL)); 38 | if (!hook) 39 | { 40 | return FALSE; 41 | } 42 | SendMessage(window, STOP_WINDOW_PROC_MESSAGE, 0, 0); 43 | UnhookWindowsHookEx(hook); 44 | return TRUE; 45 | } 46 | 47 | static LRESULT CALLBACK CallWndRetProc(int code, WPARAM wParam, LPARAM lParam) 48 | { 49 | if (code >= 0) 50 | { 51 | if (((CWPRETSTRUCT*) lParam)->message == START_WINDOW_PROC_MESSAGE) 52 | { 53 | WCHAR library[MAX_PATH]; 54 | GetModuleFileName(hInstance, library, MAX_PATH); 55 | LoadLibrary(library); 56 | 57 | isListening = FALSE; // because on the current workspace the window may need to be movable/resizable 58 | oldWndProc = (WNDPROC) SetWindowLongPtr(((CWPRETSTRUCT*) lParam)->hwnd, GWLP_WNDPROC, (LONG_PTR) WindowProc); 59 | if (!oldWndProc) 60 | { 61 | FreeLibrary(hInstance); 62 | } 63 | return TRUE; 64 | } 65 | if (((CWPRETSTRUCT*) lParam)->message == STOP_WINDOW_PROC_MESSAGE) 66 | { 67 | if (oldWndProc && SetWindowLongPtr(((CWPRETSTRUCT*) lParam)->hwnd, GWLP_WNDPROC, (LONG_PTR) oldWndProc)) 68 | { 69 | FreeLibrary(hInstance); 70 | oldWndProc = NULL; 71 | } 72 | return TRUE; 73 | } 74 | } 75 | 76 | return CallNextHookEx(NULL, code, wParam, lParam); 77 | } 78 | 79 | static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 80 | { 81 | if (msg == START_WINDOW_PROC_MESSAGE) 82 | { 83 | isListening = TRUE; 84 | return TRUE; 85 | } 86 | if (isListening) 87 | { 88 | if (msg == STOP_WINDOW_PROC_MESSAGE) 89 | { 90 | isListening = FALSE; 91 | return TRUE; 92 | } 93 | switch (msg) 94 | { 95 | case WM_MOVING: 96 | case WM_SIZING: 97 | GetWindowRect(hwnd, (RECT*) lParam); 98 | return TRUE; 99 | case WM_NCLBUTTONDBLCLK: 100 | if (wParam == HTCAPTION) 101 | { 102 | return 0; 103 | } 104 | break; 105 | case WM_SYSCOMMAND: 106 | if (wParam == 0xF012 || wParam == SC_RESTORE || wParam == SC_MOVE || wParam == SC_SIZE) 107 | { 108 | return 0; 109 | } 110 | } 111 | } 112 | 113 | return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); 114 | } 115 | -------------------------------------------------------------------------------- /Windawesome/NetworkMonitorWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.NetworkInformation; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | namespace Windawesome 8 | { 9 | public sealed class NetworkMonitorWidget : IFixedWidthWidget 10 | { 11 | private Bar bar; 12 | 13 | private Label label; 14 | private bool isLeft; 15 | private readonly Timer updateTimer; 16 | private readonly Color backgroundColor; 17 | private readonly Color foregroundColor; 18 | private long oldReceived; 19 | private long oldSent; 20 | private NetworkInterface networkInterface; 21 | private int updateDuration; 22 | 23 | public NetworkMonitorWidget(int interfaceId = 0, int updateTime = 1000, 24 | Color? backgroundColor = null, Color? foregroundColor = null) 25 | { 26 | this.backgroundColor = backgroundColor ?? Color.White; 27 | this.foregroundColor = foregroundColor ?? Color.Black; 28 | 29 | if (!NetworkInterface.GetIsNetworkAvailable()) 30 | { 31 | return; 32 | } 33 | 34 | updateDuration = updateTime; 35 | updateTimer = new Timer { Interval = updateTime }; 36 | updateTimer.Tick += OnTimerTick; 37 | 38 | networkInterface = NetworkInterface.GetAllNetworkInterfaces()[interfaceId]; 39 | oldReceived = networkInterface.GetIPv4Statistics().BytesReceived; 40 | oldSent = networkInterface.GetIPv4Statistics().BytesSent; 41 | } 42 | 43 | private void OnTimerTick(object sender, EventArgs e) 44 | { 45 | var oldLeft = label.Left; 46 | var oldRight = label.Right; 47 | 48 | var curReceived = networkInterface.GetIPv4Statistics().BytesReceived; 49 | var downSpeed = ((float) (curReceived - oldReceived)) / updateDuration * 1000 / 1024; 50 | var curSent = networkInterface.GetIPv4Statistics().BytesSent; 51 | var upSpeed = ((float) (curSent - oldSent)) / updateDuration * 1000 / 1024; 52 | 53 | var oldWidth = label.Width; 54 | label.Text = string.Format("\u2193{0}{1} \u2191{2}{3}", ((downSpeed > 999) ? downSpeed / 1024 : downSpeed).ToString("0.0"), 55 | ((downSpeed > 999) ? "M" : "k"), ((upSpeed > 999) ? upSpeed / 1024 : upSpeed).ToString("0.0"), ((upSpeed > 999) ? "M" : "k")); 56 | var newWidth = TextRenderer.MeasureText(label.Text, label.Font).Width; 57 | label.Width = newWidth; 58 | 59 | if (oldWidth != newWidth) 60 | { 61 | this.RepositionControls(oldLeft, oldRight); 62 | bar.DoFixedWidthWidgetWidthChanged(this); 63 | } 64 | 65 | oldSent = curSent; 66 | oldReceived = curReceived; 67 | } 68 | 69 | #region IWidget Members 70 | 71 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 72 | { 73 | } 74 | 75 | void IWidget.InitializeWidget(Bar bar) 76 | { 77 | this.bar = bar; 78 | 79 | label = bar.CreateLabel("", 0); 80 | label.BackColor = backgroundColor; 81 | label.ForeColor = foregroundColor; 82 | label.TextAlign = ContentAlignment.MiddleCenter; 83 | 84 | bar.BarShown += () => updateTimer.Start(); 85 | bar.BarHidden += () => updateTimer.Stop(); 86 | } 87 | 88 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 89 | { 90 | this.isLeft = isLeft; 91 | 92 | return new[] { label }; 93 | } 94 | 95 | public void RepositionControls(int left, int right) 96 | { 97 | this.label.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.label.Width, 0); 98 | } 99 | 100 | int IWidget.GetLeft() 101 | { 102 | return label.Left; 103 | } 104 | 105 | int IWidget.GetRight() 106 | { 107 | return label.Right; 108 | } 109 | 110 | void IWidget.StaticDispose() 111 | { 112 | } 113 | 114 | void IWidget.Dispose() 115 | { 116 | } 117 | 118 | void IWidget.Refresh() 119 | { 120 | } 121 | 122 | #endregion 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Windawesome/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Linq; 4 | using System.Runtime.CompilerServices; 5 | using System.Threading; 6 | using System.Windows.Forms; 7 | 8 | [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] 9 | 10 | namespace Windawesome 11 | { 12 | static class Program 13 | { 14 | private static Windawesome windawesome; 15 | 16 | [STAThread] 17 | static void Main() 18 | { 19 | bool createdNew; 20 | using (new Mutex(true, "{BCDA45B7-407E-43F3-82FB-D1F6D6D093FF}", out createdNew)) 21 | { 22 | if (createdNew) // if the mutex was taken successfully, i.e. this is the first instance of the app running 23 | { 24 | SetPriorities(); 25 | 26 | Application.EnableVisualStyles(); 27 | Application.SetCompatibleTextRenderingDefault(false); 28 | 29 | // set exception handling 30 | Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 31 | Application.ThreadException += OnApplicationThreadException; 32 | AppDomain.CurrentDomain.UnhandledException += (_, e) => OnException(e.ExceptionObject as Exception); 33 | 34 | windawesome = new Windawesome(); 35 | Application.Run(new WindawesomeApplicationContext()); 36 | 37 | Application.ThreadException -= OnApplicationThreadException; 38 | } 39 | } 40 | } 41 | 42 | private static void SetPriorities() 43 | { 44 | Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; 45 | Thread.CurrentThread.Priority = ThreadPriority.Highest; 46 | 47 | if (SystemAndProcessInformation.isAtLeastVista) 48 | { 49 | var currentProcessHandle = NativeMethods.GetCurrentProcess(); 50 | 51 | var defaultMemoryPriority = NativeMethods.DefaultMemoryPriority; 52 | NativeMethods.NtSetInformationProcess(currentProcessHandle, NativeMethods.ProcessInformationMemoryPriority, 53 | ref defaultMemoryPriority, sizeof (uint)); 54 | 55 | var defaultIOPriority = NativeMethods.DefaultIOPriority; 56 | NativeMethods.NtSetInformationProcess(currentProcessHandle, NativeMethods.ProcessInformationIOPriority, 57 | ref defaultIOPriority, sizeof (uint)); 58 | } 59 | } 60 | 61 | private static void OnApplicationThreadException(object sender, ThreadExceptionEventArgs e) 62 | { 63 | OnException(e.Exception); 64 | } 65 | 66 | private static void OnException(Exception e) 67 | { 68 | System.IO.File.AppendAllLines("log.txt", new[] 69 | { 70 | "------------------------------------", 71 | DateTime.Now.ToString(), 72 | "Assemblies:", 73 | System.Reflection.Assembly.GetExecutingAssembly().FullName 74 | }. 75 | Concat(System.Reflection.Assembly.GetExecutingAssembly().GetReferencedAssemblies().Select(a => a.FullName)). 76 | Concat(new[] 77 | { 78 | "", 79 | "OS: " + Environment.OSVersion.VersionString, 80 | "CLR: " + Environment.Version.ToString(3), 81 | "64-bit OS: " + Environment.Is64BitOperatingSystem, 82 | "64-bit process: " + Environment.Is64BitProcess, 83 | "Elevated: " + SystemAndProcessInformation.isRunningElevated, 84 | e.ToString(), 85 | "Inner Exception:", 86 | e.InnerException != null ? e.InnerException.ToString() : "none" 87 | })); 88 | 89 | if (windawesome != null) 90 | { 91 | MessageBox.Show("An exception has occurred. Windawesome will now close. " + 92 | "Please see the log file in the program directory and post an issue on the website " + 93 | "if you think this is a bug.", 94 | "Exception occurred"); 95 | windawesome.Quit(); 96 | } 97 | } 98 | 99 | private class WindawesomeApplicationContext : ApplicationContext 100 | { 101 | public WindawesomeApplicationContext() 102 | { 103 | Windawesome.WindawesomeExiting += this.ExitThread; 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Windawesome/LaptopBatteryMonitorWidget.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace Windawesome 6 | { 7 | public sealed class LaptopBatteryMonitorWidget : IFixedWidthWidget 8 | { 9 | private Bar bar; 10 | 11 | private Label label; 12 | private bool isLeft; 13 | private readonly Timer updateTimer; 14 | private readonly string textForCharging; 15 | private readonly string textForNotCharging; 16 | private readonly string prefix; 17 | private readonly string postfix; 18 | private readonly Color backgroundColor; 19 | private readonly Color foregroundColor; 20 | 21 | public LaptopBatteryMonitorWidget(string textForCharging = "C", string textForNotCharging = "B", 22 | string prefix = " ", string postfix = "%", int updateTime = 60000, 23 | Color? backgroundColor = null, Color? foregroundColor = null) 24 | { 25 | updateTimer = new Timer { Interval = updateTime }; 26 | updateTimer.Tick += OnTimerTick; 27 | 28 | this.textForCharging = textForCharging; 29 | this.textForNotCharging = textForNotCharging; 30 | 31 | this.prefix = prefix; 32 | this.postfix = postfix; 33 | 34 | this.backgroundColor = backgroundColor ?? Color.White; 35 | this.foregroundColor = foregroundColor ?? Color.Black; 36 | } 37 | 38 | private void OnTimerTick(object sender, System.EventArgs e) 39 | { 40 | var powerStatus = SystemInformation.PowerStatus; 41 | switch (powerStatus.BatteryChargeStatus) 42 | { 43 | case BatteryChargeStatus.Critical: 44 | label.ForeColor = Color.Red; 45 | break; 46 | case BatteryChargeStatus.High: 47 | label.ForeColor = Color.Green; 48 | break; 49 | case BatteryChargeStatus.Low: 50 | label.ForeColor = Color.Orange; 51 | break; 52 | } 53 | 54 | var oldLeft = label.Left; 55 | var oldRight = label.Right; 56 | var oldWidth = label.Width; 57 | label.Text = (powerStatus.PowerLineStatus == PowerLineStatus.Offline ? 58 | textForNotCharging : textForCharging) + prefix + (powerStatus.BatteryLifePercent * 100) + postfix; 59 | 60 | label.Width = TextRenderer.MeasureText(label.Text, label.Font).Width; 61 | if (oldWidth != label.Width) 62 | { 63 | this.RepositionControls(oldLeft, oldRight); 64 | bar.DoFixedWidthWidgetWidthChanged(this); 65 | } 66 | } 67 | 68 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 69 | { 70 | } 71 | 72 | void IWidget.InitializeWidget(Bar bar) 73 | { 74 | this.bar = bar; 75 | 76 | var powerStatus = SystemInformation.PowerStatus; 77 | label = bar.CreateLabel((powerStatus.PowerLineStatus == PowerLineStatus.Offline ? 78 | textForNotCharging : textForCharging) + prefix + (powerStatus.BatteryLifePercent * 100) + postfix, 0); 79 | label.BackColor = backgroundColor; 80 | label.ForeColor = foregroundColor; 81 | label.TextAlign = ContentAlignment.MiddleCenter; 82 | switch (powerStatus.BatteryChargeStatus) 83 | { 84 | case BatteryChargeStatus.Critical: 85 | label.ForeColor = Color.Red; 86 | break; 87 | case BatteryChargeStatus.High: 88 | label.ForeColor = Color.Green; 89 | break; 90 | case BatteryChargeStatus.Low: 91 | label.ForeColor = Color.Orange; 92 | break; 93 | case BatteryChargeStatus.NoSystemBattery: 94 | label.ForeColor = Color.Black; 95 | label.Text = @"NO BAT"; 96 | return ; 97 | } 98 | 99 | bar.BarShown += () => updateTimer.Start(); 100 | bar.BarHidden += () => updateTimer.Stop(); 101 | } 102 | 103 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 104 | { 105 | this.isLeft = isLeft; 106 | 107 | return new[] { label }; 108 | } 109 | 110 | public void RepositionControls(int left, int right) 111 | { 112 | this.label.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.label.Width, 0); 113 | } 114 | 115 | int IWidget.GetLeft() 116 | { 117 | return label.Left; 118 | } 119 | 120 | int IWidget.GetRight() 121 | { 122 | return label.Right; 123 | } 124 | 125 | void IWidget.StaticDispose() 126 | { 127 | } 128 | 129 | void IWidget.Dispose() 130 | { 131 | } 132 | 133 | void IWidget.Refresh() 134 | { 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Windawesome/FullScreenLayout.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Windawesome 3 | { 4 | public sealed class FullScreenLayout : ILayout 5 | { 6 | private Workspace workspace; 7 | 8 | private void MaximizeWindow(Window window) 9 | { 10 | if (Utilities.WindowIsNotHung(window)) 11 | { 12 | var newMonitorBounds = workspace.Monitor.Bounds; 13 | var newMonitorWorkingArea = workspace.Monitor.WorkingArea; 14 | 15 | var hWindowsMonitor = NativeMethods.MonitorFromWindow(window.hWnd, NativeMethods.MFRF.MONITOR_MONITOR_DEFAULTTONULL); 16 | var windowsMonitorInfo = NativeMethods.MONITORINFO.Default; 17 | NativeMethods.GetMonitorInfo(hWindowsMonitor, ref windowsMonitorInfo); 18 | var windowsMonitorBounds = windowsMonitorInfo.rcMonitor.ToRectangle(); 19 | 20 | var winPlacement = NativeMethods.WINDOWPLACEMENT.Default; 21 | NativeMethods.GetWindowPlacement(window.hWnd, ref winPlacement); 22 | 23 | winPlacement.MaxPosition.X = newMonitorBounds.Left; 24 | winPlacement.MaxPosition.Y = newMonitorBounds.Top; 25 | 26 | if (NativeMethods.IsZoomed(window.hWnd) && windowsMonitorBounds != newMonitorBounds) 27 | { 28 | // restore if program is maximized and should be on a different monitor 29 | NativeMethods.ShowWindow(window.hWnd, NativeMethods.SW.SW_SHOWNOACTIVATE); // should not use SW_RESTORE as it activates the window 30 | System.Threading.Thread.Sleep(NativeMethods.minimizeRestoreDelay); 31 | } 32 | 33 | var ws = NativeMethods.GetWindowStyleLongPtr(window.hWnd); 34 | if (ws.HasFlag(NativeMethods.WS.WS_CAPTION | NativeMethods.WS.WS_MAXIMIZEBOX)) 35 | { 36 | if (windowsMonitorBounds != newMonitorBounds) 37 | { 38 | winPlacement.NormalPosition.left += newMonitorBounds.Left - windowsMonitorBounds.Left; // these are in working area coordinates 39 | winPlacement.NormalPosition.right += newMonitorBounds.Right - windowsMonitorBounds.Right; 40 | winPlacement.NormalPosition.top += newMonitorBounds.Top - windowsMonitorBounds.Top; 41 | winPlacement.NormalPosition.bottom += newMonitorBounds.Bottom - windowsMonitorBounds.Bottom; 42 | } 43 | 44 | winPlacement.ShowCmd = NativeMethods.SW.SW_SHOWMAXIMIZED; 45 | } 46 | else 47 | { 48 | winPlacement.NormalPosition.left = newMonitorBounds.Left; // these are in working area coordinates 49 | winPlacement.NormalPosition.right = newMonitorBounds.Left + newMonitorWorkingArea.Width; 50 | winPlacement.NormalPosition.top = newMonitorBounds.Top; 51 | winPlacement.NormalPosition.bottom = newMonitorBounds.Top + newMonitorWorkingArea.Height; 52 | 53 | winPlacement.ShowCmd = NativeMethods.SW.SW_SHOWNOACTIVATE; 54 | } 55 | 56 | NativeMethods.SetWindowPlacement(window.hWnd, ref winPlacement); 57 | } 58 | } 59 | 60 | private void OnWorkspaceWindowAddedOrRemoved(Workspace workspace, Window window) 61 | { 62 | if (workspace == this.workspace && workspace.IsWorkspaceVisible) 63 | { 64 | Workspace.DoLayoutUpdated(); 65 | } 66 | } 67 | 68 | #region ILayout Members 69 | 70 | string ILayout.LayoutSymbol() 71 | { 72 | return workspace.GetWindowsCount() == 0 ? "[M]" : "[" + workspace.GetWindowsCount() + "]"; 73 | } 74 | 75 | public string LayoutName() 76 | { 77 | return "Full Screen"; 78 | } 79 | 80 | void ILayout.Initialize(Workspace workspace) 81 | { 82 | this.workspace = workspace; 83 | 84 | workspace.WindowTitlebarToggled += MaximizeWindow; 85 | workspace.WindowBorderToggled += MaximizeWindow; 86 | 87 | Workspace.WorkspaceWindowAdded += OnWorkspaceWindowAddedOrRemoved; 88 | Workspace.WorkspaceWindowRemoved += OnWorkspaceWindowAddedOrRemoved; 89 | } 90 | 91 | void ILayout.Dispose() 92 | { 93 | workspace.WindowTitlebarToggled -= MaximizeWindow; 94 | workspace.WindowBorderToggled -= MaximizeWindow; 95 | 96 | Workspace.WorkspaceWindowAdded -= OnWorkspaceWindowAddedOrRemoved; 97 | Workspace.WorkspaceWindowRemoved -= OnWorkspaceWindowAddedOrRemoved; 98 | } 99 | 100 | bool ILayout.ShouldSaveAndRestoreSharedWindowsPosition() 101 | { 102 | return false; 103 | } 104 | 105 | void ILayout.Reposition() 106 | { 107 | workspace.GetLayoutManagedWindows().ForEach(MaximizeWindow); 108 | Workspace.DoLayoutUpdated(); 109 | } 110 | 111 | void ILayout.WindowMinimized(Window window) 112 | { 113 | } 114 | 115 | void ILayout.WindowRestored(Window window) 116 | { 117 | (this as ILayout).WindowCreated(window); 118 | } 119 | 120 | void ILayout.WindowCreated(Window window) 121 | { 122 | if (workspace.IsWorkspaceVisible) 123 | { 124 | MaximizeWindow(window); 125 | } 126 | } 127 | 128 | void ILayout.WindowDestroyed(Window window) 129 | { 130 | } 131 | 132 | #endregion 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Config/2-Program Rules.py: -------------------------------------------------------------------------------- 1 | from Windawesome import Windawesome, ProgramRule, State, OnWindowCreatedOrShownAction, OnWindowCreatedOnWorkspaceAction 2 | from Windawesome.NativeMethods import WS, WS_EX 3 | 4 | config.ProgramRules = [ 5 | ProgramRule( 6 | className = "^cygwin/x X rl$", 7 | windowCreatedDelay = 300, 8 | rules = [ProgramRule.Rule(workspace = 5)] 9 | ), 10 | ProgramRule( 11 | className = "^TApplication$", 12 | displayName = "^Find and Run Robot$", 13 | isManaged = False 14 | ), 15 | ProgramRule( 16 | className = "^TApplication$", 17 | rules = [ProgramRule.Rule(isFloating = True)] 18 | ), 19 | ProgramRule( 20 | className = "^MozillaWindowClass$", 21 | rules = [ProgramRule.Rule(workspace = 2)] 22 | ), 23 | ProgramRule( 24 | className = "^MozillaDialogClass$", 25 | rules = [ProgramRule.Rule(workspace = 2, isFloating = True)] 26 | ), 27 | ProgramRule( 28 | className = "^CabinetWClass$", # Windows Explorer 29 | updateIcon = True, 30 | rules = [ProgramRule.Rule(workspace = 1)] 31 | ), 32 | ProgramRule( 33 | className = "^ExploreWClass$", # Windows Explorer 34 | updateIcon = True, 35 | rules = [ProgramRule.Rule(workspace = 1)] 36 | ), 37 | ProgramRule( 38 | className = "^wxWindowNR$", 39 | displayName = ".*BitComet.*", 40 | onWindowCreatedAction = OnWindowCreatedOrShownAction.HideWindow, 41 | onHiddenWindowShownAction = OnWindowCreatedOrShownAction.HideWindow, 42 | showMenu = False, 43 | rules = [ProgramRule.Rule(workspace = 9, titlebar = State.HIDDEN, windowBorders = State.HIDDEN)] 44 | ), 45 | ProgramRule( 46 | displayName = ".*SA Dictionary 2010.*", 47 | rules = [ProgramRule.Rule(isFloating = True)] 48 | ), 49 | ProgramRule( 50 | className = "^rctrl_renwnd32$", # Outlook 51 | rules = [ProgramRule.Rule(workspace = 8)] 52 | ), 53 | ProgramRule( 54 | className = "^{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}$", # foobar2000 55 | rules = [ProgramRule.Rule(workspace = 7)] 56 | ), 57 | 58 | # editors 59 | 60 | ProgramRule( 61 | className = "^Vim$", 62 | windowCreatedDelay = 100, 63 | rules = [ProgramRule.Rule(workspace = 3, titlebar = State.HIDDEN, windowBorders = State.HIDDEN)] 64 | ), 65 | ProgramRule( 66 | className = "^XLMAIN$", # Excel 67 | rules = [ProgramRule.Rule(redrawOnShow = True)] 68 | ), 69 | ProgramRule( 70 | displayName = ".*Microsoft Visual Studio.*", 71 | onWindowCreatedAction = OnWindowCreatedOrShownAction.HideWindow, 72 | rules = [ProgramRule.Rule(workspace = 5, titlebar = State.HIDDEN, windowBorders = State.HIDDEN)] 73 | ), 74 | 75 | # media players 76 | 77 | ProgramRule( 78 | className = "^MediaPlayerClassicW$", 79 | rules = [ProgramRule.Rule(workspace = 1)] 80 | ), 81 | 82 | # chat 83 | 84 | ProgramRule( 85 | className = "^icoTrilly$", 86 | onWindowCreatedAction = OnWindowCreatedOrShownAction.TemporarilyShowWindowOnCurrentWorkspace, 87 | onWindowCreatedOnInactiveWorkspaceAction = OnWindowCreatedOnWorkspaceAction.PreserveTopmostWindow, 88 | rules = [ProgramRule.Rule(workspace = 4, isFloating = True)] 89 | ), 90 | ProgramRule( 91 | className = "^ico.*", 92 | processName = "^trillian$", 93 | onWindowCreatedAction = OnWindowCreatedOrShownAction.HideWindow, 94 | onWindowCreatedOnCurrentWorkspaceAction = OnWindowCreatedOnWorkspaceAction.PreserveTopmostWindow, 95 | onWindowCreatedOnInactiveWorkspaceAction = OnWindowCreatedOnWorkspaceAction.PreserveTopmostWindow, 96 | rules = [ProgramRule.Rule(workspace = 4)] 97 | ), 98 | 99 | # terminals 100 | 101 | ProgramRule( 102 | className = "^Console_2_Main$", 103 | rules = [ProgramRule.Rule(workspace = 3)] 104 | ), 105 | ProgramRule( 106 | className = "^mintty$", 107 | redrawDesktopOnWindowCreated = True, 108 | rules = [ProgramRule.Rule(workspace = 3, titlebar = State.HIDDEN, windowBorders = State.HIDDEN)] 109 | ), 110 | 111 | # other 112 | 113 | ProgramRule( 114 | displayName = "^Windows 7 Manager - Junk File Cleaner$", 115 | isManaged = False 116 | ), 117 | ProgramRule( 118 | displayName = "^Windows 7 Manager - Registry Cleaner$", 119 | isManaged = False 120 | ), 121 | ProgramRule( 122 | displayName = ".*Windows 7 Manager.*", 123 | rules = [ProgramRule.Rule(workspace = 1)] 124 | ), 125 | ProgramRule( 126 | className = "^MsiDialogCloseClass$", 127 | isManaged = False 128 | ), 129 | ProgramRule( 130 | className = "^MsiDialogNoCloseClass$", 131 | isManaged = False 132 | ), 133 | ProgramRule( 134 | className = "^\$\$\$Secure UAP Dummy Window Class For Interim Dialog$" 135 | ), 136 | ProgramRule( 137 | className = "^#32770$", # all dialogs 138 | rules = [ProgramRule.Rule(isFloating = True)] # should be floating 139 | ), 140 | ProgramRule( 141 | styleContains = WS.WS_POPUP, 142 | isManaged = False 143 | ), 144 | ProgramRule( 145 | styleNotContains = WS.WS_MAXIMIZEBOX, 146 | rules = [ProgramRule.Rule(isFloating = True)] 147 | ), 148 | ProgramRule() # an all-catching rule in the end to manage all other windows 149 | ] 150 | -------------------------------------------------------------------------------- /Windawesome/LanguageBarWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | namespace Windawesome 8 | { 9 | public sealed class LanguageBarWidget : IFixedWidthWidget 10 | { 11 | private uint globalShellHookMessage; 12 | private Bar bar; 13 | 14 | private Label label; 15 | private bool isLeft; 16 | private readonly Color backgroundColor; 17 | private readonly Color foregroundColor; 18 | private readonly static StringBuilder stringBuilder = new StringBuilder(85); 19 | 20 | private delegate void InputLanguageChangedEventHandler(IntPtr hWnd); 21 | private static event InputLanguageChangedEventHandler InputLanguageChanged; 22 | 23 | public LanguageBarWidget(Color? backgroundColor = null, Color? foregroundColor = null) 24 | { 25 | this.backgroundColor = backgroundColor ?? Color.White; 26 | this.foregroundColor = foregroundColor ?? Color.Black; 27 | } 28 | 29 | private static bool OnGlobalShellHookMessage(ref Message m) 30 | { 31 | InputLanguageChanged(NativeMethods.GetForegroundWindow()); 32 | return true; 33 | } 34 | 35 | private static string GetWindowKeyboardLanguage(IntPtr hWnd) 36 | { 37 | var keyboardLayout = NativeMethods.GetKeyboardLayout( 38 | NativeMethods.GetWindowThreadProcessId(hWnd, IntPtr.Zero)); 39 | 40 | var localeId = unchecked((uint) (short) keyboardLayout.ToInt32()); 41 | 42 | if (SystemAndProcessInformation.isAtLeastVista) 43 | { 44 | NativeMethods.LCIDToLocaleName(localeId, stringBuilder, stringBuilder.Capacity, 0); 45 | return stringBuilder.ToString(); 46 | } 47 | 48 | // XP doesn't have LCIDToLocaleName 49 | NativeMethods.GetLocaleInfo(localeId, NativeMethods.LOCALE_SISO639LANGNAME, stringBuilder, stringBuilder.Capacity); 50 | var languageName = stringBuilder.ToString(); 51 | NativeMethods.GetLocaleInfo(localeId, NativeMethods.LOCALE_SISO3166CTRYNAME, stringBuilder, stringBuilder.Capacity); 52 | return languageName + "-" + stringBuilder; 53 | } 54 | 55 | private void SetNewLanguage(string language) 56 | { 57 | if (language != label.Text) 58 | { 59 | var oldLeft = label.Left; 60 | var oldRight = label.Right; 61 | var oldWidth = label.Width; 62 | label.Text = language; 63 | 64 | label.Width = TextRenderer.MeasureText(label.Text, label.Font).Width; 65 | if (oldWidth != label.Width) 66 | { 67 | this.RepositionControls(oldLeft, oldRight); 68 | bar.DoFixedWidthWidgetWidthChanged(this); 69 | } 70 | } 71 | } 72 | 73 | private void SetNewLanguage(IntPtr hWnd) 74 | { 75 | if (bar.Monitor.CurrentVisibleWorkspace.IsCurrentWorkspace) 76 | { 77 | SetNewLanguage(GetWindowKeyboardLanguage(hWnd)); 78 | } 79 | } 80 | 81 | #region IFixedWidthWidget Members 82 | 83 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 84 | { 85 | if (NativeMethods.RegisterGlobalShellHook(windawesome.Handle)) 86 | { 87 | globalShellHookMessage = NativeMethods.RegisterWindowMessage("GLOBAL_SHELL_HOOK"); 88 | if (SystemAndProcessInformation.isAtLeastVista && SystemAndProcessInformation.isRunningElevated) 89 | { 90 | if (SystemAndProcessInformation.isAtLeast7) 91 | { 92 | NativeMethods.ChangeWindowMessageFilterEx(windawesome.Handle, globalShellHookMessage, NativeMethods.MSGFLTEx.MSGFLT_ALLOW, IntPtr.Zero); 93 | } 94 | else 95 | { 96 | NativeMethods.ChangeWindowMessageFilter(globalShellHookMessage, NativeMethods.MSGFLT.MSGFLT_ADD); 97 | } 98 | } 99 | 100 | windawesome.RegisterMessage((int) globalShellHookMessage, OnGlobalShellHookMessage); 101 | } 102 | } 103 | 104 | void IWidget.InitializeWidget(Bar bar) 105 | { 106 | this.bar = bar; 107 | 108 | label = bar.CreateLabel("", 0); 109 | label.BackColor = backgroundColor; 110 | label.ForeColor = foregroundColor; 111 | label.TextAlign = ContentAlignment.MiddleCenter; 112 | 113 | Workspace.WindowActivatedEvent += SetNewLanguage; 114 | InputLanguageChanged += SetNewLanguage; 115 | } 116 | 117 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 118 | { 119 | this.isLeft = isLeft; 120 | 121 | return new[] { label }; 122 | } 123 | 124 | public void RepositionControls(int left, int right) 125 | { 126 | this.label.Location = this.isLeft ? new Point(left, 0) : new Point(right - this.label.Width, 0); 127 | } 128 | 129 | int IWidget.GetLeft() 130 | { 131 | return label.Left; 132 | } 133 | 134 | int IWidget.GetRight() 135 | { 136 | return label.Right; 137 | } 138 | 139 | void IWidget.StaticDispose() 140 | { 141 | NativeMethods.UnregisterGlobalShellHook(); 142 | 143 | // remove the message filters 144 | if (SystemAndProcessInformation.isAtLeastVista && SystemAndProcessInformation.isRunningElevated) 145 | { 146 | if (SystemAndProcessInformation.isAtLeast7) 147 | { 148 | NativeMethods.ChangeWindowMessageFilterEx(Windawesome.HandleStatic, globalShellHookMessage, NativeMethods.MSGFLTEx.MSGFLT_RESET, IntPtr.Zero); 149 | } 150 | else 151 | { 152 | NativeMethods.ChangeWindowMessageFilter(globalShellHookMessage, NativeMethods.MSGFLT.MSGFLT_REMOVE); 153 | } 154 | } 155 | } 156 | 157 | void IWidget.Dispose() 158 | { 159 | } 160 | 161 | void IWidget.Refresh() 162 | { 163 | } 164 | 165 | #endregion 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /WindowSubclassingCSharp/WindowSubclassing.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | 6 | namespace Windawesome 7 | { 8 | public class WindowSubclassing : IPlugin 9 | { 10 | private readonly Tuple[] ignoredPrograms; // (className, displayName) 11 | private Windawesome windawesome; 12 | private HashMultiSet[] subclassedWindows; 13 | 14 | private static readonly uint startWindowProcMessage; 15 | private static readonly uint stopWindowProcMessage; 16 | 17 | static WindowSubclassing() 18 | { 19 | // TODO: can use messages between WM_USER and 0x7FFF 20 | startWindowProcMessage = NativeMethods.RegisterWindowMessage("START_WINDOW_PROC"); 21 | stopWindowProcMessage = NativeMethods.RegisterWindowMessage("STOP_WINDOW_PROC"); 22 | } 23 | 24 | public WindowSubclassing(IEnumerable> ignoredPrograms) 25 | { 26 | this.ignoredPrograms = ignoredPrograms.ToArray(); 27 | } 28 | 29 | private bool IsMatch(string cName, string dName) 30 | { 31 | return ignoredPrograms.Any(t => Regex.IsMatch(cName, t.Item1) && Regex.IsMatch(dName, t.Item2)); 32 | } 33 | 34 | private void OnWorkspaceApplicationAdded(Workspace workspace, Window window) 35 | { 36 | if (workspace.Layout.LayoutName() == "Tile" || workspace.Layout.LayoutName() == "Full Screen") 37 | { 38 | if (!IsMatch(window.className, window.DisplayName)) 39 | { 40 | if (Environment.Is64BitProcess && window.is64BitProcess) 41 | { 42 | if (subclassedWindows[workspace.id - 1].Add(window) == HashMultiSet.AddResult.AddedFirst) 43 | { 44 | NativeMethods.SubclassWindow64(windawesome.Handle, window.hWnd); 45 | } 46 | if (workspace.IsCurrentWorkspace) 47 | { 48 | NativeMethods.SendNotifyMessage(window.hWnd, startWindowProcMessage, UIntPtr.Zero, IntPtr.Zero); 49 | } 50 | } 51 | else if (!Environment.Is64BitOperatingSystem) 52 | { 53 | if (subclassedWindows[workspace.id - 1].Add(window) == HashMultiSet.AddResult.AddedFirst) 54 | { 55 | NativeMethods.SubclassWindow32(windawesome.Handle, window.hWnd); 56 | } 57 | if (workspace.IsCurrentWorkspace) 58 | { 59 | NativeMethods.SendNotifyMessage(window.hWnd, startWindowProcMessage, UIntPtr.Zero, IntPtr.Zero); 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | private void OnWorkspaceApplicationRemoved(Workspace workspace, Window window) 67 | { 68 | switch (subclassedWindows[workspace.id - 1].Remove(window)) 69 | { 70 | case HashMultiSet.RemoveResult.RemovedLast: 71 | NativeMethods.UnsubclassWindow(window.hWnd); 72 | break; 73 | case HashMultiSet.RemoveResult.Removed: 74 | NativeMethods.SendNotifyMessage(window.hWnd, stopWindowProcMessage, UIntPtr.Zero, IntPtr.Zero); 75 | break; 76 | } 77 | } 78 | 79 | private void OnWorkspaceChangedFrom(Workspace workspace) 80 | { 81 | subclassedWindows[workspace.id - 1].Where(w => w.WorkspacesCount > 1).ForEach(w => 82 | NativeMethods.SendNotifyMessage(w.hWnd, stopWindowProcMessage, UIntPtr.Zero, IntPtr.Zero)); 83 | } 84 | 85 | private void OnWorkspaceChangedTo(Workspace workspace) 86 | { 87 | subclassedWindows[workspace.id - 1].Where(w => w.WorkspacesCount > 1).ForEach(w => 88 | NativeMethods.SendNotifyMessage(w.hWnd, startWindowProcMessage, UIntPtr.Zero, IntPtr.Zero)); 89 | } 90 | 91 | private void OnWorkspaceLayoutChanged(Workspace workspace, ILayout oldLayout) 92 | { 93 | if (workspace.Layout.LayoutName() != "Tile" && workspace.Layout.LayoutName() != "Full Screen") 94 | { 95 | subclassedWindows[workspace.id - 1].ForEach(w => OnWorkspaceApplicationRemoved(workspace, w)); 96 | } 97 | } 98 | 99 | //private void Listen(Window window) 100 | //{ 101 | // if (window.titlebar == State.SHOWN || window.windowBorders == State.SHOWN) 102 | // { 103 | // NativeMethods.SendNotifyMessage(window.hWnd, START_WINDOW_PROC_MESSAGE, UIntPtr.Zero, IntPtr.Zero); 104 | // } 105 | // else if (window.titlebar == State.HIDDEN && window.windowBorders == State.HIDDEN) 106 | // { 107 | // NativeMethods.SendNotifyMessage(window.hWnd, STOP_WINDOW_PROC_MESSAGE, UIntPtr.Zero, IntPtr.Zero); 108 | // } 109 | // else if (window.titlebar == State.AS_IS || window.windowBorders == State.AS_IS) 110 | // { 111 | // var style = NativeMethods.GetWindowStyleLongPtr(window.hWnd); 112 | 113 | // if ((style & NativeMethods.WS.WS_CAPTION) != 0 || (style & NativeMethods.WS.WS_SIZEBOX) != 0) 114 | // { 115 | // NativeMethods.SendNotifyMessage(window.hWnd, START_WINDOW_PROC_MESSAGE, UIntPtr.Zero, IntPtr.Zero); 116 | // } 117 | // } 118 | //} 119 | 120 | #region IPlugin Members 121 | 122 | void IPlugin.InitializePlugin(Windawesome windawesome) 123 | { 124 | Workspace.WorkspaceWindowAdded += OnWorkspaceApplicationAdded; 125 | Workspace.WorkspaceWindowRemoved += OnWorkspaceApplicationRemoved; 126 | //Workspace.WorkspaceChangedFrom += OnWorkspaceChangedFrom; 127 | //Workspace.WorkspaceChangedTo += OnWorkspaceChangedTo; 128 | Workspace.WorkspaceLayoutChanged += OnWorkspaceLayoutChanged; 129 | this.windawesome = windawesome; 130 | 131 | subclassedWindows = new HashMultiSet[windawesome.config.Workspaces.Length]; 132 | for (var i = 0; i < windawesome.config.Workspaces.Length; i++) 133 | { 134 | subclassedWindows[i] = new HashMultiSet(); 135 | } 136 | } 137 | 138 | void IPlugin.Dispose() 139 | { 140 | subclassedWindows.ForEach(set => set.ForEach(w => NativeMethods.UnsubclassWindow(w.hWnd))); 141 | } 142 | 143 | #endregion 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /Config/1-General Settings.py: -------------------------------------------------------------------------------- 1 | from System.Drawing import Color, Font 2 | from System.Linq import Enumerable 3 | from Windawesome import ILayout, TileLayout, FullScreenLayout, FloatingLayout, IPlugin, Workspace 4 | from Windawesome import Bar, LayoutWidget, WorkspacesWidget, ApplicationTabsWidget, SystemTrayWidget, CpuMonitorWidget, RamMonitorWidget, LaptopBatteryMonitorWidget, LanguageBarWidget, CurrentlyPlayingWidget, SeparatorWidget 5 | from Windawesome import LoggerPlugin, ShortcutsManager, InputLanguageChangerPlugin 6 | from Windawesome.NativeMethods import MOD 7 | from System import Tuple 8 | from System.Windows.Forms import Keys 9 | 10 | def onLayoutLabelClick(): 11 | if windawesome.CurrentWorkspace.Layout.LayoutName() == "Full Screen": 12 | windawesome.CurrentWorkspace.ChangeLayout(FloatingLayout()) 13 | elif windawesome.CurrentWorkspace.Layout.LayoutName() == "Floating": 14 | windawesome.CurrentWorkspace.ChangeLayout(TileLayout()) 15 | else: 16 | windawesome.CurrentWorkspace.ChangeLayout(FullScreenLayout()) 17 | 18 | config.WindowBorderWidth = 1 19 | config.WindowPaddedBorderWidth = 0 20 | 21 | config.CheckForUpdates = False 22 | 23 | workspacesWidgetForegroundColors = [Color.Yellow for i in range(0, 10)] 24 | workspacesWidgetForegroundColors[0] = Color.LightSeaGreen 25 | workspacesWidgetBackgroundColors = [Color.Black for i in range(0, 10)] 26 | 27 | config.Bars = Enumerable.ToArray[Bar]([ 28 | Bar(windawesome.monitors[0], 29 | [ 30 | WorkspacesWidget( 31 | normalForegroundColor = workspacesWidgetForegroundColors, 32 | normalBackgroundColor = workspacesWidgetBackgroundColors, 33 | highlightedForegroundColor = Color.DarkOrange, 34 | highlightedBackgroundColor = Color.Black, 35 | highlightedInactiveForegroundColor = Color.LightSeaGreen, 36 | highlightedInactiveBackgroundColor = Color.Black, 37 | flashingForegroundColor = Color.Black 38 | ), 39 | LayoutWidget( 40 | foregroundColor = Color.Gold, 41 | backgroundColor = Color.Black, 42 | onClick = onLayoutLabelClick 43 | ) 44 | ], 45 | 46 | [ 47 | SystemTrayWidget(), 48 | LanguageBarWidget( 49 | foregroundColor = Color.Gold, 50 | backgroundColor = Color.Black 51 | ), 52 | SeparatorWidget( 53 | foregroundColor = Color.Gold, 54 | backgroundColor = Color.Black 55 | ), 56 | DateTimeWidget("ddd, d-MMM", "", "", Color.Black, Color.Gold), 57 | SeparatorWidget( 58 | foregroundColor = Color.Gold, 59 | backgroundColor = Color.Black 60 | ), 61 | DateTimeWidget("h:mm tt", "", "", Color.Black, Color.Gold), 62 | ], 63 | 64 | [ 65 | ApplicationTabsWidget( 66 | normalForegroundColor = Color.LightSeaGreen, 67 | normalBackgroundColor = Color.Black, 68 | highlightedForegroundColor = Color.DarkOrange, 69 | highlightedBackgroundColor = Color.Black, 70 | ) 71 | ], 72 | 73 | backgroundColor = Color.Black, 74 | font = Font("Consolas", 11) 75 | ), 76 | Bar(windawesome.monitors[0], 77 | [ 78 | WorkspacesWidget( 79 | normalForegroundColor = workspacesWidgetForegroundColors, 80 | normalBackgroundColor = workspacesWidgetBackgroundColors, 81 | highlightedForegroundColor = Color.DarkOrange, 82 | highlightedBackgroundColor = Color.Black, 83 | highlightedInactiveForegroundColor = Color.LightSeaGreen, 84 | highlightedInactiveBackgroundColor = Color.Black, 85 | flashingForegroundColor = Color.Black 86 | ), 87 | LayoutWidget( 88 | foregroundColor = Color.Gold, 89 | backgroundColor = Color.Black, 90 | onClick = onLayoutLabelClick 91 | ) 92 | ], 93 | 94 | [ 95 | SystemTrayWidget(True), 96 | LanguageBarWidget( 97 | foregroundColor = Color.Gold, 98 | backgroundColor = Color.Black 99 | ), 100 | SeparatorWidget( 101 | foregroundColor = Color.Gold, 102 | backgroundColor = Color.Black 103 | ), 104 | DateTimeWidget("ddd, d-MMM", "", "", Color.Black, Color.Gold), 105 | SeparatorWidget( 106 | foregroundColor = Color.Gold, 107 | backgroundColor = Color.Black 108 | ), 109 | DateTimeWidget("h:mm tt", "", "", Color.Black, Color.Gold), 110 | ], 111 | 112 | [ 113 | ApplicationTabsWidget( 114 | normalForegroundColor = Color.LightSeaGreen, 115 | normalBackgroundColor = Color.Black, 116 | highlightedForegroundColor = Color.DarkOrange, 117 | highlightedBackgroundColor = Color.Black, 118 | ) 119 | ], 120 | 121 | backgroundColor = Color.Black, 122 | font = Font("Consolas", 11) 123 | ) 124 | ]) 125 | 126 | config.Workspaces = Enumerable.ToArray[Workspace]([ 127 | Workspace(windawesome.monitors[0], FloatingLayout(), [config.Bars[1]], name = 'main'), 128 | Workspace(windawesome.monitors[0], FullScreenLayout(), [config.Bars[0]], name = 'web'), 129 | Workspace(windawesome.monitors[0], FullScreenLayout(), [config.Bars[0]]), 130 | Workspace(windawesome.monitors[0], TileLayout(masterAreaAxis = TileLayout.LayoutAxis.TopToBottom, masterAreaWindowsCount = 2, masterAreaFactor = 0.5), [config.Bars[0]], name = 'chat'), 131 | Workspace(windawesome.monitors[0], FullScreenLayout(), [config.Bars[0]]), 132 | Workspace(windawesome.monitors[0], FullScreenLayout(), [config.Bars[0]]), 133 | Workspace(windawesome.monitors[0], FullScreenLayout(), [config.Bars[0]]), 134 | Workspace(windawesome.monitors[0], FullScreenLayout(), [config.Bars[0]], name = 'mail'), 135 | Workspace(windawesome.monitors[0], FullScreenLayout(), [config.Bars[0]], name = 'BC') 136 | ]) 137 | 138 | config.StartingWorkspaces = [config.Workspaces[0]] 139 | 140 | config.Plugins = [ 141 | #LoggerPlugin(logWorkspaceSwitching = True, logWindowMinimization = True, logWindowRestoration = True, 142 | # logActivation = True), 143 | ShortcutsManager(), 144 | InputLanguageChangerPlugin(["icoicq", "icoSKYPE", "icoGOOGLE", "icoChannel", "icoJabber"]) 145 | ] 146 | -------------------------------------------------------------------------------- /Windawesome/LoggerPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace Windawesome 5 | { 6 | public sealed class LoggerPlugin : IPlugin 7 | { 8 | private readonly bool logRuleMatching; 9 | private readonly bool logCreation; 10 | private readonly bool logDeletion; 11 | private readonly bool logWorkspaceSwitching; 12 | private readonly bool logWindowMinimization; 13 | private readonly bool logWindowRestoration; 14 | private readonly bool logActivation; 15 | private readonly StreamWriter writer; 16 | private Windawesome windawesome; 17 | 18 | public LoggerPlugin(string filename = "logplugin.txt", bool logRuleMatching = true, bool logCreation = false, bool logDeletion = false, 19 | bool logWorkspaceSwitching = false, bool logWindowMinimization = false, bool logWindowRestoration = false, 20 | bool logActivation = false) 21 | { 22 | this.logRuleMatching = logRuleMatching; 23 | this.logCreation = logCreation; 24 | this.logDeletion = logDeletion; 25 | this.logWorkspaceSwitching = logWorkspaceSwitching; 26 | this.logWindowMinimization = logWindowMinimization; 27 | this.logWindowRestoration = logWindowRestoration; 28 | this.logActivation = logActivation; 29 | writer = new StreamWriter(filename, true); 30 | } 31 | 32 | private void OnProgramRuleMatched(ProgramRule programRule, IntPtr hWnd, string className, string displayName, string processName, NativeMethods.WS style, NativeMethods.WS_EX exStyle) 33 | { 34 | if (programRule != null) 35 | { 36 | writer.WriteLine("MATCHED - class '{0}'; caption '{1}'; processName '{2}';", 37 | className, displayName, processName); 38 | writer.WriteLine("\tAGAINST RULE WITH class '{0}'; caption '{1}'; process name '{2}';", 39 | programRule.className, programRule.displayName, programRule.processName); 40 | writer.WriteLine("\tstyle contains: '{0}'; style not contains '{1}'; ex style contains '{2}'; ex style not contains '{3}'; is managed '{4}'", 41 | programRule.styleContains, programRule.styleNotContains, programRule.exStyleContains, programRule.exStyleNotContains, programRule.isManaged); 42 | } 43 | else 44 | { 45 | writer.WriteLine("COULD NOT MATCH - class '{0}'; caption '{1}'; processName '{2}' AGAINST ANY RULE", 46 | className, displayName, processName); 47 | } 48 | } 49 | 50 | private void OnWorkspaceWindowAdded(Workspace workspace, Window window) 51 | { 52 | writer.WriteLine("ADDED - class '{0}'; caption '{1}'; workspace '{2}'", 53 | window.className, window.DisplayName, workspace.id); 54 | } 55 | 56 | private void OnWorkspaceWindowRemoved(Workspace workspace, Window window) 57 | { 58 | writer.WriteLine("REMOVED - class '{0}'; caption '{1}'; workspace '{2}'", 59 | window.className, window.DisplayName, workspace.id); 60 | } 61 | 62 | private void OnWorkspaceWindowMinimized(Workspace workspace, Window window) 63 | { 64 | writer.WriteLine("MINIMIZED - class '{0}'; caption '{1}'; workspace '{2}'", 65 | window.className, window.DisplayName, workspace.id); 66 | } 67 | 68 | private void OnWorkspaceWindowRestored(Workspace workspace, Window window) 69 | { 70 | writer.WriteLine("RESTORED - class '{0}'; caption '{1}'; workspace '{2}'", 71 | window.className, window.DisplayName, workspace.id); 72 | } 73 | 74 | private void OnWorkspaceShown(Workspace workspace) 75 | { 76 | writer.WriteLine("Workspace '{0}' shown", workspace.id); 77 | } 78 | 79 | private void OnWorkspaceHidden(Workspace workspace) 80 | { 81 | writer.WriteLine("Workspace '{0}' hidden", workspace.id); 82 | } 83 | 84 | private void OnWorkspaceActivated(Workspace workspace) 85 | { 86 | writer.WriteLine("Workspace '{0}' activated", workspace.id); 87 | } 88 | 89 | private void OnWorkspaceDeactivated(Workspace workspace) 90 | { 91 | writer.WriteLine("Workspace '{0}' deactivated", workspace.id); 92 | } 93 | 94 | private void OnWindowActivated(IntPtr hWnd) 95 | { 96 | var window = windawesome.CurrentWorkspace.GetWindow(hWnd); 97 | if (window != null) 98 | { 99 | writer.WriteLine("ACTIVATED - class '{0}'; caption '{1}'; workspace '{2}'", 100 | window.className, window.DisplayName, windawesome.CurrentWorkspace.id); 101 | } 102 | else 103 | { 104 | writer.WriteLine("ACTIVATED - HWND '{0}'; caption '{1}'; workspace '{2}'", 105 | hWnd, NativeMethods.GetText(hWnd), windawesome.CurrentWorkspace.id); 106 | } 107 | } 108 | 109 | #region IPlugin Members 110 | 111 | void IPlugin.InitializePlugin(Windawesome windawesome) 112 | { 113 | this.windawesome = windawesome; 114 | 115 | if (logRuleMatching) 116 | { 117 | Windawesome.ProgramRuleMatched += OnProgramRuleMatched; 118 | } 119 | if (logCreation) 120 | { 121 | Workspace.WorkspaceWindowAdded += OnWorkspaceWindowAdded; 122 | } 123 | if (logDeletion) 124 | { 125 | Workspace.WorkspaceWindowRemoved += OnWorkspaceWindowRemoved; 126 | } 127 | if (logWorkspaceSwitching) 128 | { 129 | Workspace.WorkspaceShown += OnWorkspaceShown; 130 | Workspace.WorkspaceHidden += OnWorkspaceHidden; 131 | Workspace.WorkspaceActivated += OnWorkspaceActivated; 132 | Workspace.WorkspaceDeactivated += OnWorkspaceDeactivated; 133 | } 134 | if (logWindowMinimization) 135 | { 136 | Workspace.WorkspaceWindowMinimized += OnWorkspaceWindowMinimized; 137 | } 138 | if (logWindowRestoration) 139 | { 140 | Workspace.WorkspaceWindowRestored += OnWorkspaceWindowRestored; 141 | } 142 | if (logActivation) 143 | { 144 | Workspace.WindowActivatedEvent += OnWindowActivated; 145 | } 146 | } 147 | 148 | void IPlugin.Dispose() 149 | { 150 | writer.WriteLine("=========================================="); 151 | writer.Close(); 152 | } 153 | 154 | #endregion 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Docs/API.txt: -------------------------------------------------------------------------------- 1 | IMPORTANT!!! 2 | This document is badly out of date. If you want to write a plugin/widget for Windawesome, I suggest you look at the code and see what methods are public so you know what you can use. 3 | If you just want to configure Windawesome, then the only functions you need are the public ones in Windawesome.cs - take a look at them. They are pretty self-explanatory, I think. 4 | 5 | Methods: 6 | 7 | Windawesome: 8 | 9 | void RefreshWindawesome() 10 | removes all windows that have died but Windawesome hasn't noticed, which will fix some problems with the Widgets which would be thinking that there are more windows 11 | 12 | void ChangeApplicationToWorkspace(IntPtr handle, int workspace) 13 | moves the specified window from the current workspace to the one specified in the second parameter 14 | 15 | void AddApplicationToWorkspace(IntPtr handle, int workspace) 16 | adds the specified window from the current workspace to the one specified in the second parameter 17 | 18 | void RemoveApplicationFromCurrentWorkspace(IntPtr handle) 19 | removes the specified window from the current workspace 20 | 21 | public void RemoveApplicationFromAllWorkspaces(IntPtr hWnd) 22 | removes the specified window from all workspaces - this is somewhat like making the window unmanaged by Windawesome 23 | 24 | void SwitchToWorkspace(int workspace, bool setForeground = true) 25 | switches the current workspace to the one specified in the first parameter. If the second parameter is true, the window highest in Z order of the new workspace is set as the foreground and active window, otherwise is not 26 | 27 | void ToggleShowHideWindowInTaskbar(IntPtr handle) 28 | toggles the visibility of a button in the Windows taskbar for this window 29 | 30 | void ToggleShowHideWindowTitlebar(IntPtr handle) 31 | toggles the visibility of this window's titlebar 32 | 33 | void ToggleShowHideWindowBorder(IntPtr handle) 34 | toggles the visibility of this window's border 35 | 36 | void ToggleTaskbarVisibility() 37 | toggles the visibility of Window's taskbar 38 | 39 | void SwitchToApplication(IntPtr handle) 40 | switches to the window with this handle on whichever workspace it is 41 | 42 | void RunApplication(string path, string arguments = "") 43 | runs the specified application. Even if Windawesome is run in elevated mode, the new application will not be elevated 44 | 45 | void RunOrShowApplication(string className, string path, string displayName = ".*", string arguments = "") 46 | if the application with the specified class and display name is running (both are regexes), it is switch to, on whichever workspace it is. If not, it is run with RunApplication 47 | 48 | void QuitApplication(IntPtr handle) 49 | quits the specified application 50 | 51 | void MinimizeApplication(IntPtr handle) 52 | minimizes the specified application 53 | 54 | bool SwitchToApplicationInCurrentWorkspace(IntPtr handle) 55 | switches to the specified application but only if it is in the current workspace. Returns true if the application was found on the current workspace and was switched to 56 | 57 | static void RegisterMessage(int message, HandleMessageDelegate targetHandler) 58 | tells Windawesome that if it gets a message with that number it should call the delegate provided. Useful for plugins and widgets 59 | 60 | static Bitmap GetWindowSmallIconAsBitmap(IntPtr handle) 61 | returns the small icon of a window as a Bitmap instance 62 | 63 | Bar: 64 | 65 | void OnWidgetControlsChanged(IWidget widget, Control[] oldControls, Control[] newControls) 66 | void OnSpanWidgetControlsRemoved(IWidget widget, Control[] controls) 67 | void OnSpanWidgetControlsAdded(IWidget widget, Control[] controls) 68 | void OnFixedWidthWidgetWidthChanged(IWidget widget) 69 | Label CreateLabel(string text, int xLocation, int width = -1) 70 | 71 | Events: 72 | 73 | Windawesome: 74 | 75 | delegate void LayoutUpdatedEventHandler() 76 | static event LayoutUpdatedEventHandler LayoutUpdated 77 | called when the layout is updated (e.g. changed from one layout to the other, the layout symbol is changed and so on) 78 | 79 | delegate void WindowTitleOrIconChangedEventHandler(Workspace workspace, Window window, string newText, Bitmap newIcon) 80 | static event WindowTitleOrIconChangedEventHandler WindowTitleOrIconChanged 81 | called when a window's text (which is in the specified workspace) has been changed to the new text or the icon has changed to the new icon 82 | 83 | delegate void WindowFlashingEventHandler(LinkedList> list) 84 | static event WindowFlashingEventHandler WindowFlashing 85 | called when a window is flashing in the Windows Taskbar. The argument passed is a list of all the Workspaces which contain this Window 86 | 87 | Workspace: 88 | 89 | delegate void WorkspaceApplicationAddedEventHandler(Workspace workspace, Window window) 90 | static event WorkspaceApplicationAddedEventHandler WorkspaceApplicationAdded 91 | called when an application is added to that workspace 92 | 93 | delegate void WorkspaceApplicationRemovedEventHandler(Workspace workspace, Window window) 94 | static event WorkspaceApplicationRemovedEventHandler WorkspaceApplicationRemoved 95 | called when an application is removed from that workspace 96 | 97 | delegate void WorkspaceApplicationMinimizedEventHandler(Workspace workspace, Window window) 98 | static event WorkspaceApplicationMinimizedEventHandler WorkspaceApplicationMinimized 99 | called when an application is minimized in that workspace 100 | 101 | delegate void WorkspaceApplicationRestoredEventHandler(Workspace workspace, Window window) 102 | static event WorkspaceApplicationRestoredEventHandler WorkspaceApplicationRestored 103 | called when an application is restored in that workspace 104 | 105 | delegate void WorkspaceChangedFromEventHandler(Workspace workspace) 106 | static event WorkspaceChangedFromEventHandler WorkspaceChangedFrom 107 | called when a workspace has been unswitched from 108 | 109 | delegate void WorkspaceChangedToEventHandler(Workspace workspace) 110 | static event WorkspaceChangedToEventHandler WorkspaceChangedTo 111 | called when a workspace has been switched to 112 | 113 | delegate void WorkspaceLayoutChangedEventHandler(Workspace workspace, ILayout oldLayout) 114 | static event WorkspaceLayoutChangedEventHandler WorkspaceLayoutChanged 115 | called when a workspace's layout has changed. The ILayout argument is the old layout 116 | 117 | delegate void WindowActivatedEventHandler(IntPtr handle) 118 | static event WindowActivatedEventHandler WindowActivatedEvent 119 | called when an application has been switched to 120 | 121 | -------------------------------------------------------------------------------- /Windawesome/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Images\Icon missing.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | -------------------------------------------------------------------------------- /TileLayout/TileLayout.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6} 9 | Library 10 | Properties 11 | Windawesome 12 | TileLayout 13 | v4.0 14 | 512 15 | Client 16 | 17 | 18 | true 19 | ..\bin\x64\Debug\Layouts\ 20 | DEBUG;TRACE 21 | full 22 | x64 23 | bin\Debug\TileLayout.dll.CodeAnalysisLog.xml 24 | true 25 | GlobalSuppressions.cs 26 | prompt 27 | MinimumRecommendedRules.ruleset 28 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 29 | false 30 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 31 | false 32 | false 33 | true 34 | 35 | 36 | ..\bin\x64\Release\Layouts\ 37 | 38 | 39 | true 40 | none 41 | x64 42 | bin\Release\TileLayout.dll.CodeAnalysisLog.xml 43 | true 44 | GlobalSuppressions.cs 45 | prompt 46 | MinimumRecommendedRules.ruleset 47 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 48 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 49 | false 50 | 51 | 52 | true 53 | ..\bin\x86\Debug\Layouts\ 54 | DEBUG;TRACE 55 | full 56 | x86 57 | bin\Debug\TileLayout.dll.CodeAnalysisLog.xml 58 | true 59 | GlobalSuppressions.cs 60 | prompt 61 | MinimumRecommendedRules.ruleset 62 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 63 | false 64 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 65 | false 66 | true 67 | 68 | 69 | ..\bin\x86\Release\Layouts\ 70 | 71 | 72 | true 73 | none 74 | x86 75 | bin\Release\TileLayout.dll.CodeAnalysisLog.xml 76 | true 77 | GlobalSuppressions.cs 78 | prompt 79 | MinimumRecommendedRules.ruleset 80 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 81 | false 82 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 83 | false 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | {90BCA858-A66A-42BF-A560-F956550FF9FE} 96 | Windawesome 97 | False 98 | 99 | 100 | 101 | 108 | -------------------------------------------------------------------------------- /ShortcutsManager/ShortcutsManager.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {F708858D-F410-437B-997E-1373E44C5DA4} 9 | Library 10 | Properties 11 | Windawesome 12 | ShortcutsManager 13 | v4.0 14 | 512 15 | Client 16 | 17 | 18 | true 19 | ..\bin\x64\Debug\Plugins\ 20 | DEBUG;TRACE 21 | full 22 | x64 23 | bin\Debug\ShortcutsManager.dll.CodeAnalysisLog.xml 24 | true 25 | GlobalSuppressions.cs 26 | prompt 27 | MinimumRecommendedRules.ruleset 28 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 29 | true 30 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 31 | true 32 | true 33 | 34 | 35 | ..\bin\x64\Release\Plugins\ 36 | 37 | 38 | true 39 | none 40 | x64 41 | bin\Release\ShortcutsManager.dll.CodeAnalysisLog.xml 42 | true 43 | GlobalSuppressions.cs 44 | prompt 45 | MinimumRecommendedRules.ruleset 46 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 47 | false 48 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 49 | false 50 | 51 | 52 | true 53 | ..\bin\x86\Debug\Plugins\ 54 | DEBUG;TRACE 55 | full 56 | x86 57 | bin\Debug\ShortcutsManager.dll.CodeAnalysisLog.xml 58 | true 59 | GlobalSuppressions.cs 60 | prompt 61 | MinimumRecommendedRules.ruleset 62 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 63 | true 64 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 65 | true 66 | true 67 | 68 | 69 | ..\bin\x86\Release\Plugins\ 70 | 71 | 72 | true 73 | none 74 | x86 75 | bin\Release\ShortcutsManager.dll.CodeAnalysisLog.xml 76 | true 77 | GlobalSuppressions.cs 78 | prompt 79 | MinimumRecommendedRules.ruleset 80 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 81 | false 82 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 83 | false 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | {90BCA858-A66A-42BF-A560-F956550FF9FE} 96 | Windawesome 97 | False 98 | 99 | 100 | 101 | 108 | -------------------------------------------------------------------------------- /Windawesome/Utilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Drawing; 4 | using System.Runtime.InteropServices; 5 | using System.Threading.Tasks; 6 | 7 | namespace Windawesome 8 | { 9 | public static class Utilities 10 | { 11 | public static void MoveMouseToMiddleOf(Rectangle bounds) 12 | { 13 | NativeMethods.SetCursorPos((bounds.Left + bounds.Right) / 2, (bounds.Top + bounds.Bottom) / 2); 14 | } 15 | 16 | public static IntPtr GetRootOwner(IntPtr hWnd) 17 | { 18 | var result = hWnd; 19 | hWnd = NativeMethods.GetWindow(hWnd, NativeMethods.GW.GW_OWNER); 20 | while (hWnd != IntPtr.Zero && hWnd != result) 21 | { 22 | result = hWnd; 23 | hWnd = NativeMethods.GetWindow(hWnd, NativeMethods.GW.GW_OWNER); 24 | } 25 | return result; 26 | } 27 | 28 | public static IntPtr DoForSelfAndOwnersWhile(IntPtr hWnd, Predicate action) 29 | { 30 | while (hWnd != IntPtr.Zero && action(hWnd)) 31 | { 32 | hWnd = NativeMethods.GetWindow(hWnd, NativeMethods.GW.GW_OWNER); 33 | } 34 | return hWnd; 35 | } 36 | 37 | // http://blogs.msdn.com/b/oldnewthing/archive/2007/10/08/5351207.aspx 38 | // http://stackoverflow.com/questions/210504/enumerate-windows-like-alt-tab-does 39 | public static bool IsAltTabWindow(IntPtr hWnd) 40 | { 41 | var exStyle = NativeMethods.GetWindowExStyleLongPtr(hWnd); 42 | if (exStyle.HasFlag(NativeMethods.WS_EX.WS_EX_TOOLWINDOW) || 43 | NativeMethods.GetWindow(hWnd, NativeMethods.GW.GW_OWNER) != IntPtr.Zero) 44 | { 45 | return false; 46 | } 47 | if (exStyle.HasFlag(NativeMethods.WS_EX.WS_EX_APPWINDOW)) 48 | { 49 | return true; 50 | } 51 | 52 | // Start at the root owner 53 | var hWndTry = NativeMethods.GetAncestor(hWnd, NativeMethods.GA.GA_ROOTOWNER); 54 | IntPtr oldHWnd; 55 | 56 | // See if we are the last active visible popup 57 | do 58 | { 59 | oldHWnd = hWndTry; 60 | hWndTry = NativeMethods.GetLastActivePopup(hWndTry); 61 | } 62 | while (oldHWnd != hWndTry && !NativeMethods.IsWindowVisible(hWndTry)); 63 | 64 | return hWndTry == hWnd; 65 | } 66 | 67 | public static bool IsAppWindow(IntPtr hWnd) 68 | { 69 | return NativeMethods.IsWindowVisible(hWnd) && 70 | !NativeMethods.GetWindowExStyleLongPtr(hWnd).HasFlag(NativeMethods.WS_EX.WS_EX_NOACTIVATE) && 71 | !NativeMethods.GetWindowStyleLongPtr(hWnd).HasFlag(NativeMethods.WS.WS_CHILD); 72 | } 73 | 74 | public static bool IsVisibleAndNotHung(Window window) 75 | { 76 | return NativeMethods.IsWindowVisible(window.hWnd) && WindowIsNotHung(window.hWnd); 77 | } 78 | 79 | public static bool WindowIsNotHung(Window window) 80 | { 81 | return WindowIsNotHung(window.hWnd); 82 | } 83 | 84 | public static bool WindowIsNotHung(IntPtr hWnd) 85 | { 86 | // IsHungAppWindow is not going to work, as it starts returning true 5 seconds after the window 87 | // has hung - so if a SetWindowPos, e.g., is called on such a window, it may block forever, even 88 | // though IsHungAppWindow returned false 89 | 90 | // SendMessageTimeout with a small timeout will timeout for some programs which are heavy on 91 | // computation and do not respond in time - like Visual Studio. A big timeout works, but if an 92 | // application is really hung, then Windawesome is blocked for this number of milliseconds. 93 | // That can be felt and is annoying. Perhaps the best scenario is: 94 | // return !IsHungAppWindow && (SendMessageTimeout(with_big_timeout) || GetLastWin32Error) 95 | // As this will not block forever at any point and it will only block the main thread for "with_big_timeout" 96 | // milliseconds the first 5 seconds when a program is hung - after that IsHungAppWindow catches it 97 | // immediately and returns. However, I decided that in most cases apps are not hung, so the overhead 98 | // of calling IsHungAppWindow AND SendMessageTimeout is not worth. 99 | 100 | return NativeMethods.SendMessageTimeout(hWnd, NativeMethods.WM_NULL, UIntPtr.Zero, IntPtr.Zero, 101 | NativeMethods.SMTO.SMTO_ABORTIFHUNG | NativeMethods.SMTO.SMTO_BLOCK, 3000, IntPtr.Zero) != IntPtr.Zero; 102 | } 103 | 104 | public static void QuitApplication(IntPtr hWnd) 105 | { 106 | NativeMethods.SendNotifyMessage(hWnd, NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_CLOSE, IntPtr.Zero); 107 | } 108 | 109 | public static void MinimizeApplication(IntPtr hWnd) 110 | { 111 | NativeMethods.SendNotifyMessage(hWnd, NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_MINIMIZE, IntPtr.Zero); 112 | } 113 | 114 | public static void MaximizeApplication(IntPtr hWnd) 115 | { 116 | NativeMethods.SendNotifyMessage(hWnd, NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_MAXIMIZE, IntPtr.Zero); 117 | } 118 | 119 | public static void RestoreApplication(IntPtr hWnd) 120 | { 121 | NativeMethods.SendNotifyMessage(hWnd, NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_RESTORE, IntPtr.Zero); 122 | } 123 | 124 | public static void RunApplication(string path, string arguments = "") 125 | { 126 | Task.Factory.StartNew(() => 127 | { 128 | if (SystemAndProcessInformation.isAtLeastVista && SystemAndProcessInformation.isRunningElevated) 129 | { 130 | NativeMethods.RunApplicationNonElevated(path, arguments); // TODO: this is not working on XP 131 | } 132 | else 133 | { 134 | Process.Start(path, arguments); 135 | } 136 | }); 137 | } 138 | 139 | public static void GetWindowSmallIconAsBitmap(IntPtr hWnd, Action action) 140 | { 141 | IntPtr result; 142 | NativeMethods.SendMessageTimeout(hWnd, NativeMethods.WM_GETICON, NativeMethods.ICON_SMALL, 143 | IntPtr.Zero, NativeMethods.SMTO.SMTO_BLOCK, 500, out result); 144 | 145 | if (result == IntPtr.Zero) 146 | { 147 | NativeMethods.SendMessageTimeout(hWnd, NativeMethods.WM_QUERYDRAGICON, UIntPtr.Zero, 148 | IntPtr.Zero, NativeMethods.SMTO.SMTO_BLOCK, 500, out result); 149 | } 150 | 151 | if (result == IntPtr.Zero) 152 | { 153 | result = NativeMethods.GetClassLongPtr(hWnd, NativeMethods.GCL_HICONSM); 154 | } 155 | 156 | if (result == IntPtr.Zero) 157 | { 158 | Task.Factory.StartNew(hWnd2 => 159 | { 160 | Bitmap bitmap = null; 161 | try 162 | { 163 | int processId; 164 | NativeMethods.GetWindowThreadProcessId((IntPtr) hWnd2, out processId); 165 | var processFileName = Process.GetProcessById(processId).MainModule.FileName; 166 | 167 | var info = new NativeMethods.SHFILEINFO(); 168 | 169 | NativeMethods.SHGetFileInfo(processFileName, 0, ref info, 170 | Marshal.SizeOf(info), NativeMethods.SHGFI_ICON | NativeMethods.SHGFI_SMALLICON); 171 | 172 | if (info.hIcon != IntPtr.Zero) 173 | { 174 | bitmap = new Bitmap(Bitmap.FromHicon(info.hIcon), SystemAndProcessInformation.smallIconSize); 175 | NativeMethods.DestroyIcon(info.hIcon); 176 | } 177 | else 178 | { 179 | var icon = Icon.ExtractAssociatedIcon(processFileName); 180 | if (icon != null) 181 | { 182 | bitmap = new Bitmap(icon.ToBitmap(), SystemAndProcessInformation.smallIconSize); 183 | } 184 | } 185 | } 186 | catch 187 | { 188 | } 189 | 190 | return bitmap; 191 | }, hWnd).ContinueWith(t => action(t.Result), TaskScheduler.FromCurrentSynchronizationContext()); 192 | } 193 | else 194 | { 195 | Bitmap bitmap = null; 196 | try 197 | { 198 | bitmap = new Bitmap(Bitmap.FromHicon(result), SystemAndProcessInformation.smallIconSize); 199 | } 200 | catch 201 | { 202 | } 203 | action(bitmap); 204 | } 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /Windawesome/SystemSettingsChanger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Windawesome 4 | { 5 | internal static class SystemSettingsChanger 6 | { 7 | private static readonly NativeMethods.NONCLIENTMETRICS originalNonClientMetrics; 8 | private static readonly NativeMethods.ANIMATIONINFO originalAnimationInfo; 9 | private static readonly bool originalHideMouseWhenTyping; 10 | private static readonly bool originalFocusFollowsMouse; 11 | private static readonly bool originalFocusFollowsMouseSetOnTop; 12 | 13 | static SystemSettingsChanger() 14 | { 15 | originalNonClientMetrics = NativeMethods.NONCLIENTMETRICS.Default; 16 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_GETNONCLIENTMETRICS, originalNonClientMetrics.cbSize, 17 | ref originalNonClientMetrics, 0); 18 | 19 | originalAnimationInfo = NativeMethods.ANIMATIONINFO.Default; 20 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_GETANIMATION, originalAnimationInfo.cbSize, 21 | ref originalAnimationInfo, 0); 22 | 23 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_GETMOUSEVANISH, 0, 24 | ref originalHideMouseWhenTyping, 0); 25 | 26 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_GETACTIVEWINDOWTRACKING, 0, 27 | ref originalFocusFollowsMouse, 0); 28 | 29 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_GETACTIVEWNDTRKZORDER, 0, 30 | ref originalFocusFollowsMouseSetOnTop, 0); 31 | } 32 | 33 | public static void ApplyChanges(Config config) 34 | { 35 | System.Threading.Tasks.Task.Factory.StartNew(() => 36 | { 37 | // set the "hide mouse when typing" 38 | if (config.HideMouseWhenTyping != originalHideMouseWhenTyping) 39 | { 40 | var hideMouseWhenTyping = config.HideMouseWhenTyping; 41 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETMOUSEVANISH, 0, 42 | ref hideMouseWhenTyping, 0); 43 | 44 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 45 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETMOUSEVANISH, IntPtr.Zero); 46 | } 47 | 48 | // set the "focus follows mouse" 49 | if (config.FocusFollowsMouse != originalFocusFollowsMouse) 50 | { 51 | var focusFollowsMouse = config.FocusFollowsMouse; 52 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETACTIVEWINDOWTRACKING, 0, 53 | ref focusFollowsMouse, 0); 54 | 55 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 56 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETACTIVEWINDOWTRACKING, IntPtr.Zero); 57 | } 58 | 59 | // set the "set window on top on focus follows mouse" 60 | if (config.FocusFollowsMouseSetOnTop != originalFocusFollowsMouseSetOnTop) 61 | { 62 | var focusFollowsMouseSetOnTop = config.FocusFollowsMouseSetOnTop; 63 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETACTIVEWNDTRKZORDER, 0, 64 | ref focusFollowsMouseSetOnTop, 0); 65 | 66 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 67 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETACTIVEWNDTRKZORDER, IntPtr.Zero); 68 | } 69 | 70 | // set the minimize/maximize/restore animations 71 | if ((originalAnimationInfo.iMinAnimate == 1 && !config.ShowMinimizeMaximizeRestoreAnimations) || 72 | (originalAnimationInfo.iMinAnimate == 0 && config.ShowMinimizeMaximizeRestoreAnimations)) 73 | { 74 | var animationInfo = originalAnimationInfo; 75 | animationInfo.iMinAnimate = config.ShowMinimizeMaximizeRestoreAnimations ? 1 : 0; 76 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETANIMATION, animationInfo.cbSize, 77 | ref animationInfo, 0); 78 | 79 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 80 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETANIMATION, IntPtr.Zero); 81 | } 82 | 83 | // set the global border and padded border widths 84 | if ((config.WindowBorderWidth >= 0 && originalNonClientMetrics.iBorderWidth != config.WindowBorderWidth) || 85 | (SystemAndProcessInformation.isAtLeastVista && config.WindowPaddedBorderWidth >= 0 && originalNonClientMetrics.iPaddedBorderWidth != config.WindowPaddedBorderWidth)) 86 | { 87 | var metrics = originalNonClientMetrics; 88 | metrics.iBorderWidth = config.WindowBorderWidth; 89 | metrics.iPaddedBorderWidth = config.WindowPaddedBorderWidth; 90 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETNONCLIENTMETRICS, metrics.cbSize, 91 | ref metrics, 0); 92 | 93 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 94 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETNONCLIENTMETRICS, IntPtr.Zero); 95 | } 96 | }); 97 | } 98 | 99 | public static void RevertChanges(Config config) 100 | { 101 | var thread = new System.Threading.Thread(() => // this has to be a foreground thread 102 | { 103 | // revert the hiding of the mouse when typing 104 | if (config.HideMouseWhenTyping != originalHideMouseWhenTyping) 105 | { 106 | var hideMouseWhenTyping = originalHideMouseWhenTyping; 107 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETMOUSEVANISH, 0, 108 | ref hideMouseWhenTyping, NativeMethods.SPIF.SPIF_UPDATEINIFILE); 109 | 110 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 111 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETMOUSEVANISH, IntPtr.Zero); 112 | } 113 | 114 | // revert the "focus follows mouse" 115 | if (config.FocusFollowsMouse != originalFocusFollowsMouse) 116 | { 117 | var focusFollowsMouse = originalFocusFollowsMouse; 118 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETACTIVEWINDOWTRACKING, 0, 119 | ref focusFollowsMouse, NativeMethods.SPIF.SPIF_UPDATEINIFILE); 120 | 121 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 122 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETACTIVEWINDOWTRACKING, IntPtr.Zero); 123 | } 124 | 125 | // revert the "set window on top on focus follows mouse" 126 | if (config.FocusFollowsMouseSetOnTop != originalFocusFollowsMouseSetOnTop) 127 | { 128 | var focusFollowsMouseSetOnTop = originalFocusFollowsMouseSetOnTop; 129 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETACTIVEWNDTRKZORDER, 0, 130 | ref focusFollowsMouseSetOnTop, NativeMethods.SPIF.SPIF_UPDATEINIFILE); 131 | 132 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 133 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETACTIVEWNDTRKZORDER, IntPtr.Zero); 134 | } 135 | 136 | // revert the minimize/maximize/restore animations 137 | if ((originalAnimationInfo.iMinAnimate == 1 && !config.ShowMinimizeMaximizeRestoreAnimations) || 138 | (originalAnimationInfo.iMinAnimate == 0 && config.ShowMinimizeMaximizeRestoreAnimations)) 139 | { 140 | var animationInfo = originalAnimationInfo; 141 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETANIMATION, animationInfo.cbSize, 142 | ref animationInfo, NativeMethods.SPIF.SPIF_UPDATEINIFILE); 143 | 144 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 145 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETANIMATION, IntPtr.Zero); 146 | } 147 | 148 | // revert the size of non-client area of windows 149 | if ((config.WindowBorderWidth >= 0 && originalNonClientMetrics.iBorderWidth != config.WindowBorderWidth) || 150 | (SystemAndProcessInformation.isAtLeastVista && config.WindowPaddedBorderWidth >= 0 && originalNonClientMetrics.iPaddedBorderWidth != config.WindowPaddedBorderWidth)) 151 | { 152 | var metrics = originalNonClientMetrics; 153 | NativeMethods.SystemParametersInfo(NativeMethods.SPI.SPI_SETNONCLIENTMETRICS, metrics.cbSize, 154 | ref metrics, NativeMethods.SPIF.SPIF_UPDATEINIFILE); 155 | 156 | NativeMethods.SendNotifyMessage(NativeMethods.HWND_BROADCAST, NativeMethods.WM_SETTINGCHANGE, 157 | (UIntPtr) (uint) NativeMethods.SPI.SPI_SETNONCLIENTMETRICS, IntPtr.Zero); 158 | } 159 | }); 160 | thread.Start(); 161 | 162 | new System.Threading.Timer(_ => 163 | { 164 | // SystemParametersInfo sometimes hangs because of SPI_SETNONCLIENTMETRICS, 165 | // even though SPIF_SENDCHANGE is not added to the flags 166 | if (thread.IsAlive) 167 | { 168 | thread.Abort(); 169 | Environment.Exit(0); 170 | } 171 | }, null, 5000, 0); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /Config/3-Hotkeys.rb: -------------------------------------------------------------------------------- 1 | 2 | def subscribe(modifiers, key) 3 | Windawesome::ShortcutsManager.subscribe modifiers, key, lambda { 4 | ret = yield 5 | return true if ret == nil 6 | ret 7 | } 8 | end 9 | 10 | flashing_window = nil 11 | previous_workspace = config.workspaces[0] 12 | 13 | def get_current_workspace_managed_window 14 | _, window, _ = windawesome.try_get_managed_window_for_workspace Windawesome::NativeMethods.get_foreground_window, windawesome.current_workspace 15 | window 16 | end 17 | 18 | Windawesome::Windawesome.window_flashing { |hWnd, l| flashing_window = hWnd } 19 | 20 | Windawesome::Workspace.workspace_deactivated { |ws| previous_workspace = ws } 21 | 22 | modifiers = Windawesome::ShortcutsManager::KeyModifiers 23 | key = System::Windows::Forms::Keys 24 | 25 | # quit Windawesome 26 | subscribe modifiers.Alt | modifiers.Shift, key.Q do 27 | windawesome.quit 28 | end 29 | 30 | # refresh Windawesome 31 | subscribe modifiers.Alt | modifiers.Shift, key.R do 32 | windawesome.refresh_windawesome 33 | end 34 | 35 | # quit application 36 | subscribe modifiers.Alt, key.Q do 37 | hWnd = Windawesome::NativeMethods.get_foreground_window 38 | Windawesome::Utilities.quit_application hWnd if Windawesome::NativeMethods.get_window_class_name(hWnd) != "WorkerW" 39 | end 40 | 41 | subscribe modifiers.Control | modifiers.Alt | modifiers.Shift, key.Q do 42 | windawesome.remove_application_from_workspace Windawesome::NativeMethods.get_foreground_window 43 | end 44 | 45 | # dismiss application 46 | subscribe modifiers.Alt, key.D do 47 | windawesome.dismiss_temporarily_shown_window Windawesome::NativeMethods.get_foreground_window 48 | end 49 | 50 | # minimize application 51 | subscribe modifiers.Alt, key.A do 52 | Windawesome::Utilities.minimize_application Windawesome::NativeMethods.get_foreground_window 53 | end 54 | 55 | # maximize or restore application 56 | subscribe modifiers.Alt, key.S do 57 | window = Windawesome::NativeMethods.get_foreground_window 58 | ws = Windawesome::NativeMethods.get_window_style_long_ptr.invoke window 59 | if ws.has_flag Windawesome::NativeMethods::WS.WS_MAXIMIZE 60 | Windawesome::Utilities.restore_application window 61 | elsif ws.has_flag Windawesome::NativeMethods::WS.WS_CAPTION and ws.has_flag Windawesome::NativeMethods::WS.WS_MAXIMIZEBOX 62 | Windawesome::Utilities.maximize_application window 63 | end 64 | end 65 | 66 | # switch to previous workspace 67 | subscribe modifiers.Alt, key.Oemtilde do 68 | windawesome.switch_to_workspace previous_workspace.id 69 | end 70 | 71 | # start Firefox 72 | subscribe modifiers.Alt, key.F do 73 | windawesome.run_or_show_application "^MozillaWindowClass$", "C:\\Program Files (x86)\\Pale Moon\\palemoon.exe" 74 | end 75 | 76 | # start Explorer 77 | subscribe modifiers.Alt, key.E do 78 | Windawesome::Utilities.run_application "C:\\Users\\Boris\\Desktop\\Downloads.lnk" 79 | end 80 | 81 | # start Hostile Takeover 82 | subscribe modifiers.Alt, key.H do 83 | Windawesome::Utilities.run_application "C:\\Program Files (x86)\\Vim\\vim73\\gvim.exe", "\"C:\\Users\\Boris\\Downloads\\Hostile Takeover.txt\"" 84 | end 85 | 86 | # start Foobar2000 87 | subscribe modifiers.Alt, key.W do 88 | Windawesome::Utilities.run_application "C:\\Program Files (x86)\\foobar2000\\foobar2000.exe" 89 | end 90 | 91 | # start Cygwin's MinTTY shell 92 | subscribe modifiers.Alt | modifiers.Shift, key.Return do 93 | Windawesome::Utilities.run_application "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Cygwin\\Cygwin Terminal.lnk" 94 | end 95 | 96 | # start Bitcomet 97 | subscribe modifiers.Alt, key.B do 98 | Windawesome::Utilities.run_application "C:\\Program Files\\BitComet\\BitComet.exe" 99 | end 100 | 101 | # switch to flashing window 102 | subscribe modifiers.Alt, key.U do 103 | windawesome.switch_to_application flashing_window if flashing_window 104 | end 105 | 106 | # toggle window floating 107 | subscribe modifiers.Control | modifiers.Alt | modifiers.Shift, key.F do 108 | windawesome.toggle_window_floating Windawesome::NativeMethods.get_foreground_window 109 | end 110 | 111 | # toggle window titlebar 112 | subscribe modifiers.Alt | modifiers.Shift, key.D do 113 | windawesome.toggle_show_hide_window_titlebar Windawesome::NativeMethods.get_foreground_window 114 | end 115 | 116 | # toggle Windows taskbar 117 | subscribe modifiers.Alt | modifiers.Control, key.Space do 118 | windawesome.toggle_taskbar_visibility 119 | end 120 | 121 | # toggle window border 122 | subscribe modifiers.Alt | modifiers.Shift, key.B do 123 | windawesome.toggle_show_hide_window_border Windawesome::NativeMethods.get_foreground_window 124 | end 125 | 126 | # toggle window menu 127 | subscribe modifiers.Control | modifiers.Alt | modifiers.Shift, key.M do 128 | windawesome.toggle_show_hide_window_menu Windawesome::NativeMethods.get_foreground_window 129 | end 130 | 131 | # Layout stuff 132 | 133 | subscribe modifiers.Alt | modifiers.Shift, key.T do # change layout to Tile 134 | windawesome.current_workspace.change_layout Windawesome::TileLayout.new 135 | end 136 | 137 | subscribe modifiers.Alt | modifiers.Shift, key.M do # change layout to Full Screen 138 | windawesome.current_workspace.change_layout Windawesome::FullScreenLayout.new 139 | end 140 | 141 | subscribe modifiers.Alt | modifiers.Shift, key.F do # change layout to Floating 142 | windawesome.current_workspace.change_layout Windawesome::FloatingLayout.new 143 | end 144 | 145 | # window position stuff 146 | 147 | subscribe modifiers.Alt, key.J do 148 | window = get_current_workspace_managed_window 149 | if window 150 | next_window = windawesome.current_workspace.get_next_window window 151 | windawesome.switch_to_application next_window.hWnd if next_window 152 | elsif windawesome.current_workspace.get_windows_count > 0 153 | windawesome.switch_to_application windawesome.current_workspace.get_windows.first.value.hWnd 154 | end 155 | end 156 | 157 | subscribe modifiers.Alt, key.K do 158 | window = get_current_workspace_managed_window 159 | if window 160 | previous_window = windawesome.current_workspace.get_previous_window window 161 | windawesome.switch_to_application previous_window.hWnd if previous_window 162 | elsif windawesome.current_workspace.get_windows_count > 0 163 | windawesome.switch_to_application windawesome.current_workspace.get_windows.first.value.hWnd 164 | end 165 | end 166 | 167 | subscribe modifiers.Alt | modifiers.Shift, key.J do 168 | window = get_current_workspace_managed_window 169 | windawesome.current_workspace.shift_window_forward window if window 170 | end 171 | 172 | subscribe modifiers.Alt | modifiers.Shift, key.K do 173 | window = get_current_workspace_managed_window 174 | windawesome.current_workspace.shift_window_backwards window if window 175 | end 176 | 177 | subscribe modifiers.Control | modifiers.Alt | modifiers.Shift, key.Return do 178 | window = get_current_workspace_managed_window 179 | windawesome.current_workspace.shift_window_to_main_position window if window 180 | end 181 | 182 | # Tile Layout stuff 183 | 184 | subscribe modifiers.Alt | modifiers.Shift, key.L do 185 | windawesome.current_workspace.layout.toggle_layout_axis if windawesome.current_workspace.layout.layout_name == "Tile" 186 | end 187 | 188 | subscribe modifiers.Alt | modifiers.Shift, key.S do 189 | windawesome.current_workspace.layout.toggle_stack_area_axis if windawesome.current_workspace.layout.layout_name == "Tile" 190 | end 191 | 192 | subscribe modifiers.Control | modifiers.Alt | modifiers.Shift, key.S do 193 | windawesome.current_workspace.layout.toggle_master_area_axis if windawesome.current_workspace.layout.layout_name == "Tile" 194 | end 195 | 196 | subscribe modifiers.Alt | modifiers.Shift, key.Left do 197 | windawesome.current_workspace.layout.add_to_master_area_factor(-0.05) if windawesome.current_workspace.layout.layout_name == "Tile" 198 | end 199 | 200 | subscribe modifiers.Alt | modifiers.Shift, key.Right do 201 | windawesome.current_workspace.layout.add_to_master_area_factor if windawesome.current_workspace.layout.layout_name == "Tile" 202 | end 203 | 204 | # Workspaces stuff 205 | 206 | (1 .. config.workspaces.length).each do |i| 207 | k = eval("key.D" + i.to_s) 208 | 209 | subscribe modifiers.Alt, k do 210 | windawesome.switch_to_workspace i 211 | end 212 | 213 | subscribe modifiers.Alt | modifiers.Shift, k do 214 | windawesome.change_application_to_workspace Windawesome::NativeMethods.get_foreground_window, i 215 | end 216 | 217 | subscribe modifiers.Control | modifiers.Alt | modifiers.Shift, k do 218 | windawesome.add_application_to_workspace Windawesome::NativeMethods.get_foreground_window, i 219 | end 220 | end 221 | -------------------------------------------------------------------------------- /ShortcutsManager/ShortcutsManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Windows.Forms; 6 | 7 | namespace Windawesome 8 | { 9 | public sealed class ShortcutsManager : IPlugin 10 | { 11 | private sealed class Subscription 12 | { 13 | private readonly Keys key; 14 | private readonly KeyModifiers modifiers; 15 | 16 | public Subscription(KeyModifiers modifiers, Keys key) 17 | { 18 | this.key = key; 19 | this.modifiers = modifiers; 20 | } 21 | 22 | public sealed class SubscriptionEqualityComparer : IEqualityComparer 23 | { 24 | #region IEqualityComparer Members 25 | 26 | bool IEqualityComparer.Equals(Subscription x, Subscription y) 27 | { 28 | if (((x.modifiers & KeyModifiers.Alt) != KeyModifiers.None || 29 | (y.modifiers & KeyModifiers.Alt) != KeyModifiers.None) && 30 | (x.modifiers & KeyModifiers.Alt & y.modifiers) == KeyModifiers.None) 31 | { 32 | return false; 33 | } 34 | if (((x.modifiers & KeyModifiers.Control) != KeyModifiers.None || 35 | (y.modifiers & KeyModifiers.Control) != KeyModifiers.None) && 36 | (x.modifiers & KeyModifiers.Control & y.modifiers) == KeyModifiers.None) 37 | { 38 | return false; 39 | } 40 | if (((x.modifiers & KeyModifiers.Shift) != KeyModifiers.None || 41 | (y.modifiers & KeyModifiers.Shift) != KeyModifiers.None) && 42 | (x.modifiers & KeyModifiers.Shift & y.modifiers) == KeyModifiers.None) 43 | { 44 | return false; 45 | } 46 | if (((x.modifiers & KeyModifiers.Win) != KeyModifiers.None || 47 | (y.modifiers & KeyModifiers.Win) != KeyModifiers.None) && 48 | (x.modifiers & KeyModifiers.Win & y.modifiers) == KeyModifiers.None) 49 | { 50 | return false; 51 | } 52 | return x.key == y.key; 53 | } 54 | 55 | int IEqualityComparer.GetHashCode(Subscription obj) 56 | { 57 | var modifiers = 0; 58 | if ((obj.modifiers & KeyModifiers.Alt) != KeyModifiers.None) 59 | { 60 | modifiers += 1; 61 | } 62 | if ((obj.modifiers & KeyModifiers.Control) != KeyModifiers.None) 63 | { 64 | modifiers += 2; 65 | } 66 | if ((obj.modifiers & KeyModifiers.Shift) != KeyModifiers.None) 67 | { 68 | modifiers += 4; 69 | } 70 | if ((obj.modifiers & KeyModifiers.Win) != KeyModifiers.None) 71 | { 72 | modifiers += 8; 73 | } 74 | 75 | return modifiers + 256 + (int) obj.key; 76 | } 77 | 78 | #endregion 79 | } 80 | } 81 | 82 | [Flags] 83 | public enum KeyModifiers 84 | { 85 | None = 0, 86 | 87 | LControl = 1, 88 | RControl = 2, 89 | Control = LControl | RControl, 90 | 91 | LShift = 4, 92 | RShift = 8, 93 | Shift = LShift | RShift, 94 | 95 | LAlt = 16, 96 | RAlt = 32, 97 | Alt = LAlt | RAlt, 98 | 99 | LWin = 64, 100 | RWin = 128, 101 | Win = LWin | RWin 102 | } 103 | 104 | public delegate bool KeyboardEventHandler(); 105 | private static readonly NativeMethods.HookProc keyboardHookProcedure = KeyboardHookProc; 106 | private static readonly List registeredHotkeys; 107 | private static IntPtr hook; 108 | private static Dictionary subscriptions; 109 | private static bool hasKeyOnlySubscriptions; 110 | 111 | static ShortcutsManager() 112 | { 113 | registeredHotkeys = new List(); 114 | } 115 | 116 | public static void Subscribe(KeyModifiers modifiers, Keys key, KeyboardEventHandler handler) 117 | { 118 | if ((modifiers & KeyModifiers.Control) == KeyModifiers.LControl || 119 | (modifiers & KeyModifiers.Control) == KeyModifiers.RControl || 120 | (modifiers & KeyModifiers.Alt) == KeyModifiers.LAlt || 121 | (modifiers & KeyModifiers.Alt) == KeyModifiers.RAlt || 122 | (modifiers & KeyModifiers.Shift) == KeyModifiers.LShift || 123 | (modifiers & KeyModifiers.Shift) == KeyModifiers.RShift || 124 | (modifiers & KeyModifiers.Win) == KeyModifiers.LWin || 125 | (modifiers & KeyModifiers.Win) == KeyModifiers.RWin) 126 | { 127 | if (hook == IntPtr.Zero) 128 | { 129 | subscriptions = new Dictionary(new Subscription.SubscriptionEqualityComparer()); 130 | 131 | hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_KEYBOARD_LL, keyboardHookProcedure, 132 | System.Diagnostics.Process.GetCurrentProcess().MainModule.BaseAddress, 0); 133 | } 134 | 135 | var newSubscription = new Subscription(modifiers, key); 136 | KeyboardEventHandler handlers; 137 | if (subscriptions.TryGetValue(newSubscription, out handlers)) 138 | { 139 | subscriptions[newSubscription] = handlers + handler; 140 | } 141 | else 142 | { 143 | subscriptions[newSubscription] = handler; 144 | } 145 | } 146 | else 147 | { 148 | NativeMethods.MOD mods = 0; 149 | if (modifiers.HasFlag(KeyModifiers.Control)) 150 | { 151 | mods |= NativeMethods.MOD.MOD_CONTROL; 152 | } 153 | if (modifiers.HasFlag(KeyModifiers.Alt)) 154 | { 155 | mods |= NativeMethods.MOD.MOD_ALT; 156 | } 157 | if (modifiers.HasFlag(KeyModifiers.Shift)) 158 | { 159 | mods |= NativeMethods.MOD.MOD_SHIFT; 160 | } 161 | if (modifiers.HasFlag(KeyModifiers.Win)) 162 | { 163 | mods |= NativeMethods.MOD.MOD_WIN; 164 | } 165 | NativeMethods.RegisterHotKey(Windawesome.HandleStatic, registeredHotkeys.Count, mods, key); 166 | registeredHotkeys.Add(handler); 167 | } 168 | 169 | hasKeyOnlySubscriptions |= modifiers == KeyModifiers.None; 170 | } 171 | 172 | private static IntPtr KeyboardHookProc(int nCode, UIntPtr wParam, IntPtr lParam) 173 | { 174 | if (nCode == 0) 175 | { 176 | if (wParam == NativeMethods.WM_KEYDOWN || wParam == NativeMethods.WM_SYSKEYDOWN) 177 | { 178 | var key = (Keys) Marshal.ReadInt32(lParam); 179 | if (key != Keys.LShiftKey && key != Keys.RShiftKey && 180 | key != Keys.LMenu && key != Keys.RMenu && 181 | key != Keys.LControlKey && key != Keys.RControlKey && 182 | key != Keys.LWin && key != Keys.RWin) 183 | { 184 | KeyModifiers modifiersPressed = 0; 185 | // there is no other way to distinguish between left and right modifier keys 186 | if ((NativeMethods.GetKeyState(Keys.LShiftKey) & 0x8000) == 0x8000) 187 | { 188 | modifiersPressed |= KeyModifiers.LShift; 189 | } 190 | if ((NativeMethods.GetKeyState(Keys.RShiftKey) & 0x8000) == 0x8000) 191 | { 192 | modifiersPressed |= KeyModifiers.RShift; 193 | } 194 | if ((NativeMethods.GetKeyState(Keys.LMenu) & 0x8000) == 0x8000) 195 | { 196 | modifiersPressed |= KeyModifiers.LAlt; 197 | } 198 | if ((NativeMethods.GetKeyState(Keys.RMenu) & 0x8000) == 0x8000) 199 | { 200 | modifiersPressed |= KeyModifiers.RAlt; 201 | } 202 | if ((NativeMethods.GetKeyState(Keys.LControlKey) & 0x8000) == 0x8000) 203 | { 204 | modifiersPressed |= KeyModifiers.LControl; 205 | } 206 | if ((NativeMethods.GetKeyState(Keys.RControlKey) & 0x8000) == 0x8000) 207 | { 208 | modifiersPressed |= KeyModifiers.RControl; 209 | } 210 | if ((NativeMethods.GetKeyState(Keys.LWin) & 0x8000) == 0x8000) 211 | { 212 | modifiersPressed |= KeyModifiers.LWin; 213 | } 214 | if ((NativeMethods.GetKeyState(Keys.RWin) & 0x8000) == 0x8000) 215 | { 216 | modifiersPressed |= KeyModifiers.RWin; 217 | } 218 | 219 | if (modifiersPressed != KeyModifiers.None || hasKeyOnlySubscriptions) 220 | { 221 | KeyboardEventHandler handlers; 222 | if (subscriptions.TryGetValue(new Subscription(modifiersPressed, key), out handlers)) 223 | { 224 | if (handlers.GetInvocationList().Cast().Any(handler => handler())) 225 | { 226 | return NativeMethods.IntPtrOne; 227 | } 228 | } 229 | } 230 | } 231 | } 232 | } 233 | 234 | return NativeMethods.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); 235 | } 236 | 237 | #region IPlugin Members 238 | 239 | void IPlugin.InitializePlugin(Windawesome windawesome) 240 | { 241 | windawesome.RegisterMessage(NativeMethods.WM_HOTKEY, 242 | (ref Message m) => registeredHotkeys[m.WParam.ToInt32()]()); 243 | } 244 | 245 | void IPlugin.Dispose() 246 | { 247 | if (hook != IntPtr.Zero) 248 | { 249 | NativeMethods.UnhookWindowsHookEx(hook); 250 | } 251 | Enumerable.Range(0, registeredHotkeys.Count).ForEach(i => NativeMethods.UnregisterHotKey(Windawesome.HandleStatic, i)); 252 | } 253 | 254 | #endregion 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /Windawesome/WorkspacesWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | 7 | namespace Windawesome 8 | { 9 | public sealed class WorkspacesWidget : IFixedWidthWidget 10 | { 11 | private Label[] workspaceLabels; 12 | private readonly Color[] normalForegroundColor; 13 | private readonly Color[] normalBackgroundColor; 14 | private readonly Color highlightedForegroundColor; 15 | private readonly Color highlightedBackgroundColor; 16 | private readonly Color highlightedInactiveForegroundColor; 17 | private readonly Color highlightedInactiveBackgroundColor; 18 | private readonly Color flashingForegroundColor; 19 | private readonly Color flashingBackgroundColor; 20 | private bool isLeft; 21 | private readonly bool flashWorkspaces; 22 | 23 | private static Windawesome windawesome; 24 | private static Timer flashTimer; 25 | private static Dictionary flashingWindows; 26 | private static HashSet flashingWorkspaces; 27 | 28 | private delegate void WorkFlashingStopped(Workspace workspace); 29 | private static event WorkFlashingStopped OnWorkspaceFlashingStopped; 30 | 31 | public WorkspacesWidget(IEnumerable normalForegroundColor = null, IEnumerable normalBackgroundColor = null, 32 | Color? highlightedForegroundColor = null, Color? highlightedBackgroundColor = null, 33 | Color? highlightedInactiveForegroundColor = null, Color? highlightedInactiveBackgroundColor = null, 34 | Color? flashingForegroundColor = null, Color? flashingBackgroundColor = null, bool flashWorkspaces = true) 35 | { 36 | this.normalForegroundColor = normalForegroundColor != null ? normalForegroundColor.ToArray() : new[] 37 | { 38 | Color.Black, Color.Black, Color.Black, Color.Black, Color.Black, 39 | Color.White, Color.White, Color.White, Color.White, Color.White 40 | }; 41 | this.normalBackgroundColor = normalBackgroundColor != null ? normalBackgroundColor.ToArray() : new[] 42 | { 43 | Color.FromArgb(0xF0, 0xF0, 0xF0), 44 | Color.FromArgb(0xD8, 0xD8, 0xD8), 45 | Color.FromArgb(0xC0, 0xC0, 0xC0), 46 | Color.FromArgb(0xA8, 0xA8, 0xA8), 47 | Color.FromArgb(0x90, 0x90, 0x90), 48 | Color.FromArgb(0x78, 0x78, 0x78), 49 | Color.FromArgb(0x60, 0x60, 0x60), 50 | Color.FromArgb(0x48, 0x48, 0x48), 51 | Color.FromArgb(0x30, 0x30, 0x30), 52 | Color.FromArgb(0x18, 0x18, 0x18) 53 | }; 54 | this.highlightedForegroundColor = highlightedForegroundColor ?? Color.White; 55 | this.highlightedBackgroundColor = highlightedBackgroundColor ?? Color.FromArgb(0x33, 0x99, 0xFF); 56 | this.highlightedInactiveForegroundColor = highlightedInactiveForegroundColor ?? Color.White; 57 | this.highlightedInactiveBackgroundColor = highlightedInactiveBackgroundColor ?? Color.Green; 58 | this.flashingForegroundColor = flashingForegroundColor ?? Color.White; 59 | this.flashingBackgroundColor = flashingBackgroundColor ?? Color.Red; 60 | this.flashWorkspaces = flashWorkspaces; 61 | if (flashWorkspaces) 62 | { 63 | if (flashTimer == null) 64 | { 65 | flashTimer = new Timer { Interval = 500 }; 66 | flashingWindows = new Dictionary(3); 67 | flashingWorkspaces = new HashSet(); 68 | 69 | Workspace.WorkspaceWindowRemoved += (_, w) => StopFlashingApplication(w.hWnd); 70 | Workspace.WindowActivatedEvent += StopFlashingApplication; 71 | Workspace.WorkspaceWindowRestored += (_, w) => StopFlashingApplication(w.hWnd); 72 | Windawesome.WindowFlashing += OnWindowFlashing; 73 | } 74 | } 75 | } 76 | 77 | private void OnWorkspaceLabelClick(object sender, EventArgs e) 78 | { 79 | windawesome.SwitchToWorkspace(Array.IndexOf(workspaceLabels, sender as Label) + 1); 80 | } 81 | 82 | private void SetWorkspaceLabelColor(Workspace workspace) 83 | { 84 | var workspaceLabel = workspaceLabels[workspace.id - 1]; 85 | if (workspace.IsCurrentWorkspace) 86 | { 87 | workspaceLabel.BackColor = highlightedBackgroundColor; 88 | workspaceLabel.ForeColor = highlightedForegroundColor; 89 | } 90 | else if (workspace.IsWorkspaceVisible) 91 | { 92 | workspaceLabel.BackColor = highlightedInactiveBackgroundColor; 93 | workspaceLabel.ForeColor = highlightedInactiveForegroundColor; 94 | } 95 | else 96 | { 97 | var count = workspace.GetWindowsCount(); 98 | if (count > 9) 99 | { 100 | count = 9; 101 | } 102 | workspaceLabel.BackColor = normalBackgroundColor[count]; 103 | workspaceLabel.ForeColor = normalForegroundColor[count]; 104 | } 105 | } 106 | 107 | private void OnWorkspaceChangedFromTo(Workspace workspace) 108 | { 109 | SetWorkspaceLabelColor(workspace); 110 | } 111 | 112 | private static void OnWindowFlashing(IntPtr hWnd, LinkedList> list) 113 | { 114 | if (list != null) 115 | { 116 | if (NativeMethods.IsWindow(hWnd) && !flashingWindows.ContainsKey(hWnd)) 117 | { 118 | var foregroundWindow = NativeMethods.GetForegroundWindow(); 119 | 120 | if (Utilities.DoForSelfAndOwnersWhile(foregroundWindow, h => h != hWnd) == IntPtr.Zero) 121 | { 122 | var workspace = list.First.Value.Item1; 123 | 124 | flashingWindows[hWnd] = workspace; 125 | flashingWorkspaces.Add(workspace); 126 | if (flashingWorkspaces.Count == 1) 127 | { 128 | flashTimer.Start(); 129 | } 130 | } 131 | } 132 | } 133 | } 134 | 135 | private static void StopFlashingApplication(IntPtr hWnd) 136 | { 137 | Workspace workspace; 138 | if (flashingWindows.TryGetValue(hWnd, out workspace)) 139 | { 140 | flashingWindows.Remove(hWnd); 141 | if (flashingWindows.Values.All(w => w != workspace)) 142 | { 143 | OnWorkspaceFlashingStopped(workspace); 144 | flashingWorkspaces.Remove(workspace); 145 | if (flashingWorkspaces.Count == 0) 146 | { 147 | flashTimer.Stop(); 148 | } 149 | } 150 | } 151 | } 152 | 153 | private void OnTimerTick(object sender, EventArgs e) 154 | { 155 | foreach (var flashingWorkspace in flashingWorkspaces) 156 | { 157 | if (workspaceLabels[flashingWorkspace.id - 1].BackColor == flashingBackgroundColor) 158 | { 159 | SetWorkspaceLabelColor(flashingWorkspace); 160 | } 161 | else 162 | { 163 | workspaceLabels[flashingWorkspace.id - 1].BackColor = flashingBackgroundColor; 164 | workspaceLabels[flashingWorkspace.id - 1].ForeColor = flashingForegroundColor; 165 | } 166 | } 167 | } 168 | 169 | #region IWidget Members 170 | 171 | void IWidget.StaticInitializeWidget(Windawesome windawesome) 172 | { 173 | WorkspacesWidget.windawesome = windawesome; 174 | } 175 | 176 | void IWidget.InitializeWidget(Bar bar) 177 | { 178 | if (flashWorkspaces) 179 | { 180 | flashTimer.Tick += OnTimerTick; 181 | OnWorkspaceFlashingStopped += SetWorkspaceLabelColor; 182 | } 183 | 184 | bar.BarShown += () => flashTimer.Start(); 185 | bar.BarHidden += () => flashTimer.Stop(); 186 | 187 | workspaceLabels = new Label[windawesome.config.Workspaces.Length]; 188 | 189 | Workspace.WorkspaceWindowAdded += (ws, _) => SetWorkspaceLabelColor(ws); 190 | Workspace.WorkspaceWindowRemoved += (ws, _) => SetWorkspaceLabelColor(ws); 191 | 192 | Workspace.WorkspaceDeactivated += OnWorkspaceChangedFromTo; 193 | Workspace.WorkspaceActivated += OnWorkspaceChangedFromTo; 194 | Workspace.WorkspaceShown += OnWorkspaceChangedFromTo; 195 | Workspace.WorkspaceHidden += OnWorkspaceChangedFromTo; 196 | 197 | for (var i = 0; i < windawesome.config.Workspaces.Length; i++) 198 | { 199 | var workspace = windawesome.config.Workspaces[i]; 200 | var name = workspace.name ?? (i + 1).ToString(); 201 | 202 | var label = bar.CreateLabel(" " + name + " ", 0); 203 | label.TextAlign = ContentAlignment.MiddleCenter; 204 | label.Click += OnWorkspaceLabelClick; 205 | workspaceLabels[i] = label; 206 | SetWorkspaceLabelColor(workspace); 207 | } 208 | } 209 | 210 | IEnumerable IFixedWidthWidget.GetInitialControls(bool isLeft) 211 | { 212 | this.isLeft = isLeft; 213 | 214 | return workspaceLabels; 215 | } 216 | 217 | public void RepositionControls(int left, int right) 218 | { 219 | if (isLeft) 220 | { 221 | foreach (var label in workspaceLabels) 222 | { 223 | label.Location = new Point(left, 0); 224 | left += label.Width; 225 | } 226 | } 227 | else 228 | { 229 | foreach (var label in NativeMethods.Reverse(workspaceLabels)) 230 | { 231 | right -= label.Width; 232 | label.Location = new Point(right, 0); 233 | } 234 | } 235 | } 236 | 237 | int IWidget.GetLeft() 238 | { 239 | return workspaceLabels.First().Left; 240 | } 241 | 242 | int IWidget.GetRight() 243 | { 244 | return workspaceLabels.Last().Right; 245 | } 246 | 247 | void IWidget.StaticDispose() 248 | { 249 | } 250 | 251 | void IWidget.Dispose() 252 | { 253 | } 254 | 255 | void IWidget.Refresh() 256 | { 257 | // remove all flashing windows 258 | flashingWindows.Keys.ToArray().ForEach(StopFlashingApplication); 259 | } 260 | 261 | #endregion 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /WindowSubclassingCSharp/WindowSubclassingCSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1} 9 | Library 10 | Properties 11 | Windawesome 12 | WindowSubclassingCSharp 13 | v4.0 14 | 512 15 | Client 16 | 17 | 18 | true 19 | ..\bin\x64\Debug\Plugins\ 20 | DEBUG;TRACE 21 | full 22 | x64 23 | bin\Debug\WindowSubclassingCSharp.dll.CodeAnalysisLog.xml 24 | true 25 | GlobalSuppressions.cs 26 | prompt 27 | MinimumRecommendedRules.ruleset 28 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 29 | false 30 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 31 | false 32 | 33 | 34 | ..\bin\x64\Release\Plugins\ 35 | 36 | 37 | true 38 | none 39 | x64 40 | bin\Release\WindowSubclassingCSharp.dll.CodeAnalysisLog.xml 41 | true 42 | GlobalSuppressions.cs 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 46 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 47 | 48 | 49 | true 50 | ..\bin\x86\Debug\Plugins\ 51 | DEBUG;TRACE 52 | full 53 | x86 54 | bin\Debug\WindowSubclassingCSharp.dll.CodeAnalysisLog.xml 55 | true 56 | GlobalSuppressions.cs 57 | prompt 58 | MinimumRecommendedRules.ruleset 59 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 60 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 61 | 62 | 63 | ..\bin\x86\Release\Plugins\ 64 | 65 | 66 | true 67 | none 68 | x86 69 | bin\Release\WindowSubclassingCSharp.dll.CodeAnalysisLog.xml 70 | true 71 | GlobalSuppressions.cs 72 | prompt 73 | MinimumRecommendedRules.ruleset 74 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 75 | false 76 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 77 | false 78 | 79 | 80 | ..\bin\x64\Release Profiling\Plugins\ 81 | true 82 | x64 83 | bin\Release\WindowSubclassingCSharp.dll.CodeAnalysisLog.xml 84 | true 85 | GlobalSuppressions.cs 86 | prompt 87 | MinimumRecommendedRules.ruleset 88 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 89 | true 90 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 91 | true 92 | full 93 | true 94 | 95 | 96 | ..\bin\x86\Release Profiling\Plugins\ 97 | true 98 | x86 99 | bin\Release\WindowSubclassingCSharp.dll.CodeAnalysisLog.xml 100 | true 101 | GlobalSuppressions.cs 102 | prompt 103 | MinimumRecommendedRules.ruleset 104 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets 105 | false 106 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules 107 | false 108 | full 109 | true 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | {90BCA858-A66A-42BF-A560-F956550FF9FE} 122 | Windawesome 123 | False 124 | 125 | 126 | 127 | 134 | -------------------------------------------------------------------------------- /Windawesome.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowSubclassing", "WindowSubclassing\WindowSubclassing.vcxproj", "{67670ECC-FD00-4B7C-8748-00A168FA9768}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SystemTrayHook", "SystemTrayHook\SystemTrayHook.vcxproj", "{4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Windawesome", "Windawesome\Windawesome.csproj", "{90BCA858-A66A-42BF-A560-F956550FF9FE}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Helpers", "Helpers\Helpers.vcxproj", "{B4A776E4-4C87-44B6-AFD6-A4996EE38330}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TileLayout", "TileLayout\TileLayout.csproj", "{720B613C-08A1-44EB-A5C0-7F35A16D7EC6}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowSubclassingCSharp", "WindowSubclassingCSharp\WindowSubclassingCSharp.csproj", "{3A9C3694-8057-43E3-B9B0-1487DBF80CB1}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortcutsManager", "ShortcutsManager\ShortcutsManager.csproj", "{F708858D-F410-437B-997E-1373E44C5DA4}" 17 | EndProject 18 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GlobalShellHook", "GlobalShellHook\GlobalShellHook.vcxproj", "{A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}" 19 | EndProject 20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{354EF524-746F-47B0-B9F8-4A9C0F2DE872}" 21 | ProjectSection(SolutionItems) = preProject 22 | app_version.xml = app_version.xml 23 | EndProjectSection 24 | EndProject 25 | Global 26 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 27 | Debug|x64 = Debug|x64 28 | Debug|x86 = Debug|x86 29 | Profiling|x64 = Profiling|x64 30 | Profiling|x86 = Profiling|x86 31 | Release|x64 = Release|x64 32 | Release|x86 = Release|x86 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Debug|x64.ActiveCfg = Debug|x64 36 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Debug|x64.Build.0 = Debug|x64 37 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Debug|x86.ActiveCfg = Debug|Win32 38 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Debug|x86.Build.0 = Debug|Win32 39 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Profiling|x64.ActiveCfg = Release Profiling|x64 40 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Profiling|x64.Build.0 = Release Profiling|x64 41 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Profiling|x86.ActiveCfg = Release Profiling|Win32 42 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Profiling|x86.Build.0 = Release Profiling|Win32 43 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Release|x64.ActiveCfg = Release|x64 44 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Release|x64.Build.0 = Release|x64 45 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Release|x86.ActiveCfg = Release|Win32 46 | {67670ECC-FD00-4B7C-8748-00A168FA9768}.Release|x86.Build.0 = Release|Win32 47 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Debug|x64.ActiveCfg = Debug|x64 48 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Debug|x64.Build.0 = Debug|x64 49 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Debug|x86.ActiveCfg = Debug|Win32 50 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Debug|x86.Build.0 = Debug|Win32 51 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Profiling|x64.ActiveCfg = Debug|x64 52 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Profiling|x64.Build.0 = Debug|x64 53 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Profiling|x86.ActiveCfg = Debug|Win32 54 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Profiling|x86.Build.0 = Debug|Win32 55 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Release|x64.ActiveCfg = Release|x64 56 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Release|x64.Build.0 = Release|x64 57 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Release|x86.ActiveCfg = Release|Win32 58 | {4B1EDA49-44B3-49BC-9B5D-B3F602FDBDBD}.Release|x86.Build.0 = Release|Win32 59 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Debug|x64.ActiveCfg = Debug|x64 60 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Debug|x64.Build.0 = Debug|x64 61 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Debug|x86.ActiveCfg = Debug|x86 62 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Debug|x86.Build.0 = Debug|x86 63 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Profiling|x64.ActiveCfg = Debug|x64 64 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Profiling|x64.Build.0 = Debug|x64 65 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Profiling|x86.ActiveCfg = Debug|x86 66 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Profiling|x86.Build.0 = Debug|x86 67 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Release|x64.ActiveCfg = Release|x64 68 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Release|x64.Build.0 = Release|x64 69 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Release|x86.ActiveCfg = Release|x86 70 | {90BCA858-A66A-42BF-A560-F956550FF9FE}.Release|x86.Build.0 = Release|x86 71 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Debug|x64.ActiveCfg = Debug|x64 72 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Debug|x64.Build.0 = Debug|x64 73 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Debug|x86.ActiveCfg = Debug|Win32 74 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Debug|x86.Build.0 = Debug|Win32 75 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Profiling|x64.ActiveCfg = Debug|x64 76 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Profiling|x64.Build.0 = Debug|x64 77 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Profiling|x86.ActiveCfg = Debug|Win32 78 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Profiling|x86.Build.0 = Debug|Win32 79 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Release|x64.ActiveCfg = Release|x64 80 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Release|x64.Build.0 = Release|x64 81 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Release|x86.ActiveCfg = Release|Win32 82 | {B4A776E4-4C87-44B6-AFD6-A4996EE38330}.Release|x86.Build.0 = Release|Win32 83 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Debug|x64.ActiveCfg = Debug|x64 84 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Debug|x64.Build.0 = Debug|x64 85 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Debug|x86.ActiveCfg = Debug|x86 86 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Debug|x86.Build.0 = Debug|x86 87 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Profiling|x64.ActiveCfg = Debug|x64 88 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Profiling|x64.Build.0 = Debug|x64 89 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Profiling|x86.ActiveCfg = Debug|x86 90 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Profiling|x86.Build.0 = Debug|x86 91 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Release|x64.ActiveCfg = Release|x64 92 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Release|x64.Build.0 = Release|x64 93 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Release|x86.ActiveCfg = Release|x86 94 | {720B613C-08A1-44EB-A5C0-7F35A16D7EC6}.Release|x86.Build.0 = Release|x86 95 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Debug|x64.ActiveCfg = Debug|x64 96 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Debug|x64.Build.0 = Debug|x64 97 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Debug|x86.ActiveCfg = Debug|x86 98 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Debug|x86.Build.0 = Debug|x86 99 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Profiling|x64.ActiveCfg = Release Profiling|x64 100 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Profiling|x64.Build.0 = Release Profiling|x64 101 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Profiling|x86.ActiveCfg = Release Profiling|x86 102 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Profiling|x86.Build.0 = Release Profiling|x86 103 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Release|x64.ActiveCfg = Release|x64 104 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Release|x64.Build.0 = Release|x64 105 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Release|x86.ActiveCfg = Release|x86 106 | {3A9C3694-8057-43E3-B9B0-1487DBF80CB1}.Release|x86.Build.0 = Release|x86 107 | {F708858D-F410-437B-997E-1373E44C5DA4}.Debug|x64.ActiveCfg = Debug|x64 108 | {F708858D-F410-437B-997E-1373E44C5DA4}.Debug|x64.Build.0 = Debug|x64 109 | {F708858D-F410-437B-997E-1373E44C5DA4}.Debug|x86.ActiveCfg = Debug|x86 110 | {F708858D-F410-437B-997E-1373E44C5DA4}.Debug|x86.Build.0 = Debug|x86 111 | {F708858D-F410-437B-997E-1373E44C5DA4}.Profiling|x64.ActiveCfg = Debug|x64 112 | {F708858D-F410-437B-997E-1373E44C5DA4}.Profiling|x64.Build.0 = Debug|x64 113 | {F708858D-F410-437B-997E-1373E44C5DA4}.Profiling|x86.ActiveCfg = Debug|x86 114 | {F708858D-F410-437B-997E-1373E44C5DA4}.Profiling|x86.Build.0 = Debug|x86 115 | {F708858D-F410-437B-997E-1373E44C5DA4}.Release|x64.ActiveCfg = Release|x64 116 | {F708858D-F410-437B-997E-1373E44C5DA4}.Release|x64.Build.0 = Release|x64 117 | {F708858D-F410-437B-997E-1373E44C5DA4}.Release|x86.ActiveCfg = Release|x86 118 | {F708858D-F410-437B-997E-1373E44C5DA4}.Release|x86.Build.0 = Release|x86 119 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Debug|x64.ActiveCfg = Debug|x64 120 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Debug|x64.Build.0 = Debug|x64 121 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Debug|x86.ActiveCfg = Debug|Win32 122 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Debug|x86.Build.0 = Debug|Win32 123 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Profiling|x64.ActiveCfg = Debug|x64 124 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Profiling|x64.Build.0 = Debug|x64 125 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Profiling|x86.ActiveCfg = Debug|Win32 126 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Profiling|x86.Build.0 = Debug|Win32 127 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Release|x64.ActiveCfg = Release|x64 128 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Release|x64.Build.0 = Release|x64 129 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Release|x86.ActiveCfg = Release|Win32 130 | {A16BB20E-4E10-4C13-9BF4-F945FCE4E87C}.Release|x86.Build.0 = Release|Win32 131 | EndGlobalSection 132 | GlobalSection(SolutionProperties) = preSolution 133 | HideSolutionNode = FALSE 134 | EndGlobalSection 135 | EndGlobal 136 | -------------------------------------------------------------------------------- /TileLayout/TileLayout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | 6 | namespace Windawesome 7 | { 8 | public sealed class TileLayout : ILayout 9 | { 10 | public enum LayoutAxis 11 | { 12 | LeftToRight, 13 | RightToLeft, 14 | TopToBottom, 15 | BottomToTop, 16 | Monocle 17 | } 18 | 19 | private Workspace workspace; 20 | private IEnumerable windows; 21 | private LayoutAxis layoutAxis; 22 | private LayoutAxis masterAreaAxis; 23 | private LayoutAxis stackAreaAxis; 24 | private double masterAreaFactor; 25 | private int masterAreaWindowsCount; 26 | 27 | public TileLayout(LayoutAxis layoutAxis = LayoutAxis.LeftToRight, LayoutAxis masterAreaAxis = LayoutAxis.Monocle, 28 | LayoutAxis stackAreaAxis = LayoutAxis.TopToBottom, double masterAreaFactor = 0.6, int masterAreaWindowsCount = 1) 29 | { 30 | this.layoutAxis = layoutAxis; 31 | this.masterAreaAxis = masterAreaAxis; 32 | this.stackAreaAxis = stackAreaAxis; 33 | if (masterAreaFactor > 1) 34 | { 35 | masterAreaFactor = 1; 36 | } 37 | else if (masterAreaFactor < 0) 38 | { 39 | masterAreaFactor = 0; 40 | } 41 | this.masterAreaFactor = masterAreaFactor; 42 | if (masterAreaWindowsCount < 0) 43 | { 44 | masterAreaWindowsCount = 0; 45 | } 46 | this.masterAreaWindowsCount = masterAreaWindowsCount; 47 | } 48 | 49 | #region API 50 | 51 | public void AddToMasterAreaWindowsCount(int count = 1) 52 | { 53 | masterAreaWindowsCount += count; 54 | if (masterAreaWindowsCount < 0) 55 | { 56 | masterAreaWindowsCount = 0; 57 | } 58 | this.Reposition(); 59 | } 60 | 61 | public void ToggleLayoutAxis() 62 | { 63 | SetLayoutAxis((LayoutAxis) (((int) layoutAxis + 1) % Enum.GetValues(typeof(LayoutAxis)).Length)); 64 | } 65 | 66 | public void ToggleMasterAreaAxis() 67 | { 68 | SetMasterAreaAxis((LayoutAxis) (((int) masterAreaAxis + 1) % Enum.GetValues(typeof(LayoutAxis)).Length)); 69 | } 70 | 71 | public void ToggleStackAreaAxis() 72 | { 73 | SetStackAreaAxis((LayoutAxis) (((int) stackAreaAxis + 1) % Enum.GetValues(typeof(LayoutAxis)).Length)); 74 | } 75 | 76 | public void SetLayoutAxis(LayoutAxis layoutAxis) 77 | { 78 | if (this.layoutAxis != layoutAxis) 79 | { 80 | this.layoutAxis = layoutAxis; 81 | 82 | this.Reposition(); 83 | } 84 | } 85 | 86 | public void SetMasterAreaAxis(LayoutAxis masterAreaAxis) 87 | { 88 | if (this.masterAreaAxis != masterAreaAxis) 89 | { 90 | this.masterAreaAxis = masterAreaAxis; 91 | 92 | this.Reposition(); 93 | } 94 | } 95 | 96 | public void SetStackAreaAxis(LayoutAxis stackAreaAxis) 97 | { 98 | if (this.stackAreaAxis != stackAreaAxis) 99 | { 100 | this.stackAreaAxis = stackAreaAxis; 101 | 102 | this.Reposition(); 103 | } 104 | } 105 | 106 | public void AddToMasterAreaFactor(double masterAreaFactorChange = 0.05) 107 | { 108 | masterAreaFactor += masterAreaFactorChange; 109 | if (masterAreaFactor > 1) 110 | { 111 | masterAreaFactor = 1; 112 | } 113 | else if (masterAreaFactor < 0) 114 | { 115 | masterAreaFactor = 0; 116 | } 117 | 118 | this.Reposition(); 119 | } 120 | 121 | #endregion 122 | 123 | private IntPtr PositionAreaWindows(IntPtr winPosInfo, Rectangle workingArea, bool master) 124 | { 125 | var count = master ? 126 | Math.Min(masterAreaWindowsCount, windows.Count()) : 127 | Math.Max(windows.Count() - masterAreaWindowsCount, 0); 128 | if (count > 0) 129 | { 130 | var otherWindowsCount = master ? 131 | Math.Max(windows.Count() - masterAreaWindowsCount, 0) : 132 | Math.Min(masterAreaWindowsCount, windows.Count()); 133 | var factor = otherWindowsCount == 0 ? 1 : (master ? masterAreaFactor : 1 - masterAreaFactor); 134 | var axis = master ? masterAreaAxis : stackAreaAxis; 135 | 136 | int eachWidth = workingArea.Width, eachHight = workingArea.Height; 137 | int x = workingArea.X, y = workingArea.Y; 138 | 139 | switch (layoutAxis) 140 | { 141 | case LayoutAxis.LeftToRight: 142 | eachWidth = (int) (eachWidth * factor); 143 | x = master ? workingArea.X : workingArea.Right - eachWidth; 144 | break; 145 | case LayoutAxis.RightToLeft: 146 | eachWidth = (int) (eachWidth * factor); 147 | x = master ? workingArea.Right - eachWidth : workingArea.X; 148 | break; 149 | case LayoutAxis.TopToBottom: 150 | eachHight = (int) (eachHight * factor); 151 | y = master ? workingArea.Y : workingArea.Bottom - eachHight; 152 | break; 153 | case LayoutAxis.BottomToTop: 154 | eachHight = (int) (eachHight * factor); 155 | y = master ? workingArea.Bottom - eachHight : workingArea.Y; 156 | break; 157 | } 158 | switch (axis) 159 | { 160 | case LayoutAxis.RightToLeft: 161 | x += eachWidth; 162 | break; 163 | case LayoutAxis.BottomToTop: 164 | y += eachHight; 165 | break; 166 | } 167 | switch (axis) 168 | { 169 | case LayoutAxis.LeftToRight: 170 | case LayoutAxis.RightToLeft: 171 | eachWidth /= count; 172 | break; 173 | case LayoutAxis.TopToBottom: 174 | case LayoutAxis.BottomToTop: 175 | eachHight /= count; 176 | break; 177 | } 178 | switch (axis) 179 | { 180 | case LayoutAxis.RightToLeft: 181 | x -= eachWidth; 182 | break; 183 | case LayoutAxis.BottomToTop: 184 | y -= eachHight; 185 | break; 186 | } 187 | 188 | var masterOrStackWindows = master ? this.windows.Take(masterAreaWindowsCount) : this.windows.Skip(masterAreaWindowsCount); 189 | foreach (var window in masterOrStackWindows.Where(Utilities.WindowIsNotHung)) 190 | { 191 | // TODO: this doesn't work for ICQ 7.5's windows. MoveWindow works in Debug mode, but not in Release 192 | winPosInfo = NativeMethods.DeferWindowPos(winPosInfo, window.hWnd, IntPtr.Zero, 193 | x, y, eachWidth, eachHight, 194 | NativeMethods.SWP.SWP_FRAMECHANGED | NativeMethods.SWP.SWP_NOACTIVATE | NativeMethods.SWP.SWP_NOCOPYBITS | 195 | NativeMethods.SWP.SWP_NOZORDER | NativeMethods.SWP.SWP_NOOWNERZORDER); 196 | 197 | switch (axis) 198 | { 199 | case LayoutAxis.LeftToRight: 200 | x += eachWidth; 201 | break; 202 | case LayoutAxis.RightToLeft: 203 | x -= eachWidth; 204 | break; 205 | case LayoutAxis.TopToBottom: 206 | y += eachHight; 207 | break; 208 | case LayoutAxis.BottomToTop: 209 | y -= eachHight; 210 | break; 211 | } 212 | } 213 | } 214 | 215 | return winPosInfo; 216 | } 217 | 218 | private static string GetAreaSymbol(int count, LayoutAxis axis) 219 | { 220 | switch (axis) 221 | { 222 | case LayoutAxis.LeftToRight: 223 | case LayoutAxis.RightToLeft: 224 | return "|"; 225 | case LayoutAxis.TopToBottom: 226 | case LayoutAxis.BottomToTop: 227 | return "="; 228 | default: // LayoutAxis.Monocle 229 | return count.ToString(); 230 | } 231 | } 232 | 233 | private void Reposition() 234 | { 235 | if (this.windows.Count() > 0) 236 | { 237 | var workingArea = workspace.Monitor.WorkingArea; 238 | var winPosInfo = NativeMethods.BeginDeferWindowPos(this.windows.Count()); 239 | winPosInfo = PositionAreaWindows(winPosInfo, workingArea, true); 240 | winPosInfo = PositionAreaWindows(winPosInfo, workingArea, false); 241 | NativeMethods.EndDeferWindowPos(winPosInfo); 242 | } 243 | 244 | Workspace.DoLayoutUpdated(); 245 | } 246 | 247 | #region ILayout Members 248 | 249 | string ILayout.LayoutSymbol() 250 | { 251 | if (layoutAxis == LayoutAxis.Monocle) 252 | { 253 | return "[" + workspace.GetWindowsCount() + "]"; 254 | } 255 | 256 | var master = "[]"; 257 | var stackCount = workspace.GetWindowsCount() - masterAreaWindowsCount; 258 | 259 | if (masterAreaWindowsCount > 1) 260 | { 261 | master = GetAreaSymbol(masterAreaWindowsCount, masterAreaAxis); 262 | } 263 | var stack = GetAreaSymbol(stackCount, stackAreaAxis); 264 | 265 | switch (layoutAxis) 266 | { 267 | case LayoutAxis.LeftToRight: 268 | case LayoutAxis.TopToBottom: 269 | return master + (master == "[]" ? "" : "]") + stack; 270 | case LayoutAxis.RightToLeft: 271 | case LayoutAxis.BottomToTop: 272 | return stack + (master == "[]" ? "" : "[") + master; 273 | } 274 | 275 | throw new Exception("Unreachable code... reached!"); 276 | } 277 | 278 | public string LayoutName() 279 | { 280 | return "Tile"; 281 | } 282 | 283 | bool ILayout.ShouldSaveAndRestoreSharedWindowsPosition() 284 | { 285 | return false; 286 | } 287 | 288 | void ILayout.Initialize(Workspace workspace) 289 | { 290 | this.workspace = workspace; 291 | } 292 | 293 | void ILayout.Dispose() 294 | { 295 | } 296 | 297 | void ILayout.Reposition() 298 | { 299 | // restore any maximized windows - should not use SW_RESTORE as it activates the window 300 | var hasMaximized = false; 301 | foreach (var window in workspace.GetLayoutManagedWindows(). 302 | Where(w => NativeMethods.IsZoomed(w.hWnd) && Utilities.WindowIsNotHung(w))) 303 | { 304 | hasMaximized = true; 305 | NativeMethods.ShowWindow(window.hWnd, NativeMethods.SW.SW_SHOWNOACTIVATE); 306 | } 307 | if (hasMaximized) 308 | { 309 | System.Threading.Thread.Sleep(NativeMethods.minimizeRestoreDelay); 310 | } 311 | 312 | this.windows = workspace.GetLayoutManagedWindows(); 313 | Reposition(); 314 | } 315 | 316 | void ILayout.WindowMinimized(Window window) 317 | { 318 | (this as ILayout).WindowDestroyed(window); 319 | } 320 | 321 | void ILayout.WindowRestored(Window window) 322 | { 323 | (this as ILayout).WindowCreated(window); 324 | } 325 | 326 | void ILayout.WindowCreated(Window window) 327 | { 328 | if (workspace.IsWorkspaceVisible || window.WorkspacesCount == 1) 329 | { 330 | if (NativeMethods.IsZoomed(window.hWnd) && Utilities.WindowIsNotHung(window)) 331 | { 332 | // restore if maximized - should not use SW_RESTORE as it activates the window 333 | NativeMethods.ShowWindow(window.hWnd, NativeMethods.SW.SW_SHOWNOACTIVATE); 334 | System.Threading.Thread.Sleep(NativeMethods.minimizeRestoreDelay); 335 | } 336 | if (workspace.IsWorkspaceVisible) 337 | { 338 | Reposition(); 339 | } 340 | } 341 | } 342 | 343 | void ILayout.WindowDestroyed(Window window) 344 | { 345 | if (workspace.IsWorkspaceVisible) 346 | { 347 | Reposition(); 348 | } 349 | } 350 | 351 | #endregion 352 | } 353 | } 354 | --------------------------------------------------------------------------------