openframeworks / openframeworks/openFrameworks

[feature request] a more malleable fullscreen interface

Open
#7,759 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
10.4k
Forks
2.6k
Avg merge
1d 21h
Merged PRs (30d)
9

Description

in order to allow a more malleable fullscreen UX, the notion of "fullscreeneness" shall be expressible by an arbitrary rectangle (previously the only option to "implicit" fullscreen was unilateral multi fullscreen enabled in Settings).

this designs takes into account default behaviour, backward-compatibility, and "ease of use" / "ease of implementation" — provides methods to query the system about monitors (more or less channelling some GLFW readily available stuff), but leaves complicated stuff in the hands of the complication-loving programmer. from OF's point of view it is basically adapting existing multimonitor code to a different invocation pattern, and allowing the rect to be user-settable.

in terms of API, in https://github.com/openframeworks/openFrameworks/issues/7752#issuecomment-1815731410 the suggestion was made to add a method that sets a retained ofRectangle subsequently used by the fullscreen code as the "fullscreen rect". however this introduces gray zones: this Rect must have a default (presumably: "the monitor in which the OF window is in") but what happens if you move the OF window to another monitor and toggle fullscreen? if the default follows the window, it would overwrite a custom rect. or "if a custom rect has been set, don't update it"?... that seems prone to ambiguous interpretation on both sides of the interface.

A simpler, non-obtrusive and backward-compatible approach is to add a rect argument flavour as ofSetFullScreen(ofRectangle & desired_rect). that way, the current behaviour is not affected in any way, and only a user wishing for a custom rect will activate the custom rect code path (no hidden funny, sequence-dependent stuff). working in this immediate-mode-ish manner means less methods and no data internally retained — it is up to the programmer to persist their desired_rect or not.

the suggested API allows one to cycle freely between "window", "standard fullscreen" and "custom fullscreen":

Usage:

// basic
ofSetFullScreen(true); // fullscreen current monitor
ofSetFullScreen(false); // back to window

// drag window to another monitor
ofSetFullScreen(true); // fullscreen in the other monitor
ofSetFullScreen(ofGetMainMonitorRect()); // fullscreens the main monitor;
ofSetFullScreen(false); // back to window in other monitor (retained last windowed coords before fullscreen)

// equivalent to ofGLFWWindowSettings::multiMonitorFullScreen
ofSetFullScreen(ofGetMultiMonitorsRect()); // fullscreens the whole set of monitors

// dangerous but appropriate in controlled install/performance setups:
auto monitors =  ofGetConnectedMonitorsRects();
auto r = monitors[1];
for (size_t i = 2; i < monitors.size(); i++) r.growToInclude(monitors[i]);
ofSetFullScreen(r); // fullscreens on all but first monitor

// note that the monitor rect getters are also usefull for windows:
ofSetWindowPosition(ofGetMultiMonitorsRect()[1].getPosition()); // positions the window on the 2nd monitor

Interface:

// \param desired_rect invokes the OF fullscreen) with the custom rectangle
// (based on current ofFullscreen method (hide decorations, menu, etc))
// returns true if the operation was successfully completed as per the desired_rect
bool ofSetFullScreen(const ofRectangle & desired_rect)

// \brief get gemetry of the connected monitors
// \returns a vector of rectangles (order follows the underlying WM logic)
std::vector<ofRectangle> ofGetConnectedMonitorsRects() const

// \brief get the geomegry for the main monitor
// \returns an ofRectangle corresponding to the main monitor 
ofRectangle ofGetMainMonitorRect() const

// \brief get the geometry for the monitor currently handling the OF window
// \returns an ofRectangle corresponding to the current window 
ofRectangle ofGetCurrentMonitorRect() const

// \brief get the smallest rectangle that encompasses all connected monitors
// \returns an ofRectangle encompassing all connected monitors
ofRectangle ofGetMultiMonitorsRect() const

note that i am avoiding ofToggleFullScreen() — as far as i'm concerned i would deprecate that function as there is no gain to "not know" which direction the action is going. if you want toggling behaviour it is only a matter of storing the boolean state at your app level -- or relying on a queried property to determine the current state and call the other. ofToggleFullScreen() is a bad shortcut that only serves to obfuscates 1 bit of info.

note that @dimitre has a proposal #6954 that uses an optional bool; some analysis needed to determine how to combine the interface -- and probably at the same time merge all that work!

it also requires making sure things are cross-platform; i can test multimonitor setups on macOS14 and archlinux/i3wm/X11/nvidia

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the existing ofSetFullScreen(), ofToggleFullScreen(), and multimonitor handling, along with proposal #6954 and issue #7752. Define how the proposed rectangle and monitor-query APIs should interact with existing behavior, then verify fullscreen transitions and monitor geometry across macOS and Linux/X11 as described.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
desktop
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.