Skip to content

Commit

Permalink
[3.2] Add window click-through support.
Browse files Browse the repository at this point in the history
  • Loading branch information
bruvzg committed Sep 17, 2020
1 parent 31d0f8a commit e51fed9
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 0 deletions.
6 changes: 6 additions & 0 deletions core/bind/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ void _OS::set_window_title(const String &p_title) {
OS::get_singleton()->set_window_title(p_title);
}

void _OS::set_window_mouse_passthrough(const PoolVector2Array &p_region) {

OS::get_singleton()->set_window_mouse_passthrough(p_region);
}

int _OS::get_mouse_button_state() const {

return OS::get_singleton()->get_mouse_button_state();
Expand Down Expand Up @@ -1307,6 +1312,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_touchscreen_ui_hint"), &_OS::has_touchscreen_ui_hint);

ClassDB::bind_method(D_METHOD("set_window_title", "title"), &_OS::set_window_title);
ClassDB::bind_method(D_METHOD("set_window_mouse_passthrough", "region"), &_OS::set_window_mouse_passthrough);

ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode", "enable"), &_OS::set_low_processor_usage_mode);
ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"), &_OS::is_in_low_processor_usage_mode);
Expand Down
1 change: 1 addition & 0 deletions core/bind/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ class _OS : public Object {

Point2 get_mouse_position() const;
void set_window_title(const String &p_title);
void set_window_mouse_passthrough(const PoolVector2Array &p_region);
int get_mouse_button_state() const;

void set_clipboard(const String &p_text);
Expand Down
1 change: 1 addition & 0 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class OS {
virtual Point2 get_mouse_position() const = 0;
virtual int get_mouse_button_state() const = 0;
virtual void set_window_title(const String &p_title) = 0;
virtual void set_window_mouse_passthrough(const PoolVector2Array &p_region){};

virtual void set_clipboard(const String &p_text);
virtual String get_clipboard() const;
Expand Down
22 changes: 22 additions & 0 deletions doc/classes/OS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,28 @@
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
</description>
</method>
<method name="set_window_mouse_passthrough">
<return type="void">
</return>
<argument index="0" name="region" type="PoolVector2Array">
</argument>
<description>
Sets a polygonal region of the window which accepts mouse events. Mouse events outside the region will be passed through.
Passing an empty array will disable passthrough support (all mouse events will be intercepted by the window, which is the default behavior).
[codeblock]
# Set region, using Path2D node.
OS.set_window_mouse_passthrough($Path2D.curve.get_baked_points())

# Set region, using Polygon2D node.
OS.set_window_mouse_passthrough($Polygon2D.polygon)

# Reset region to default.
OS.set_window_mouse_passthrough([])
[/codeblock]
[b]Note:[/b] On Windows, the portion of a window that lies outside the region is not drawn, while on Linux and macOS it is.
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
</description>
</method>
<method name="set_window_title">
<return type="void">
</return>
Expand Down
2 changes: 2 additions & 0 deletions platform/osx/os_osx.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class OS_OSX : public OS_Unix {
NSOpenGLPixelFormat *pixelFormat;
NSOpenGLContext *context;

Vector<Vector2> mpath;
bool layered_window;

CursorShape cursor_shape;
Expand Down Expand Up @@ -208,6 +209,7 @@ class OS_OSX : public OS_Unix {
virtual int get_mouse_button_state() const;
void update_real_mouse_position();
virtual void set_window_title(const String &p_title);
virtual void set_window_mouse_passthrough(const PoolVector2Array &p_region);

virtual Size2 get_window_size() const;
virtual Size2 get_real_window_size() const;
Expand Down
25 changes: 25 additions & 0 deletions platform/osx/os_osx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "os_osx.h"

#include "core/math/geometry.h"
#include "core/os/keyboard.h"
#include "core/print_string.h"
#include "core/version_generated.gen.h"
Expand Down Expand Up @@ -2136,6 +2137,13 @@ virtual void log_error(const char *p_function, const char *p_file, int p_line, c
[window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]];
}

void OS_OSX::set_window_mouse_passthrough(const PoolVector2Array &p_region) {
mpath.clear();
for (int i = 0; i < p_region.size(); i++) {
mpath.push_back(p_region[i]);
}
}

void OS_OSX::set_native_icon(const String &p_filename) {

FileAccess *f = FileAccess::open(p_filename, FileAccess::READ);
Expand Down Expand Up @@ -3053,6 +3061,23 @@ void _update_keyboard_layouts() {
}
process_key_events();

if (mpath.size() > 0) {
const Vector2 mpos = get_mouse_pos([window_object mouseLocationOutsideOfEventStream]);
if (Geometry::is_point_in_polygon(mpos, mpath)) {
if ([window_object ignoresMouseEvents]) {
[window_object setIgnoresMouseEvents:NO];
}
} else {
if (![window_object ignoresMouseEvents]) {
[window_object setIgnoresMouseEvents:YES];
}
}
} else {
if ([window_object ignoresMouseEvents]) {
[window_object setIgnoresMouseEvents:NO];
}
}

[autoreleasePool drain];
autoreleasePool = [[NSAutoreleasePool alloc] init];

Expand Down
32 changes: 32 additions & 0 deletions platform/windows/os_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "os_windows.h"

#include "core/io/marshalls.h"
#include "core/math/geometry.h"
#include "core/version_generated.gen.h"
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles3/rasterizer_gles3.h"
Expand Down Expand Up @@ -1952,6 +1953,36 @@ void OS_Windows::set_window_title(const String &p_title) {
SetWindowTextW(hWnd, p_title.c_str());
}

void OS_Windows::set_window_mouse_passthrough(const PoolVector2Array &p_region) {
mpath.clear();
for (int i = 0; i < p_region.size(); i++) {
mpath.push_back(p_region[i]);
}
_update_window_mouse_passthrough();
}

void OS_Windows::_update_window_mouse_passthrough() {
if (mpath.size() == 0) {
SetWindowRgn(hWnd, NULL, TRUE);
} else {
POINT *points = (POINT *)memalloc(sizeof(POINT) * mpath.size());
for (int i = 0; i < mpath.size(); i++) {
if (video_mode.borderless_window) {
points[i].x = mpath[i].x;
points[i].y = mpath[i].y;
} else {
points[i].x = mpath[i].x + GetSystemMetrics(SM_CXSIZEFRAME);
points[i].y = mpath[i].y + GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
}
}

HRGN region = CreatePolygonRgn(points, mpath.size(), ALTERNATE);
SetWindowRgn(hWnd, region, TRUE);
DeleteObject(region);
memfree(points);
}
}

void OS_Windows::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
}

Expand Down Expand Up @@ -2339,6 +2370,7 @@ void OS_Windows::set_borderless_window(bool p_borderless) {

preserve_window_size = true;
_update_window_style();
_update_window_mouse_passthrough();
}

bool OS_Windows::get_borderless_window() {
Expand Down
4 changes: 4 additions & 0 deletions platform/windows/os_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ class OS_Windows : public OS {
int pressrc;
HINSTANCE hInstance; // Holds The Instance Of The Application
HWND hWnd;

Vector<Vector2> mpath;
Point2 last_pos;

bool layered_window;
Expand Down Expand Up @@ -371,6 +373,7 @@ class OS_Windows : public OS {
void _touch_event(bool p_pressed, float p_x, float p_y, int idx);

void _update_window_style(bool p_repaint = true, bool p_maximized = false);
void _update_window_mouse_passthrough();

void _set_mouse_mode_impl(MouseMode p_mode);

Expand Down Expand Up @@ -422,6 +425,7 @@ class OS_Windows : public OS {
void update_real_mouse_position();
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String &p_title);
virtual void set_window_mouse_passthrough(const PoolVector2Array &p_region);

virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0);
virtual VideoMode get_video_mode(int p_screen = 0) const;
Expand Down
6 changes: 6 additions & 0 deletions platform/x11/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def can_build():
print("xinerama not found.. x11 disabled.")
return False

x11_error = os.system("pkg-config xext --modversion > /dev/null ")
if x11_error:
print("xext not found.. x11 disabled.")
return False

x11_error = os.system("pkg-config xrandr --modversion > /dev/null ")
if x11_error:
print("xrandr not found.. x11 disabled.")
Expand Down Expand Up @@ -197,6 +202,7 @@ def configure(env):
env.ParseConfig("pkg-config x11 --cflags --libs")
env.ParseConfig("pkg-config xcursor --cflags --libs")
env.ParseConfig("pkg-config xinerama --cflags --libs")
env.ParseConfig("pkg-config xext --cflags --libs")
env.ParseConfig("pkg-config xrandr --cflags --libs")
env.ParseConfig("pkg-config xrender --cflags --libs")
env.ParseConfig("pkg-config xi --cflags --libs")
Expand Down
28 changes: 28 additions & 0 deletions platform/x11/os_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/shape.h>

// ICCCM
#define WM_NormalState 1L // window normal state
Expand Down Expand Up @@ -976,6 +977,33 @@ void OS_X11::set_window_title(const String &p_title) {
XChangeProperty(x11_display, x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length());
}

void OS_X11::set_window_mouse_passthrough(const PoolVector2Array &p_region) {
int event_base, error_base;
const Bool ext_okay = XShapeQueryExtension(x11_display, &event_base, &error_base);
if (ext_okay) {
Region region;
if (p_region.size() == 0) {
region = XCreateRegion();
XRectangle rect;
rect.x = 0;
rect.y = 0;
rect.width = get_real_window_size().x;
rect.height = get_real_window_size().y;
XUnionRectWithRegion(&rect, region, region);
} else {
XPoint *points = (XPoint *)memalloc(sizeof(XPoint) * p_region.size());
for (int i = 0; i < p_region.size(); i++) {
points[i].x = p_region[i].x;
points[i].y = p_region[i].y;
}
region = XPolygonRegion(points, p_region.size(), EvenOddRule);
memfree(points);
}
XShapeCombineRegion(x11_display, x11_window, ShapeInput, 0, 0, region, ShapeSet);
XDestroyRegion(region);
}
}

void OS_X11::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
}

Expand Down
1 change: 1 addition & 0 deletions platform/x11/os_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ class OS_X11 : public OS_Unix {
virtual Point2 get_mouse_position() const;
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String &p_title);
virtual void set_window_mouse_passthrough(const PoolVector2Array &p_region);

virtual void set_icon(const Ref<Image> &p_icon);

Expand Down

0 comments on commit e51fed9

Please sign in to comment.