Audacity 3.2.0
Classes | Namespaces | Enumerations | Functions | Variables
ProjectWindow.cpp File Reference
#include "ProjectWindow.h"
#include "ActiveProject.h"
#include "AllThemeResources.h"
#include "AudioIO.h"
#include "Menus.h"
#include "Project.h"
#include "ProjectAudioIO.h"
#include "ProjectWindows.h"
#include "ProjectStatus.h"
#include "RefreshCode.h"
#include "TrackPanelMouseEvent.h"
#include "TrackPanelAx.h"
#include "UndoManager.h"
#include "ViewInfo.h"
#include "WaveClip.h"
#include "WaveTrack.h"
#include "commands/CommandContext.h"
#include "prefs/ThemePrefs.h"
#include "prefs/TracksPrefs.h"
#include "toolbars/ToolManager.h"
#include "tracks/ui/Scrubbing.h"
#include "tracks/ui/TrackView.h"
#include "widgets/wxPanelWrapper.h"
#include "widgets/WindowAccessible.h"
#include <wx/app.h>
#include <wx/display.h>
#include <wx/scrolbar.h>
#include <wx/sizer.h>
#include <wx/splitter.h>
Include dependency graph for ProjectWindow.cpp:

Go to the source code of this file.

Classes

class  anonymous_namespace{ProjectWindow.cpp}::ScrollBar
 

Namespaces

namespace  anonymous_namespace{ProjectWindow.cpp}
 

Enumerations

enum  { FirstID = 1000 , HSBarID , VSBarID , NextID }
 

Functions

int ScreenContaining (wxRect &r)
 
bool CornersOnScreen (wxRect &r)
 
bool IsWindowAccessible (wxRect *requestedRect)
 
void GetDefaultWindowRect (wxRect *defRect)
 
void GetNextWindowPlacement (wxRect *nextRect, bool *pMaximized, bool *pIconized)
 

Variables

constexpr int anonymous_namespace{ProjectWindow.cpp}::DEFAULT_WINDOW_WIDTH = 1200
 
constexpr int anonymous_namespace{ProjectWindow.cpp}::DEFAULT_WINDOW_HEIGHT = 674
 
BoolSetting ProjectWindowMaximized { L"/Window/Maximized", false }
 
BoolSetting ProjectWindowIconized { L"/Window/Iconized", false }
 
IntSetting ProjectWindowX { L"/Window/X", 0 }
 
IntSetting ProjectWindowY { L"/Window/Y", 0 }
 
IntSetting ProjectWindowWidth { L"/Window/Width", DEFAULT_WINDOW_WIDTH }
 
IntSetting ProjectWindowHeight { L"/Window/Height", DEFAULT_WINDOW_HEIGHT }
 
IntSetting ProjectWindowNormalX { L"/Window/Normal_X", 0 }
 
IntSetting ProjectWindowNormalY { L"/Window/Normal_Y", 0 }
 
IntSetting ProjectWindowNormalWidth { L"/Window/Normal_Width", DEFAULT_WINDOW_WIDTH }
 
IntSetting ProjectWindowNormalHeight { L"/Window/Normal_Height", DEFAULT_WINDOW_HEIGHT }
 
static CommonTrackPanelCell::MouseWheelHook::Scope anonymous_namespace{ProjectWindow.cpp}::scope
 
AttachedWindows::RegisteredFactory anonymous_namespace{ProjectWindow.cpp}::sProjectWindowKey
 
const int sbarHjump = 30
 
static ToolManager::TopPanelHook::Scope scope
 

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
FirstID 
HSBarID 
VSBarID 
NextID 

Definition at line 578 of file ProjectWindow.cpp.

578 {
579 FirstID = 1000,
580
581 // Window controls
582
583 HSBarID,
584 VSBarID,
585
586 NextID,
587};
@ VSBarID
@ HSBarID
@ NextID
@ FirstID

Function Documentation

◆ CornersOnScreen()

bool CornersOnScreen ( wxRect &  r)

Definition at line 77 of file ProjectWindow.cpp.

77 {
78 if( wxDisplay::GetFromPoint( r.GetTopLeft() ) == wxNOT_FOUND) return false;
79 if( wxDisplay::GetFromPoint( r.GetBottomRight() ) == wxNOT_FOUND) return false;
80 return true;
81}

Referenced by GetNextWindowPlacement().

Here is the caller graph for this function:

◆ GetDefaultWindowRect()

void GetDefaultWindowRect ( wxRect *  defRect)

Definition at line 110 of file ProjectWindow.cpp.

