Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add double-click maximise support to the x11 displayserver for the move decoration #6

Open
wants to merge 7 commits into
base: client_decor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1224,13 +1224,32 @@
[b]Note:[/b] [method warp_mouse] is only supported on Windows, macOS and Linux. It has no effect on Android, iOS and Web.
</description>
</method>
<method name="window_add_decoration">
<return type="int" />
<param index="0" name="region" type="PackedVector2Array" />
<param index="1" name="dec_type" type="int" enum="DisplayServer.WindowDecorationType" />
<param index="2" name="window" type="int" default="0" />
<description>
Adds polygon which should act as window move / resize region specified by [param dec_type].
</description>
</method>
<method name="window_can_draw" qualifiers="const">
<return type="bool" />
<param index="0" name="window_id" type="int" default="0" />
<description>
Returns [code]true[/code] if anything can be drawn in the window specified by [param window_id], [code]false[/code] otherwise. Using the [code]--disable-render-loop[/code] command line argument or a headless build will return [code]false[/code].
</description>
</method>
<method name="window_change_decoration">
<return type="void" />
<param index="0" name="rect_id" type="int" />
<param index="1" name="region" type="PackedVector2Array" />
<param index="2" name="dec_type" type="int" enum="DisplayServer.WindowDecorationType" />
<param index="3" name="window" type="int" default="0" />
<description>
Changes type and polygon of the move / resize region created using [method window_add_decoration].
</description>
</method>
<method name="window_get_active_popup" qualifiers="const">
<return type="int" />
<description>
Expand Down Expand Up @@ -1382,6 +1401,14 @@
Moves the window specified by [param window_id] to the foreground, so that it is visible over other windows.
</description>
</method>
<method name="window_remove_decoration">
<return type="void" />
<param index="0" name="rect_id" type="int" />
<param index="1" name="window" type="int" default="0" />
<description>
Removes move / resize region created using [method window_add_decoration].
</description>
</method>
<method name="window_request_attention">
<return type="void" />
<param index="0" name="window_id" type="int" default="0" />
Expand Down Expand Up @@ -1681,6 +1708,9 @@
<constant name="FEATURE_SCREEN_CAPTURE" value="21" enum="Feature">
Display server supports reading screen pixels. See [method screen_get_pixel].
</constant>
<constant name="FEATURE_CLIENT_SIDE_DECORATIONS" value="22" enum="Feature">
Display server supports client side decorations. See [method window_add_decoration], [method window_change_decoration], and [method window_remove_decoration].
</constant>
<constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode">
Makes the mouse cursor visible if it is hidden.
</constant>
Expand Down Expand Up @@ -1913,6 +1943,33 @@
Sent when the window title bar decoration is changed (e.g. [constant WINDOW_FLAG_EXTEND_TO_TITLE] is set or window entered/exited full screen mode).
[b]Note:[/b] This flag is implemented only on macOS.
</constant>
<constant name="WINDOW_DECORATION_TOP_LEFT" value="0" enum="WindowDecorationType">
Window top-left resize element.
</constant>
<constant name="WINDOW_DECORATION_TOP" value="1" enum="WindowDecorationType">
Window top resize element.
</constant>
<constant name="WINDOW_DECORATION_TOP_RIGHT" value="2" enum="WindowDecorationType">
Window top-right resize element.
</constant>
<constant name="WINDOW_DECORATION_LEFT" value="3" enum="WindowDecorationType">
Window left resize element.
</constant>
<constant name="WINDOW_DECORATION_RIGHT" value="4" enum="WindowDecorationType">
Window right resize element.
</constant>
<constant name="WINDOW_DECORATION_BOTTOM_LEFT" value="5" enum="WindowDecorationType">
Window bottom-left resize element.
</constant>
<constant name="WINDOW_DECORATION_BOTTOM" value="6" enum="WindowDecorationType">
Window bottom resize element.
</constant>
<constant name="WINDOW_DECORATION_BOTTOM_RIGHT" value="7" enum="WindowDecorationType">
Window bottom-right resize element.
</constant>
<constant name="WINDOW_DECORATION_MOVE" value="8" enum="WindowDecorationType">
Window move element.
</constant>
<constant name="VSYNC_DISABLED" value="0" enum="VSyncMode">
No vertical synchronization, which means the engine will display frames as fast as possible (tearing may be visible). Framerate is unlimited (notwithstanding [member Engine.max_fps]).
</constant>
Expand Down
24 changes: 24 additions & 0 deletions doc/classes/WindowDecoration.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="WindowDecoration" inherits="Control" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A move / resize region for the native [Window].
</brief_description>
<description>
A move / resize region, used to implement client side decorations for the native [Window].
</description>
<tutorials>
</tutorials>
<members>
<member name="decoration_type" type="int" setter="set_decoration_type" getter="get_decoration_type" enum="DisplayServer.WindowDecorationType" default="8">
Move / resize region type.
</member>
<member name="non_rectangular_region" type="bool" setter="set_non_rectangular_region" getter="is_non_rectangular_region" default="false">
If [code]true[/code], polygonal region is used instead of control bounds.
</member>
<member name="polygon" type="PackedVector2Array" setter="set_polygon" getter="get_polygon" default="PackedVector2Array()">
The region's list of vertices. The final point will be connected to the first.
[b]Note:[/b] Used only if [member non_rectangular_region] is [code]true[/code].
[b]Note:[/b] This returns a copy of the [PackedVector2Array] rather than a reference.
</member>
</members>
</class>
101 changes: 65 additions & 36 deletions editor/gui/editor_title_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,55 +30,84 @@

