|
1
|
1 #include "StdAfx.h"
|
|
|
2
|
|
|
3 #ifdef FOOBAR2000_DESKTOP_WINDOWS
|
|
|
4
|
|
|
5 #include "window_placement_helper.h"
|
|
|
6 #include <SDK/config_object.h>
|
|
|
7
|
|
|
8 static bool g_is_enabled()
|
|
|
9 {
|
|
|
10 return standard_config_objects::query_remember_window_positions();
|
|
|
11 }
|
|
|
12
|
|
|
13 static BOOL CALLBACK __MonitorEnumProc(
|
|
|
14 HMONITOR hMonitor, // handle to display monitor
|
|
|
15 HDC hdcMonitor, // handle to monitor DC
|
|
|
16 LPRECT lprcMonitor, // monitor intersection rectangle
|
|
|
17 LPARAM dwData // data
|
|
|
18 ) {
|
|
|
19 RECT * clip = (RECT*)dwData;
|
|
|
20 RECT newclip;
|
|
|
21 if (UnionRect(&newclip,clip,lprcMonitor)) {
|
|
|
22 *clip = newclip;
|
|
|
23 }
|
|
|
24 return TRUE;
|
|
|
25 }
|
|
|
26
|
|
|
27 static bool test_rect(const RECT * rc) {
|
|
|
28 RECT clip = {};
|
|
|
29 if (EnumDisplayMonitors(NULL,NULL,__MonitorEnumProc,(LPARAM)&clip)) {
|
|
|
30 const LONG sanitycheck = 4;
|
|
|
31 const LONG cwidth = clip.right - clip.left;
|
|
|
32 const LONG cheight = clip.bottom - clip.top;
|
|
|
33
|
|
|
34 const LONG width = rc->right - rc->left;
|
|
|
35 const LONG height = rc->bottom - rc->top;
|
|
|
36
|
|
|
37 if (width > cwidth * sanitycheck || height > cheight * sanitycheck) return false;
|
|
|
38 }
|
|
|
39
|
|
|
40 return MonitorFromRect(rc,MONITOR_DEFAULTTONULL) != NULL;
|
|
|
41 }
|
|
|
42
|
|
|
43
|
|
|
44 bool cfg_window_placement::read_from_window(HWND window)
|
|
|
45 {
|
|
|
46 WINDOWPLACEMENT wp = {};
|
|
|
47 if (g_is_enabled()) {
|
|
|
48 wp.length = sizeof(wp);
|
|
|
49 if (!GetWindowPlacement(window,&wp)) {
|
|
|
50 PFC_ASSERT(!"GetWindowPlacement fail!");
|
|
|
51 memset(&wp,0,sizeof(wp));
|
|
|
52 } else {
|
|
|
53 // bad, breaks with taskbar on top
|
|
|
54 /*if (wp.showCmd == SW_SHOWNORMAL) {
|
|
|
55 GetWindowRect(window, &wp.rcNormalPosition);
|
|
|
56 }*/
|
|
|
57
|
|
|
58 if ( !IsWindowVisible( window ) ) wp.showCmd = SW_HIDE;
|
|
|
59 }
|
|
|
60 /*else
|
|
|
61 {
|
|
|
62 if (!IsWindowVisible(window)) wp.showCmd = SW_HIDE;
|
|
|
63 }*/
|
|
|
64 }
|
|
|
65
|
|
|
66 try { set(wp); } catch(...) {} // this tends to be called often / we really couldn't care less about this failing
|
|
|
67
|
|
|
68 return wp.length == sizeof(wp);
|
|
|
69 }
|
|
|
70
|
|
|
71 bool applyWindowPlacement(HWND window, WINDOWPLACEMENT const& data, bool allowHidden) {
|
|
|
72 bool ret = false;
|
|
|
73 if (data.length == sizeof(data) && test_rect(&data.rcNormalPosition))
|
|
|
74 {
|
|
|
75 if (allowHidden || data.showCmd != SW_HIDE) {
|
|
|
76 if (data.showCmd == SW_HIDE && (data.flags & WPF_RESTORETOMAXIMIZED)) {
|
|
|
77 // Special case of hidden-from-maximized
|
|
|
78 auto fix = data;
|
|
|
79 fix.showCmd = SW_SHOWMINIMIZED;
|
|
|
80 if (SetWindowPlacement(window, &fix)) {
|
|
|
81 ShowWindow(window, SW_HIDE);
|
|
|
82 ret = true;
|
|
|
83 }
|
|
|
84 } else {
|
|
|
85 if (SetWindowPlacement(window, &data)) {
|
|
|
86 ret = true;
|
|
|
87 }
|
|
|
88 }
|
|
|
89 }
|
|
|
90 }
|
|
|
91 return ret;
|
|
|
92 }
|
|
|
93
|
|
|
94 bool cfg_window_placement::apply_to_window(HWND window, bool allowHidden) {
|
|
|
95 bool ret = false;
|
|
|
96 if (g_is_enabled())
|
|
|
97 {
|
|
|
98 auto data = get();
|
|
|
99 ret = applyWindowPlacement(window, data, allowHidden);
|
|
|
100 }
|
|
|
101
|
|
|
102 return ret;
|
|
|
103 }
|
|
|
104
|
|
|
105 void cfg_window_placement::on_window_creation_silent(HWND window) {
|
|
|
106 }
|
|
|
107 bool cfg_window_placement::on_window_creation(HWND window, bool allowHidden) {
|
|
|
108
|
|
|
109 return apply_to_window(window, allowHidden);
|
|
|
110 }
|
|
|
111
|
|
|
112
|
|
|
113 void cfg_window_placement::on_window_destruction(HWND window)
|
|
|
114 {
|
|
|
115 read_from_window(window);
|
|
|
116 }
|
|
|
117
|
|
|
118 static BOOL SetWindowSize(HWND p_wnd,unsigned p_x,unsigned p_y)
|
|
|
119 {
|
|
|
120 if (p_x != ~0 && p_y != ~0)
|
|
|
121 return SetWindowPos(p_wnd,0,0,0,p_x,p_y,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
|
|
|
122 else
|
|
|
123 return FALSE;
|
|
|
124 }
|
|
|
125
|
|
|
126 bool cfg_window_size::apply_to_window(HWND p_wnd) {
|
|
|
127 bool ret = false;
|
|
|
128
|
|
|
129 if (g_is_enabled())
|
|
|
130 {
|
|
|
131 auto v = get();
|
|
|
132 if (v.cx > 0 && v.cy > 0) {
|
|
|
133 if (SetWindowSize(p_wnd, v.cx, v.cy)) ret = true;
|
|
|
134 }
|
|
|
135
|
|
|
136 }
|
|
|
137 return ret;
|
|
|
138 }
|
|
|
139 bool cfg_window_size::on_window_creation(HWND p_wnd)
|
|
|
140 {
|
|
|
141 return apply_to_window(p_wnd);
|
|
|
142 }
|
|
|
143
|
|
|
144 void cfg_window_size::on_window_destruction(HWND p_wnd)
|
|
|
145 {
|
|
|
146 read_from_window(p_wnd);
|
|
|
147 }
|
|
|
148
|
|
|
149 bool cfg_window_size::read_from_window(HWND p_wnd)
|
|
|
150 {
|
|
|
151 SIZE val = {};
|
|
|
152 if (g_is_enabled())
|
|
|
153 {
|
|
|
154 RECT r;
|
|
|
155 if (GetWindowRect(p_wnd,&r))
|
|
|
156 {
|
|
|
157 val.cx = r.right - r.left;
|
|
|
158 val.cy = r.bottom - r.top;
|
|
|
159 }
|
|
|
160 }
|
|
|
161
|
|
|
162 set(val);
|
|
|
163 return val.cx > 0 && val.cy > 0;
|
|
|
164 }
|
|
|
165
|
|
|
166 #endif // FOOBAR2000_DESKTOP_WINDOWS
|