111{
112 *defRect = wxGetClientDisplayRect();
113
114 int width = DEFAULT_WINDOW_WIDTH;
115 int height = DEFAULT_WINDOW_HEIGHT;
116
117 //These conditional values assist in improving placement and size
118 //of NEW windows on different platforms.
119#ifdef __WXGTK__
120 height += 20;
121#endif
122
123#ifdef __WXMSW__
124 height += 40;
125#endif
126
127#ifdef __WXMAC__
128 height += 55;
129#endif
130
131 // Use screen size where it is smaller than the values we would like.
132 // Otherwise use the values we would like, and centred.
133 if (width < defRect->width)
134 {
135 defRect->x = (defRect->width - width)/2;
136 defRect->width = width;
137 }
138
139 if (height < defRect->height)
140 {
141 defRect->y = (defRect->height - height)/2;
142 // Bug 1119 workaround
143 // Small adjustment for very small Mac screens.
144 // If there is only a tiny space at the top
145 // then instead of vertical centre, align to bottom.
146 const int pixelsFormenu = 60;
147 if( defRect->y < pixelsFormenu )
148 defRect->y *=2;
149 defRect->height = height;
150 }
151}

References anonymous_namespace{ProjectWindow.cpp}::DEFAULT_WINDOW_HEIGHT, and anonymous_namespace{ProjectWindow.cpp}::DEFAULT_WINDOW_WIDTH.

Referenced by GetNextWindowPlacement(), ProjectWindow::Reset(), and ProjectManager::SaveWindowSize().

Here is the caller graph for this function:

◆ GetNextWindowPlacement()

void GetNextWindowPlacement ( wxRect *  nextRect,
bool *  pMaximized,
bool *  pIconized 
)

Definition at line 157 of file ProjectWindow.cpp.

