2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef DGL_WINDOW_HPP_INCLUDED
18 #define DGL_WINDOW_HPP_INCLUDED
20 #include "Geometry.hpp"
22 #ifndef DGL_FILE_BROWSER_DISABLED
23 # include "FileBrowserDialog.hpp"
28 #ifdef DISTRHO_NAMESPACE
29 START_NAMESPACE_DISTRHO
39 // -----------------------------------------------------------------------
44 This is the where all OS-related events initially happen, before being propagated to any widgets.
46 A Window MUST have an Application instance tied to it.
47 It is not possible to swap Application instances from within the lifetime of a Window.
48 But it is possible to completely change the Widgets that a Window contains during its lifetime.
50 Typically the event handling functions as following:
51 Application -> Window -> Top-Level-Widget -> SubWidgets
53 Please note that, unlike many other graphical toolkits out there,
54 DGL makes a clear distinction between a Window and a Widget.
55 You cannot directly draw in a Window, you need to create a Widget for that.
57 Also, a Window MUST have a single top-level Widget.
58 The Window will take care of global screen positioning and resizing, everything else is sent for widgets to handle.
62 class DISTRHO_API Window
68 Window graphics context as a scoped struct.
69 This class gives graphics context drawing time to a window's widgets.
70 Typically used for allowing OpenGL drawing operations during a window + widget constructor.
72 Unless you are subclassing the Window or StandaloneWindow classes, you do not need to care.
73 In such cases you will need to use this struct as a way to get a valid OpenGL context.
74 For example in a standalone application:
80 ScopedPointer<MyCustomTopLevelWidget> widget;
82 const Window::ScopedGraphicsContext sgc(win);
83 widget = new MyCustomTopLevelWidget(win);
90 This struct is necessary because we cannot automatically make the window leave the OpenGL context in custom code.
91 And we must always cleanly enter and leave the OpenGL context.
92 So in order to avoid messing up the global host context, this class is used around widget creation.
94 struct ScopedGraphicsContext
96 /** Constructor that will make the @a window graphics context the current one */
97 explicit ScopedGraphicsContext(Window
& window
);
99 /** Overloaded constructor, gives back context to its transient parent when done */
100 explicit ScopedGraphicsContext(Window
& window
, Window
& transientParentWindow
);
102 /** Desstructor for clearing current context, if not done yet */
103 ~ScopedGraphicsContext();
105 /** Early context clearing, useful for standalone windows not created by you. */
108 DISTRHO_DECLARE_NON_COPYABLE(ScopedGraphicsContext
)
109 DISTRHO_PREVENT_HEAP_ALLOCATION
113 Window::PrivateData
* ppData
;
118 Constructor for a regular, standalone window.
120 explicit Window(Application
& app
);
123 Constructor for a modal window, by having another window as its transient parent.
124 The Application instance must be the same between the 2 windows.
126 explicit Window(Application
& app
, Window
& transientParentWindow
);
129 Constructor for an embed Window without known size,
130 typically used in modules or plugins that run inside another host.
132 explicit Window(Application
& app
,
133 uintptr_t parentWindowHandle
,
138 Constructor for an embed Window with known size,
139 typically used in modules or plugins that run inside another host.
141 explicit Window(Application
& app
,
142 uintptr_t parentWindowHandle
,
154 Whether this Window is embed into another (usually not DGL-controlled) Window.
156 bool isEmbed() const noexcept
;
159 Check if this window is visible / mapped.
160 Invisible windows do not receive events except resize.
161 @see setVisible(bool)
163 bool isVisible() const noexcept
;
166 Set window visible (or not) according to @a visible.
167 Only valid for standalones, embed windows are always visible.
168 @see isVisible(), hide(), show()
170 void setVisible(bool visible
);
174 This is the same as calling setVisible(true).
175 @see isVisible(), setVisible(bool)
181 This is the same as calling setVisible(false).
182 @see isVisible(), setVisible(bool)
187 Hide window and notify application of a window close event.
188 The application event-loop will stop when all windows have been closed.
189 For standalone windows only, has no effect if window is embed.
192 @note It is possible to hide the window while not stopping the event-loop.
193 A closed window is always hidden, but the reverse is not always true.
198 Check if this window is resizable (by the user or window manager).
201 bool isResizable() const noexcept
;
204 Set window as resizable (by the user or window manager).
205 It is always possible to resize a window programmatically, which is not the same as the user being allowed to it.
206 @note This function does nothing for plugins, where the resizable state is set via macro.
207 @see DISTRHO_UI_USER_RESIZABLE
209 void setResizable(bool resizable
);
212 Get X offset, typically 0.
214 int getOffsetX() const noexcept
;
217 Get Y offset, typically 0.
219 int getOffsetY() const noexcept
;
224 Point
<int> getOffset() const noexcept
;
229 void setOffsetX(int x
);
234 void setOffsetY(int y
);
237 Set offset using @a x and @a y values.
239 void setOffset(int x
, int y
);
244 void setOffset(const Point
<int>& offset
);
249 uint
getWidth() const noexcept
;
254 uint
getHeight() const noexcept
;
259 Size
<uint
> getSize() const noexcept
;
264 void setWidth(uint width
);
269 void setHeight(uint height
);
272 Set size using @a width and @a height values.
274 void setSize(uint width
, uint height
);
279 void setSize(const Size
<uint
>& size
);
282 Get the title of the window previously set with setTitle().
284 const char* getTitle() const noexcept
;
287 Set the title of the window, typically displayed in the title bar or in window switchers.
289 This only makes sense for non-embedded windows.
291 void setTitle(const char* title
);
294 Check if key repeat events are ignored.
296 bool isIgnoringKeyRepeat() const noexcept
;
299 Set to ignore (or not) key repeat events according to @a ignore.
301 void setIgnoringKeyRepeat(bool ignore
) noexcept
;
304 Get the clipboard contents.
306 This gets the system clipboard contents,
307 which may have been set with setClipboard() or copied from another application.
309 Returns the clipboard contents, or null.
311 @note By default only "text/plain" mimetype is supported and returned.
312 Override onClipboardDataOffer for supporting other types.
314 const void* getClipboard(size_t& dataSize
);
317 Set the clipboard contents.
319 This sets the system clipboard contents,
320 which can be retrieved with getClipboard() or pasted into other applications.
322 If using a string, the use of a null terminator is required (and must be part of dataSize).@n
323 The MIME type of the data "text/plain" is assumed if null is used.
325 bool setClipboard(const char* mimeType
, const void* data
, size_t dataSize
);
328 Set the mouse cursor.
330 This changes the system cursor that is displayed when the pointer is inside the window.
331 May fail if setting the cursor is not supported on this system,
332 for example if compiled on X11 without Xcursor support.
334 bool setCursor(MouseCursor cursor
);
337 Add a callback function to be triggered on every idle cycle or on a specific timer frequency.
338 You can add more than one, and remove them at anytime with removeIdleCallback().
339 This can be used to perform some action at a regular interval with relatively low frequency.
341 If providing a timer frequency, there are a few things to note:
342 1. There is a platform-specific limit to the number of supported timers, and overhead associated with each,
343 so you should create only a few timers and perform several tasks in one if necessary.
344 2. This timer frequency is not guaranteed to have a resolution better than 10ms
345 (the maximum timer resolution on Windows) and may be rounded up if it is too short.
346 On X11 and MacOS, a resolution of about 1ms can usually be relied on.
348 bool addIdleCallback(IdleCallback
* callback
, uint timerFrequencyInMs
= 0);
351 Remove an idle callback previously added via addIdleCallback().
353 bool removeIdleCallback(IdleCallback
* callback
);
356 Get the application associated with this window.
358 Application
& getApp() const noexcept
;
361 Get the graphics context associated with this window.
362 GraphicsContext is an empty struct and needs to be casted into a different type in order to be usable,
363 for example GraphicsContext.
364 @see CairoSubWidget, CairoTopLevelWidget
366 const GraphicsContext
& getGraphicsContext() const noexcept
;
369 Get the "native" window handle.
370 Returned value depends on the platform:
371 - HaikuOS: This is a pointer to a `BView`.
372 - MacOS: This is a pointer to an `NSView*`.
373 - Windows: This is a `HWND`.
374 - Everything else: This is an [X11] `Window`.
376 uintptr_t getNativeWindowHandle() const noexcept
;
379 Get the scale factor requested for this window.
380 This is purely informational, and up to developers to choose what to do with it.
382 If you do not want to deal with this yourself,
383 consider using setGeometryConstraints() where you can specify to automatically scale the window contents.
384 @see setGeometryConstraints
386 double getScaleFactor() const noexcept
;
389 Grab the keyboard input focus.
393 #ifndef DGL_FILE_BROWSER_DISABLED
395 Open a file browser dialog with this window as transient parent.
396 A few options can be specified to setup the dialog.
398 If a path is selected, onFileSelected() will be called with the user chosen path.
399 If the user cancels or does not pick a file, onFileSelected() will be called with nullptr as filename.
401 This function does not block the event loop.
403 bool openFileBrowser(const DGL_NAMESPACE::FileBrowserOptions
& options
= FileBrowserOptions());
407 Request repaint of this window, for the entire area.
409 void repaint() noexcept
;
412 Request partial repaint of this window, with bounds according to @a rect.
414 void repaint(const Rectangle
<uint
>& rect
) noexcept
;
417 Render this window's content into a picture file, specified by @a filename.
418 Window must be visible and on screen.
419 Written picture format is PPM.
421 void renderToPicture(const char* filename
);
424 Run this window as a modal, blocking input events from the parent.
425 Only valid for windows that have been created with another window as parent (as passed in the constructor).
426 Can optionally block-wait, but such option is only available if the application is running as standalone.
428 void runAsModal(bool blockWait
= false);
431 Get the geometry constraints set for the Window.
432 @see setGeometryConstraints
434 Size
<uint
> getGeometryConstraints(bool& keepAspectRatio
);
437 Set geometry constraints for the Window when resized by the user, and optionally scale contents automatically.
439 void setGeometryConstraints(uint minimumWidth
,
441 bool keepAspectRatio
= false,
442 bool automaticallyScale
= false,
443 bool resizeNowIfAutoScaling
= true);
446 Set the transient parent of the window.
448 Set this for transient children like dialogs, to have them properly associated with their parent window.
449 This should be not be called for embed windows, or after making the window visible.
451 void setTransientParent(uintptr_t transientParentWindowHandle
);
453 /** DEPRECATED Use isIgnoringKeyRepeat(). */
454 DISTRHO_DEPRECATED_BY("isIgnoringKeyRepeat()")
455 inline bool getIgnoringKeyRepeat() const noexcept
{ return isIgnoringKeyRepeat(); }
457 /** DEPRECATED Use getScaleFactor(). */
458 DISTRHO_DEPRECATED_BY("getScaleFactor()")
459 inline double getScaling() const noexcept
{ return getScaleFactor(); }
461 /** DEPRECATED Use runAsModal(bool). */
462 DISTRHO_DEPRECATED_BY("runAsModal(bool)")
463 inline void exec(bool blockWait
= false) { runAsModal(blockWait
); }
467 Get the types available for the data in a clipboard.
468 Must only be called within the context of onClipboardDataOffer.
470 std::vector
<ClipboardDataOffer
> getClipboardDataOfferTypes();
473 A function called when clipboard has data present, possibly with several datatypes.
474 While handling this event, the data types can be investigated with getClipboardDataOfferTypes() to decide whether to accept the offer.
476 Reimplement and return a non-zero id to accept the clipboard data offer for a particular type.
477 Applications must ignore any type they do not recognize.
479 The default implementation accepts the "text/plain" mimetype.
481 virtual uint32_t onClipboardDataOffer();
484 A function called when the window is attempted to be closed.
485 Returning true closes the window, which is the default behaviour.
486 Override this method and return false to prevent the window from being closed by the user.
488 This method is not used for embed windows, and not even made available in DISTRHO_NAMESPACE::UI.
489 For embed windows, closing is handled by the host/parent process and we have no control over it.
490 As such, a close action on embed windows will always succeed and cannot be cancelled.
492 NOTE: This currently does not work under macOS.
494 virtual bool onClose();
497 A function called when the window gains or loses the keyboard focus.
498 The default implementation does nothing.
500 virtual void onFocus(bool focus
, CrossingMode mode
);
503 A function called when the window is resized.
504 If there is a top-level widget associated with this window, its size will be set right after this function.
505 The default implementation sets up drawing context where necessary.
507 virtual void onReshape(uint width
, uint height
);
510 A function called when scale factor requested for this window changes.
511 The default implementation does nothing.
512 WARNING function needs a proper name
514 virtual void onScaleFactorChanged(double scaleFactor
);
516 #ifndef DGL_FILE_BROWSER_DISABLED
518 A function called when a path is selected by the user, as triggered by openFileBrowser().
519 This action happens after the user confirms the action, so the file browser dialog will be closed at this point.
520 The default implementation does nothing.
522 virtual void onFileSelected(const char* filename
);
524 /** DEPRECATED Use onFileSelected(). */
525 DISTRHO_DEPRECATED_BY("onFileSelected(const char*)")
526 inline virtual void fileBrowserSelected(const char* filename
) { return onFileSelected(filename
); }
530 PrivateData
* const pData
;
531 friend class Application
;
532 friend class TopLevelWidget
;
533 #ifdef DISTRHO_NAMESPACE
534 friend class DISTRHO_NAMESPACE::PluginWindow
;
538 explicit Window(Application
& app
,
539 uintptr_t parentWindowHandle
,
547 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window
)
550 // -----------------------------------------------------------------------
554 #endif // DGL_WINDOW_HPP_INCLUDED