Skip to content

Commit 2b7745d

Browse files
authored
GLFW transparent window background touch/click pass through (#8092)
* ofAppGLFWWindow transparent input pass through (cherry picked from commit 49b117d) * GLFW Transparency Pass Through Functions (cherry picked from commit 9acecba) * example windowing transparentWindow - added (cherry picked from commit 87b14e9) * Update for Variable names and function names (cherry picked from commit 92f0ae1) * Update to transparent window example to new variables and spinning (cherry picked from commit 1d489cf) * Function name camelCase. fixed some space tabs in example (cherry picked from commit d3ea82a) * mousePassThrough setting (cherry picked from commit 3b1417d) * passThrough variable name in GLFW and example updated with blue circle to disable force passThrough (cherry picked from commit c7a409b)
1 parent fcc4fba commit 2b7745d

10 files changed

Lines changed: 436 additions & 1 deletion

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# About transparentWindow
2+
3+
![Screenshot of Example, stored as exampleName/screenshot.png (or .gif or .jpg)](transparentWindow.png)
4+
5+
6+
### Learning Objectives
7+
8+
This example demonstrates how to set and get window properties for GLFW Transparency setup and GLFW attribute for mouse passThrough this transparency to context behind the window
9+
10+
In the code, pay attention to:
11+
12+
* Use of ````ofSetWindowTransparencyInput()```` to set if mouse input passThrough is enabled or disabled for the window
13+
* Use of ````mouseMoved()```` used to check if within bounds to disable passThrough to region developer elected
14+
* The GLFW events that are disabled (keyboard press/release, mouse press/release) when passThrough is enabled, and the events that work like mouseMove, mouseExit, mouseEnter for the Window
15+
* Use of ````ofSetFullscreen()```` to toggle between fullscreen and windowed modes
16+
17+
main.cpp setup
18+
```
19+
ofGLFWWindowSettings settings;
20+
settings.transparent = true;
21+
settings.transparentInput = true;
22+
settings.floating = true;
23+
settings.decorated = false;
24+
```
25+
26+
### Expected Behavior
27+
28+
When launching this application you will see the following:
29+
30+
* A Transparent window with guides drawn for the edges 1280x720
31+
* The top quandrant has an area that when you mouseMove to passThrough will be disabled
32+
* The transparent quadrant below that when mouseMove to - passThrough is enabled
33+
* A GLFW ```floating window``` with no titlebar shown even when set
34+
* A ball that is constantly boucing off the interior of the window, affecting the position of the window
35+
* Text at the top that reports the mode of the window, and some commands for toggling logs, ( fullscreen or normal ) etc
36+
37+
When the key ````g```` is pressed:
38+
39+
* The Guide Rectangles will not be drawn and you will see the full transparency of the Window. Toggle on or off
40+
41+
When the key ````h```` is pressed:
42+
43+
* passThrough will be enabled if in state of disabled. toggling it to disable will not work due to the GLFW events. See note
44+
45+
When the key ````f```` is pressed:
46+
47+
* If the window is in normal mode, the window will go in fullscreen mode, hiding the cursor
48+
* If the window is in fullscreen mode, the window will return to the normal mode and show the cursor
49+
50+
When the key ````l```` is pressed:
51+
52+
* Verbose Logs / Notice Logs - Toggle
53+
54+
Instructions for use:
55+
56+
* Running the application will result in the transparent window slightly moving position as the ball hits an interior wall
57+
58+
59+
### Other classes used in this file
60+
61+
This Example uses no other classes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "ofMain.h"
2+
#include "ofApp.h"
3+
4+
//========================================================================
5+
int main( ){
6+
7+
//Use ofGLFWWindowSettings for more options like multi-monitor fullscreen
8+
ofGLFWWindowSettings settings;
9+
settings.transparent = true;
10+
settings.mousePassThrough = true;
11+
settings.floating = true;
12+
settings.decorated = false;
13+
settings.windowMode = OF_WINDOW;
14+
settings.setGLVersion(4, 1);
15+
settings.setSize(1280, 720);
16+
auto window = ofCreateWindow(settings);
17+
18+
ofRunApp(window, std::make_shared<ofApp>());
19+
ofRunMainLoop();
20+
21+
}
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
#include "ofApp.h"
2+
3+
//--------------------------------------------------------------
4+
void ofApp::setup(){
5+
if(bLogVerbose){
6+
ofSetLogLevel(OF_LOG_VERBOSE);
7+
}
8+
int screenW = ofGetScreenWidth();
9+
int screenH = ofGetScreenHeight();
10+
ofSetWindowPosition(screenW/2-1280/2, screenH/2-720/2);
11+
fontRenderer.load(OF_TTF_MONO, 14);
12+
lineHeight = fontRenderer.getLineHeight();
13+
14+
bFullscreen = 0;
15+
ofBackground(0, 0, 0, 0);
16+
ofSetWindowTitle("GLFW Transparency"); // should not be shown with floating
17+
ofSetFrameRate(60);
18+
uint64_t stepNanos = ofGetFixedStepForFps(60);
19+
ofSetTimeModeFixedRate(stepNanos);
20+
21+
ballPositionX = 500;
22+
ballPositionY = 500;
23+
ballVelocityX = ofRandom(-5,5);
24+
ballVelocityY = ofRandom(-5,5);
25+
26+
bgColor = ofColor(240, 248, 255); // Light Blue
27+
textColor = ofColor(0, 51, 102); // Dark Blue
28+
primaryBtnColor = ofColor(51, 153, 255); // Bright Blue
29+
secondaryBtnColor = ofColor(204, 204, 255); // Light Blue
30+
highlightColor = ofColor(255, 204, 204); // Soft Pink
31+
}
32+
33+
//--------------------------------------------------------------
34+
void ofApp::update(){
35+
36+
if(bFullscreen){
37+
ofHideCursor();
38+
} else{
39+
ofShowCursor();
40+
}
41+
42+
ballPositionX += ballVelocityX;
43+
ballPositionY += ballVelocityY;
44+
45+
int posx = ofGetWindowPositionX();
46+
int posy = ofGetWindowPositionY();
47+
48+
if (ballPositionX < 0){
49+
ballPositionX = 0;
50+
ballVelocityX *= -1;
51+
if (!bFullscreen){
52+
ofSetWindowPosition(posx-10, posy);
53+
}
54+
} else if (ballPositionX > ofGetWidth()){
55+
ballPositionX = ofGetWidth();
56+
ballVelocityX *= -1;
57+
if (!bFullscreen){
58+
ofSetWindowPosition(posx+10, posy);
59+
}
60+
}
61+
62+
if (ballPositionY < 0){
63+
ballPositionY = 0;
64+
ballVelocityY *= -1;
65+
if (!bFullscreen){
66+
ofSetWindowPosition(posx, posy-10);
67+
}
68+
} else if (ballPositionY > ofGetHeight()){
69+
ballPositionY = ofGetHeight();
70+
ballVelocityY *= -1;
71+
if (!bFullscreen){
72+
ofSetWindowPosition(posx, posy+10);
73+
}
74+
}
75+
76+
}
77+
78+
//--------------------------------------------------------------
79+
void ofApp::draw(){
80+
ofSetupScreen();
81+
int width = ofGetWidth();
82+
int height = ofGetHeight();
83+
84+
// Based on @geluso Draw 100 circles https://github.com/geluso
85+
for(int i = 0; i < 100; i++) {
86+
float speed = 1.74f;
87+
float sinX = sin(i + ofGetElapsedTimef() * speed) * 100;
88+
float sinAlpha = ofMap(sin(i + ofGetElapsedTimef() * speed),-1, 1, 0, 200);
89+
float sinRadius = ofMap(sin(i * ofGetElapsedTimef() * 0.05),-1, 1, 5, 30);
90+
ofSetColor(255,0,0,sinAlpha);
91+
ofDrawCircle(i * 13, sinX + ofGetWidth()*0.5, sinRadius);
92+
}
93+
94+
if(bDrawGuides) { // Draw edge of transparent window for clarity
95+
int screenWidth = ofGetWidth();
96+
int screenHeight = ofGetHeight();
97+
ofSetColor(secondaryBtnColor);
98+
ofDrawRectangle(0, 0, screenWidth, 6);
99+
ofDrawRectangle(0, screenHeight - 6, screenWidth, 6);
100+
ofDrawRectangle(0, 0, 6, screenHeight);
101+
ofDrawRectangle(screenWidth - 6, 0, 6, screenHeight);
102+
// draw top rect for disabling passThrough example
103+
ofSetColor(highlightColor);
104+
ofSetColor(ofColor(80, 80, 80, 196));
105+
ofDrawRectangle(0, 0, screenWidth, 300);
106+
ofSetColor(0x000000);
107+
ofDrawLine(0, 0, 0, height);
108+
ofDrawLine(width, 0, width, height);
109+
ofDrawLine(0, height, width, height);
110+
}
111+
112+
ofSetColor(textColor);
113+
centerX = ofGetWidth() / 2;
114+
centerY = 200;
115+
baseY = centerY - 2 * lineSpacing;
116+
if (bAllowPassThrough) {
117+
ofSetColor(primaryBtnColor);
118+
ofDrawRectangle(40, 10 + 1 * lineSpacing, 550, 200);
119+
ofSetColor(textColor);
120+
fontRenderer.drawString("Note: When GLFW mouse passThrough is Enabled", 50, 10 + 2 * lineSpacing);
121+
fontRenderer.drawString("GLFW Events are Disabled for that Window", 50, 10 + 3 * lineSpacing);
122+
fontRenderer.drawString("Disabled: Keyboard Events/Mouse Press/Release", 50, 10 + 4 * lineSpacing);
123+
fontRenderer.drawString("Enabled: mouseMoved/mouseExit/mouseEnter", 50, 10 + 5 * lineSpacing);
124+
} else {
125+
ofSetColor(primaryBtnColor);
126+
ofDrawRectangle(40, 10 + 1 * lineSpacing, 550, 200);
127+
ofSetColor(textColor);
128+
fontRenderer.drawString("Note: When GLFW mouse passThrough is Disabled", 50, 10 + 2 * lineSpacing);
129+
fontRenderer.drawString("GLFW Events are all enabled!", 50, 10 + 3 * lineSpacing);
130+
fontRenderer.drawString("This happens dynamically via GLFW Attribute", 50, 10 + 4 * lineSpacing);
131+
}
132+
133+
ofSetColor(highlightColor);
134+
if (bAllowPassThrough) {
135+
fontRenderer.drawString("GLFW Mouse passThrough enabled", centerX, 2 * lineSpacing);
136+
if(bForcePassThrough) {
137+
fontRenderer.drawString("Enabled: Force Mouse passThrough - Click the Blue Circle", centerX, 1 * lineSpacing);
138+
}
139+
} else {
140+
fontRenderer.drawString("press h to enable GLFW passThrough or mouse below box", centerX, 2 * lineSpacing);
141+
}
142+
ofSetColor(secondaryBtnColor);
143+
144+
if (!bFullscreen) {
145+
fontRenderer.drawString("press f to enter fullscreen", centerX, baseY);
146+
fontRenderer.drawString("window is normal / floating", centerX, baseY + lineSpacing);
147+
} else {
148+
fontRenderer.drawString("press f to exit fullscreen", centerX, baseY);
149+
fontRenderer.drawString("window is fullscreen", centerX, baseY + lineSpacing);
150+
}
151+
152+
if (bDrawGuides) {
153+
fontRenderer.drawString("press g to disable drawing edges", centerX, baseY + 2 * lineSpacing);
154+
} else {
155+
fontRenderer.drawString("press g to enable drawing edges", centerX , baseY + 2 * lineSpacing);
156+
}
157+
158+
if (bLogVerbose) {
159+
fontRenderer.drawString("press L to disable Verbose Log", centerX , baseY + 3 * lineSpacing);
160+
} else {
161+
fontRenderer.drawString("press L to enable Verbose Log", centerX , baseY + 3 * lineSpacing);
162+
}
163+
164+
fontRenderer.drawString("window pos ("+ofToString(ofGetWindowPositionX())+", "+ofToString( ofGetWindowPositionY())+")", 20, 30);
165+
166+
ofSetColor(primaryBtnColor);
167+
ofDrawCircle(ballPositionX, ballPositionY, 15);
168+
}
169+
170+
171+
//--------------------------------------------------------------
172+
void ofApp::keyPressed(int key){
173+
174+
if(key == 'f' || key == 'F'){
175+
bFullscreen = !bFullscreen;
176+
if(!bFullscreen){
177+
ofSetWindowShape(1280,720);
178+
ofSetFullscreen(false);
179+
int screenW = ofGetScreenWidth();
180+
int screenH = ofGetScreenHeight();
181+
ofSetWindowPosition(screenW/2-1280/2, screenH/2-720/2);
182+
} else if(bFullscreen == 1){
183+
ofSetFullscreen(true);
184+
}
185+
ofLogNotice("ofApp") << "bFullscreen:" << bFullscreen;
186+
187+
} else if(key == 'g' || key == 'G'){
188+
bDrawGuides = !bDrawGuides;
189+
ofLogNotice("ofApp") << "bDrawGuides:" << bDrawGuides;
190+
191+
} else if(key == 'h' || key == 'H'){
192+
bAllowPassThrough = !bAllowPassThrough;
193+
bForcePassThrough = !bForcePassThrough;
194+
ofSetWindowMousePassThrough(bAllowPassThrough);
195+
ofLogNotice("ofApp") << "ofSetWindowMousePassThrough:" << bAllowPassThrough << " Force:" << bForcePassThrough;
196+
197+
} else if(key == 'l' || key == 'L' ){
198+
bLogVerbose = !bLogVerbose;
199+
if(bLogVerbose)
200+
ofSetLogLevel(OF_LOG_VERBOSE);
201+
else
202+
ofSetLogLevel(OF_LOG_NOTICE);
203+
ofLogNotice("ofApp") << "bLogVerbose:" << bLogVerbose;
204+
}
205+
}
206+
207+
//--------------------------------------------------------------
208+
void ofApp::keyReleased(int key){
209+
ofLogVerbose("ofApp") << "keyReleased:" << key;
210+
}
211+
212+
//--------------------------------------------------------------
213+
void ofApp::mouseMoved(int x, int y ){
214+
ofLogVerbose("ofApp") << "mouseMoved: x:" << x << " y:" << y;
215+
216+
float distance = ofDist(x, y, ballPositionX, ballPositionY);
217+
if(distance <= 15 || y < 300) {
218+
if(bForcePassThrough == true && distance <= 15){
219+
bForcePassThrough = false;
220+
}
221+
if(bAllowPassThrough && (bForcePassThrough == false || distance <= 15)) {
222+
bAllowPassThrough = false;
223+
ofLogNotice("ofApp") << "ofSetWindowMousePassThrough:" << bAllowPassThrough;
224+
ofSetWindowMousePassThrough(bAllowPassThrough);
225+
}
226+
} else {
227+
if(!bAllowPassThrough) {
228+
bAllowPassThrough = true;
229+
ofLogNotice("ofApp") << "ofSetWindowMousePassThrough:" << bAllowPassThrough;
230+
ofSetWindowMousePassThrough(bAllowPassThrough);
231+
}
232+
}
233+
}
234+
235+
//--------------------------------------------------------------
236+
void ofApp::mouseDragged(int x, int y, int button){
237+
238+
}
239+
240+
//--------------------------------------------------------------
241+
void ofApp::mousePressed(int x, int y, int button){
242+
ofLogNotice("ofApp") << "mousePressed:" << button << " x:" << x << " y:" << y;
243+
}
244+
245+
//--------------------------------------------------------------
246+
void ofApp::mouseReleased(int x, int y, int button){
247+
ofLogNotice("ofApp") << "mouseReleased:" << button << " x:" << x << " y:" << y;
248+
}
249+
250+
//--------------------------------------------------------------
251+
void ofApp::mouseEntered(int x, int y){
252+
ofLogNotice("ofApp") << "mouseEntered the ofWindow: " << " x:" << x << " y:" << y;
253+
}
254+
255+
//--------------------------------------------------------------
256+
void ofApp::mouseExited(int x, int y){
257+
ofLogNotice("ofApp") << "mouseExited the ofWindow: " << " x:" << x << " y:" << y;
258+
}
259+
260+
//--------------------------------------------------------------
261+
void ofApp::windowResized(int w, int h){
262+
263+
}
264+
265+
//--------------------------------------------------------------
266+
void ofApp::gotMessage(ofMessage msg){
267+
268+
}
269+
270+
//--------------------------------------------------------------
271+
void ofApp::dragEvent(ofDragInfo dragInfo){
272+
273+
}
274+

0 commit comments

Comments
 (0)