158{
159 int inc = 25;
160
161 wxRect defaultRect;
162 GetDefaultWindowRect(&defaultRect);
163
164 *pMaximized = ProjectWindowMaximized.Read();
165 *pIconized = ProjectWindowIconized.Read();
166
167 wxRect windowRect;
168 windowRect.x = ProjectWindowX.ReadWithDefault(defaultRect.x);
169 windowRect.y = ProjectWindowY.ReadWithDefault(defaultRect.y);
170 windowRect.width = ProjectWindowWidth.ReadWithDefault(defaultRect.width);
171 windowRect.height = ProjectWindowHeight.ReadWithDefault(defaultRect.height);
172
173 wxRect normalRect;
174 normalRect.x = ProjectWindowNormalX.ReadWithDefault(defaultRect.x);
175 normalRect.y = ProjectWindowNormalY.ReadWithDefault(defaultRect.y);
176 normalRect.width = ProjectWindowNormalWidth.ReadWithDefault(defaultRect.width);
177 normalRect.height = ProjectWindowNormalHeight.ReadWithDefault(defaultRect.height);
178
179 // Workaround 2.1.1 and earlier bug on OSX...affects only normalRect, but let's just
180 // validate for all rects and plats
181 if (normalRect.width == 0 || normalRect.height == 0) {
182 normalRect = defaultRect;
183 }
184 if (windowRect.width == 0 || windowRect.height == 0) {
185 windowRect = defaultRect;
186 }
187
188
189 wxRect screenRect( wxGetClientDisplayRect());
190#if defined(__WXMAC__)
191
192 // On OSX, the top of the window should never be less than the menu height,
193 // so something is amiss if it is
194 if (normalRect.y < screenRect.y) {
195 normalRect = defaultRect;
196 }
197 if (windowRect.y < screenRect.y) {
198 windowRect = defaultRect;
199 }
200#endif
201
202 // IF projects empty, THEN it's the first window.
203 // It lands where the config says it should, and can straddle screen.
204 if (AllProjects{}.empty()) {
205 if (*pMaximized || *pIconized) {
206 *nextRect = normalRect;
207 }
208 else {
209 *nextRect = windowRect;
210 }
211 // Resize, for example if one monitor that was on is now off.
212 if (!CornersOnScreen( wxRect(*nextRect).Deflate( 32, 32 ))) {
213 *nextRect = defaultRect;
214 }
215 if (!IsWindowAccessible(nextRect)) {
216 *nextRect = defaultRect;
217 }
218 // Do not trim the first project window down.
219 // All corners are on screen (or almost so), and
220 // the rect may straddle screens.
221 return;
222 }
223
224
225 // ELSE a subsequent NEW window. It will NOT straddle screens.
226
227 // We don't mind being 32 pixels off the screen in any direction.
228 // Make sure initial sizes (pretty much) fit within the display bounds
229 // We used to trim the sizes which could result in ridiculously small windows.
230 // contributing to bug 1243.
231 // Now instead if the window significantly doesn't fit the screen, we use the default
232 // window instead, which we know does.
233 if (ScreenContaining( wxRect(normalRect).Deflate( 32, 32 ))<0) {
234 normalRect = defaultRect;
235 }
236 if (ScreenContaining( wxRect(windowRect).Deflate( 32, 32 ) )<0) {
237 windowRect = defaultRect;
238 }
239
240 bool validWindowSize = false;
241 ProjectWindow * validProject = NULL;
242 for ( auto iter = AllProjects{}.rbegin(), end = AllProjects{}.rend();
243 iter != end; ++iter
244 ) {
245 auto pProject = *iter;
246 if (!GetProjectFrame( *pProject ).IsIconized()) {
247 validWindowSize = true;
248 validProject = &ProjectWindow::Get( *pProject );
249 break;
250 }
251 }
252 if (validWindowSize) {
253 *nextRect = validProject->GetRect();
254 *pMaximized = validProject->IsMaximized();
255 *pIconized = validProject->IsIconized();
256 // Do not straddle screens.
257 if (ScreenContaining( wxRect(*nextRect).Deflate( 32, 32 ) )<0) {
258 *nextRect = defaultRect;
259 }
260 }
261 else {
262 *nextRect = normalRect;
263 }
264
265 //Placement depends on the increments
266 nextRect->x += inc;
267 nextRect->y += inc;
268
269 // defaultrect is a rectangle on the first screen. It's the right fallback to
270 // use most of the time if things are not working out right with sizing.
271 // windowRect is a saved rectangle size.
272 // normalRect seems to be a substitute for windowRect when iconized or maximised.
273
274 // Windows can say that we are off screen when actually we are not.
275 // On Windows 10 I am seeing miscalculation by about 6 pixels.
276 // To fix this we allow some sloppiness on the edge being counted as off screen.
277 // This matters most when restoring very carefully sized windows that are maximised
278 // in one dimension (height or width) but not both.
279 const int edgeSlop = 10;
280
281 // Next four lines are getting the rectangle for the screen that contains the
282 // top left corner of nextRect (and defaulting to rect of screen 0 otherwise).
283 wxPoint p = nextRect->GetLeftTop();
284 int scr = std::max( 0, wxDisplay::GetFromPoint( p ));
285 wxDisplay d( scr );
286 screenRect = d.GetClientArea();
287
288 // Now we (possibly) start trimming our rectangle down.
289 // Have we hit the right side of the screen?
290 wxPoint bottomRight = nextRect->GetBottomRight();
291 if (bottomRight.x > (screenRect.GetRight()+edgeSlop)) {
292 int newWidth = screenRect.GetWidth() - nextRect->GetLeft();
293 if (newWidth < defaultRect.GetWidth()) {
294 nextRect->x = windowRect.x;
295 nextRect->y = windowRect.y;
296 nextRect->width = windowRect.width;
297 }
298 else {
299 nextRect->width = newWidth;
300 }
301 }
302
303 // Have we hit the bottom of the screen?
304 bottomRight = nextRect->GetBottomRight();
305 if (bottomRight.y > (screenRect.GetBottom()+edgeSlop)) {
306 nextRect->y -= inc;
307 bottomRight = nextRect->GetBottomRight();
308 if (bottomRight.y > (screenRect.GetBottom()+edgeSlop)) {
309 nextRect->SetBottom(screenRect.GetBottom());
310 }
311 }
312
313 // After all that we could have a window that does not have a visible
314 // top bar. [It is unlikely, but something might have gone wrong]
315 // If so, use the safe fallback size.
316 if (!IsWindowAccessible(nextRect)) {
317 *nextRect = defaultRect;
318 }
319}
IntSetting ProjectWindowY
bool CornersOnScreen(wxRect &r)
IntSetting ProjectWindowX
void GetDefaultWindowRect(wxRect *defRect)
IntSetting ProjectWindowWidth
BoolSetting ProjectWindowIconized
bool IsWindowAccessible(wxRect *requestedRect)
BoolSetting ProjectWindowMaximized
IntSetting ProjectWindowNormalHeight
IntSetting ProjectWindowHeight
IntSetting ProjectWindowNormalX
int ScreenContaining(wxRect &r)
IntSetting ProjectWindowNormalWidth
IntSetting ProjectWindowNormalY
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
const_reverse_iterator rend() const
Definition: Project.cpp:37
const_reverse_iterator rbegin() const
Definition: Project.cpp:32
bool empty() const
Definition: Project.h:46
A top-level window associated with a project, and handling scrollbars and zooming.
Definition: ProjectWindow.h:35
static ProjectWindow & Get(AudacityProject &project)
bool IsIconized() const override
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:191
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:185
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for, if Traits<Type>::iterated_type is defined.
Definition: PackedArray.h:126