#include "editor_title_bar.h"

void EditorTitleBar::gui_input(const Ref<InputEvent> &p_event) {
if (!can_move) {
void EditorTitleBar::_update_rects() {
if (!is_inside_tree()) {
return;
}
if (!DisplayServer::get_singleton()) {
return;
}
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIENT_SIDE_DECORATIONS)) {
return;
}

Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid() && moving) {
if (mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
Window *w = Object::cast_to<Window>(get_viewport());
if (w) {
Point2 mouse = DisplayServer::get_singleton()->mouse_get_position();
w->set_position(mouse - click_pos);
DisplayServer::WindowID wid = get_viewport()->get_window_id();
for (int &id : ids) {
DisplayServer::get_singleton()->window_remove_decoration(id, wid);
}
ids.clear();

if (can_move) {
Vector<Rect2i> rects;
int prev_pos = 0;
int count = get_child_count();
for (int i = 0; i < count; i++) {
Control *n = Object::cast_to<Control>(get_child(i));
if (n && n->get_mouse_filter() != Control::MOUSE_FILTER_PASS) {
int start = n->get_position().x;
rects.push_back(Rect2(prev_pos, 0, start - prev_pos, get_size().y));
prev_pos = start + n->get_size().x;
}
} else {
moving = false;
}
if (prev_pos != 0) {
rects.push_back(Rect2(prev_pos, 0, get_size().x - prev_pos, get_size().y));
}

for (Rect2i &rect : rects) {
Vector<Point2> polygon_global;
polygon_global.push_back(rect.position);
polygon_global.push_back(rect.position + Vector2(rect.size.x, 0));
polygon_global.push_back(rect.position + rect.size);
polygon_global.push_back(rect.position + Vector2(0, rect.size.y));

Transform2D t = get_global_transform();
for (Vector2 &E : polygon_global) {
E = t.xform(E);
}
int id = DisplayServer::get_singleton()->window_add_decoration(polygon_global, DisplayServer::WINDOW_DECORATION_MOVE, wid);
ids.push_back(id);
}
}
}

Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && has_point(mb->get_position())) {
Window *w = Object::cast_to<Window>(get_viewport());
if (w) {
if (mb->get_button_index() == MouseButton::LEFT) {
if (mb->is_pressed()) {
click_pos = DisplayServer::get_singleton()->mouse_get_position() - w->get_position();
moving = true;
} else {
moving = false;
}
void EditorTitleBar::_notification(int p_notification) {
switch (p_notification) {
case NOTIFICATION_CHILD_ORDER_CHANGED:
case NOTIFICATION_RESIZED:
case NOTIFICATION_ENTER_TREE: {
_update_rects();
} break;
case NOTIFICATION_EXIT_TREE: {
if (!DisplayServer::get_singleton()) {
return;
}
if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click() && mb->is_pressed()) {
if (DisplayServer::get_singleton()->window_maximize_on_title_dbl_click()) {
if (w->get_mode() == Window::MODE_WINDOWED) {
w->set_mode(Window::MODE_MAXIMIZED);
} else if (w->get_mode() == Window::MODE_MAXIMIZED) {
w->set_mode(Window::MODE_WINDOWED);
}
} else if (DisplayServer::get_singleton()->window_minimize_on_title_dbl_click()) {
w->set_mode(Window::MODE_MINIMIZED);
}
moving = false;
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIENT_SIDE_DECORATIONS)) {
return;
}
}
DisplayServer::WindowID wid = get_viewport()->get_window_id();
for (int &id : ids) {
DisplayServer::get_singleton()->window_remove_decoration(id, wid);
}
ids.clear();
} break;
}
}

void EditorTitleBar::set_can_move_window(bool p_enabled) {
can_move = p_enabled;
set_process_input(can_move);
if (can_move != p_enabled) {
can_move = p_enabled;
_update_rects();
}
}

bool EditorTitleBar::get_can_move_window() const {
Expand Down
7 changes: 4 additions & 3 deletions editor/gui/editor_title_bar.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@
class EditorTitleBar : public HBoxContainer {
GDCLASS(EditorTitleBar, HBoxContainer);

Point2i click_pos;
bool moving = false;
Vector<int> ids;
bool can_move = false;

void _update_rects();

protected:
virtual void gui_input(const Ref<InputEvent> &p_event) override;
void _notification(int p_notification);
static void _bind_methods(){};

public:
Expand Down
1 change: 1 addition & 0 deletions editor/icons/WindowDecoration.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion editor/plugins/abstract_polygon_2d_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void AbstractPolygon2DEditor::_set_polygon(int p_idx, const Variant &p_polygon)
}

void AbstractPolygon2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
Node2D *node = _get_node();
CanvasItem *node = _get_node();
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->add_do_method(node, "set_polygon", p_polygon);
undo_redo->add_undo_method(node, "set_polygon", p_previous);
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/abstract_polygon_2d_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class AbstractPolygon2DEditor : public HBoxContainer {

bool _is_empty() const;

virtual Node2D *_get_node() const = 0;
virtual CanvasItem *_get_node() const = 0;
virtual void _set_node(Node *p_polygon) = 0;

virtual bool _is_line() const;
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/collision_polygon_2d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#include "collision_polygon_2d_editor_plugin.h"

Node2D *CollisionPolygon2DEditor::_get_node() const {
CanvasItem *CollisionPolygon2DEditor::_get_node() const {
return node;
}

Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/collision_polygon_2d_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class CollisionPolygon2DEditor : public AbstractPolygon2DEditor {
CollisionPolygon2D *node = nullptr;

protected:
virtual Node2D *_get_node() const override;
virtual CanvasItem *_get_node() const override;
virtual void _set_node(Node *p_polygon) override;

public:
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/light_occluder_2d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Ref<OccluderPolygon2D> LightOccluder2DEditor::_ensure_occluder() const {
return occluder;
}

Node2D *LightOccluder2DEditor::_get_node() const {
CanvasItem *LightOccluder2DEditor::_get_node() const {
return node;
}

Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/light_occluder_2d_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class LightOccluder2DEditor : public AbstractPolygon2DEditor {
Ref<OccluderPolygon2D> _ensure_occluder() const;

protected:
virtual Node2D *_get_node() const override;
virtual CanvasItem *_get_node() const override;
virtual void _set_node(Node *p_polygon) override;

virtual bool _is_line() const override;
Expand Down
4 changes: 2 additions & 2 deletions editor/plugins/line_2d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "editor/editor_node.h"
#include "editor/editor_undo_redo_manager.h"

Node2D *Line2DEditor::_get_node() const {
CanvasItem *Line2DEditor::_get_node() const {
return node;
}

Expand All @@ -54,7 +54,7 @@ void Line2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const {
}

void Line2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) {
Node2D *_node = _get_node();
CanvasItem *_node = _get_node();
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
undo_redo->add_do_method(_node, "set_points", p_polygon);
undo_redo->add_undo_method(_node, "set_points", p_previous);
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/line_2d_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Line2DEditor : public AbstractPolygon2DEditor {
Line2D *node = nullptr;

protected:
virtual Node2D *_get_node() const override;
virtual CanvasItem *_get_node() const override;
virtual void _set_node(Node *p_line) override;

virtual bool _is_line() const override;
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/navigation_obstacle_2d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "editor/editor_node.h"
#include "editor/editor_undo_redo_manager.h"

Node2D *NavigationObstacle2DEditor::_get_node() const {
CanvasItem *NavigationObstacle2DEditor::_get_node() const {
return node;
}

Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/navigation_obstacle_2d_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class NavigationObstacle2DEditor : public AbstractPolygon2DEditor {
NavigationObstacle2D *node = nullptr;

protected:
virtual Node2D *_get_node() const override;
virtual CanvasItem *_get_node() const override;
virtual void _set_node(Node *p_polygon) override;

virtual void _action_add_polygon(const Variant &p_polygon) override;
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/navigation_polygon_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Ref<NavigationPolygon> NavigationPolygonEditor::_ensure_navpoly() const {
return navpoly;
}

Node2D *NavigationPolygonEditor::_get_node() const {
CanvasItem *NavigationPolygonEditor::_get_node() const {
return node;
}

Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/navigation_polygon_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class NavigationPolygonEditor : public AbstractPolygon2DEditor {
protected:
void _notification(int p_what);

virtual Node2D *_get_node() const override;
virtual CanvasItem *_get_node() const override;
virtual void _set_node(Node *p_polygon) override;

virtual int _get_polygon_count() const override;
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/polygon_2d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
#include "scene/gui/texture_rect.h"
#include "scene/gui/view_panner.h"

Node2D *Polygon2DEditor::_get_node() const {
CanvasItem *Polygon2DEditor::_get_node() const {
return node;
}

Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/polygon_2d_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
int _get_polygon_count() const override;

protected:
virtual Node2D *_get_node() const override;
virtual CanvasItem *_get_node() const override;
virtual void _set_node(Node *p_polygon) override;

virtual Vector2 _get_offset(int p_idx) const override;
Expand Down
Loading