References CornersOnScreen(), AllProjects::empty(), PackedArray::end(), ProjectWindow::Get(), GetDefaultWindowRect(), GetProjectFrame(), ProjectWindow::IsIconized(), IsWindowAccessible(), ProjectWindowHeight, ProjectWindowIconized, ProjectWindowMaximized, ProjectWindowNormalHeight, ProjectWindowNormalWidth, ProjectWindowNormalX, ProjectWindowNormalY, ProjectWindowWidth, ProjectWindowX, ProjectWindowY, AllProjects::rbegin(), Setting< T >::Read(), Setting< T >::ReadWithDefault(), AllProjects::rend(), and ScreenContaining().

Referenced by AudacityApp::InitPart2(), and ProjectManager::New().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsWindowAccessible()

bool IsWindowAccessible ( wxRect *  requestedRect)

Definition at line 84 of file ProjectWindow.cpp.

85{
86 wxDisplay display;
87 wxRect targetTitleRect(requestedRect->GetLeftTop(), requestedRect->GetBottomRight());
88 // Hackery to approximate a window top bar size from a window size.
89 // and exclude the open/close and borders.
90 targetTitleRect.x += 15;
91 targetTitleRect.width -= 100;
92 if (targetTitleRect.width < 165) targetTitleRect.width = 165;
93 targetTitleRect.height = 15;
94 int targetBottom = targetTitleRect.GetBottom();
95 int targetRight = targetTitleRect.GetRight();
96 // This looks like overkill to check each and every pixel in the ranges.
97 // and decide that if any is visible on screen we are OK.
98 for (int i = targetTitleRect.GetLeft(); i < targetRight; i++) {
99 for (int j = targetTitleRect.GetTop(); j < targetBottom; j++) {
100 int monitor = display.GetFromPoint(wxPoint(i, j));
101 if (monitor != wxNOT_FOUND) {
102 return TRUE;
103 }
104 }
105 }
106 return FALSE;
107}
EventMonitor monitor

References monitor.

Referenced by GetNextWindowPlacement().

Here is the caller graph for this function:

◆ ScreenContaining()

int ScreenContaining ( wxRect &  r)

Definition at line 62 of file ProjectWindow.cpp.

62 {
63 unsigned int n = wxDisplay::GetCount();
64 for(unsigned int i = 0;i<n;i++){
65 wxDisplay d(i);
66 wxRect scr = d.GetClientArea();
67 if( scr.Contains( r ) )
68 return (int)i;
69 }
70 return -1;
71}

Referenced by GetNextWindowPlacement().

Here is the caller graph for this function:

Variable Documentation

◆ ProjectWindowHeight

IntSetting ProjectWindowHeight { L"/Window/Height", DEFAULT_WINDOW_HEIGHT }

◆ ProjectWindowIconized

BoolSetting ProjectWindowIconized { L"/Window/Iconized", false }

◆ ProjectWindowMaximized

BoolSetting ProjectWindowMaximized { L"/Window/Maximized", false }

◆ ProjectWindowNormalHeight

IntSetting ProjectWindowNormalHeight { L"/Window/Normal_Height", DEFAULT_WINDOW_HEIGHT }

◆ ProjectWindowNormalWidth

IntSetting ProjectWindowNormalWidth { L"/Window/Normal_Width", DEFAULT_WINDOW_WIDTH }

◆ ProjectWindowNormalX

IntSetting ProjectWindowNormalX { L"/Window/Normal_X", 0 }

◆ ProjectWindowNormalY

IntSetting ProjectWindowNormalY { L"/Window/Normal_Y", 0 }

◆ ProjectWindowWidth

IntSetting ProjectWindowWidth { L"/Window/Width", DEFAULT_WINDOW_WIDTH }

◆ ProjectWindowX

IntSetting ProjectWindowX { L"/Window/X", 0 }

◆ ProjectWindowY

IntSetting ProjectWindowY { L"/Window/Y", 0 }

◆ sbarHjump

const int sbarHjump = 30

◆ scope

ToolManager::TopPanelHook::Scope scope
static
Initial value:
{
[]( wxWindow &window ){
auto pProjectWindow = dynamic_cast< ProjectWindow* >( &window );
return pProjectWindow ? pProjectWindow->GetTopPanel() : nullptr;
} }
wxPanel * GetTopPanel() noexcept
Top panel contains project-related controls and tools.

Definition at line 1904 of file ProjectWindow.cpp.