| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |  *    list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |  *    this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |  *    and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
					
						
							|  |  |  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
					
						
							|  |  |  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
					
						
							|  |  |  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
					
						
							|  |  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | #include <AK/Assertions.h>
 | 
					
						
							| 
									
										
										
										
											2019-08-18 20:39:46 +02:00
										 |  |  | #include <AK/JsonObject.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 20:33:02 +01:00
										 |  |  | #include <LibGUI/Action.h>
 | 
					
						
							|  |  |  | #include <LibGUI/Application.h>
 | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  | #include <LibGUI/BoxLayout.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 20:33:02 +01:00
										 |  |  | #include <LibGUI/Event.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-20 11:47:44 +01:00
										 |  |  | #include <LibGUI/GMLParser.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 20:33:02 +01:00
										 |  |  | #include <LibGUI/Layout.h>
 | 
					
						
							|  |  |  | #include <LibGUI/Menu.h>
 | 
					
						
							|  |  |  | #include <LibGUI/Painter.h>
 | 
					
						
							|  |  |  | #include <LibGUI/Widget.h>
 | 
					
						
							|  |  |  | #include <LibGUI/Window.h>
 | 
					
						
							|  |  |  | #include <LibGUI/WindowServerConnection.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-13 21:43:32 +01:00
										 |  |  | #include <LibGfx/Bitmap.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-15 00:24:14 +01:00
										 |  |  | #include <LibGfx/Font.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-29 18:25:13 +01:00
										 |  |  | #include <LibGfx/FontDatabase.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-13 21:43:32 +01:00
										 |  |  | #include <LibGfx/Palette.h>
 | 
					
						
							| 
									
										
										
										
											2019-12-24 20:57:54 +01:00
										 |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2019-11-10 10:58:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 09:56:00 +02:00
										 |  |  | REGISTER_WIDGET(GUI, Widget) | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 16:30:13 -07:00
										 |  |  | namespace GUI { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | static HashMap<String, WidgetClassRegistration*>& widget_classes() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static HashMap<String, WidgetClassRegistration*>* map; | 
					
						
							| 
									
										
										
										
											2019-11-10 10:58:03 +01:00
										 |  |  |     if (!map) | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |         map = new HashMap<String, WidgetClassRegistration*>; | 
					
						
							| 
									
										
										
										
											2019-11-10 10:58:03 +01:00
										 |  |  |     return *map; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-23 12:07:13 +01:00
										 |  |  | WidgetClassRegistration::WidgetClassRegistration(const String& class_name, Function<NonnullRefPtr<Widget>()> factory) | 
					
						
							| 
									
										
										
										
											2019-11-10 10:58:03 +01:00
										 |  |  |     : m_class_name(class_name) | 
					
						
							|  |  |  |     , m_factory(move(factory)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     widget_classes().set(class_name, this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | WidgetClassRegistration::~WidgetClassRegistration() | 
					
						
							| 
									
										
										
										
											2019-11-10 10:58:03 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void WidgetClassRegistration::for_each(Function<void(const WidgetClassRegistration&)> callback) | 
					
						
							| 
									
										
										
										
											2019-11-10 10:58:03 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     for (auto& it : widget_classes()) { | 
					
						
							|  |  |  |         callback(*it.value); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | const WidgetClassRegistration* WidgetClassRegistration::find(const String& class_name) | 
					
						
							| 
									
										
										
										
											2019-11-10 10:58:03 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return widget_classes().get(class_name).value_or(nullptr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-23 12:07:13 +01:00
										 |  |  | Widget::Widget() | 
					
						
							| 
									
										
										
										
											2021-01-01 16:02:16 +01:00
										 |  |  |     : Core::Object(nullptr) | 
					
						
							| 
									
										
										
										
											2020-02-14 23:53:11 +01:00
										 |  |  |     , m_background_role(Gfx::ColorRole::Window) | 
					
						
							|  |  |  |     , m_foreground_role(Gfx::ColorRole::WindowText) | 
					
						
							| 
									
										
										
										
											2020-12-29 18:25:13 +01:00
										 |  |  |     , m_font(Gfx::FontDatabase::default_font()) | 
					
						
							| 
									
										
										
										
											2020-07-04 16:52:01 +02:00
										 |  |  |     , m_palette(Application::the()->palette().impl()) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-15 21:33:37 +02:00
										 |  |  |     REGISTER_RECT_PROPERTY("relative_rect", relative_rect, set_relative_rect); | 
					
						
							|  |  |  |     REGISTER_BOOL_PROPERTY("fill_with_background_color", fill_with_background_color, set_fill_with_background_color); | 
					
						
							|  |  |  |     REGISTER_BOOL_PROPERTY("visible", is_visible, set_visible); | 
					
						
							|  |  |  |     REGISTER_BOOL_PROPERTY("focused", is_focused, set_focus); | 
					
						
							|  |  |  |     REGISTER_BOOL_PROPERTY("enabled", is_enabled, set_enabled); | 
					
						
							|  |  |  |     REGISTER_STRING_PROPERTY("tooltip", tooltip, set_tooltip); | 
					
						
							| 
									
										
										
										
											2020-12-07 19:46:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-29 18:22:51 +01:00
										 |  |  |     REGISTER_SIZE_PROPERTY("min_size", min_size, set_min_size); | 
					
						
							|  |  |  |     REGISTER_SIZE_PROPERTY("max_size", max_size, set_max_size); | 
					
						
							| 
									
										
										
										
											2021-01-02 17:27:15 -05:00
										 |  |  |     REGISTER_INT_PROPERTY("width", width, set_width); | 
					
						
							| 
									
										
										
										
											2020-12-29 18:22:51 +01:00
										 |  |  |     REGISTER_INT_PROPERTY("min_width", min_width, set_min_width); | 
					
						
							|  |  |  |     REGISTER_INT_PROPERTY("max_width", max_width, set_max_width); | 
					
						
							|  |  |  |     REGISTER_INT_PROPERTY("min_height", min_height, set_min_height); | 
					
						
							| 
									
										
										
										
											2021-01-02 17:27:15 -05:00
										 |  |  |     REGISTER_INT_PROPERTY("height", height, set_height); | 
					
						
							| 
									
										
										
										
											2020-12-29 18:22:51 +01:00
										 |  |  |     REGISTER_INT_PROPERTY("max_height", max_height, set_max_height); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-29 18:46:42 +01:00
										 |  |  |     REGISTER_INT_PROPERTY("fixed_width", dummy_fixed_width, set_fixed_width); | 
					
						
							|  |  |  |     REGISTER_INT_PROPERTY("fixed_height", dummy_fixed_height, set_fixed_height); | 
					
						
							|  |  |  |     REGISTER_SIZE_PROPERTY("fixed_size", dummy_fixed_size, set_fixed_size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 18:17:14 +01:00
										 |  |  |     REGISTER_BOOL_PROPERTY("shrink_to_fit", is_shrink_to_fit, set_shrink_to_fit); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 17:27:15 -05:00
										 |  |  |     REGISTER_INT_PROPERTY("x", x, set_x); | 
					
						
							|  |  |  |     REGISTER_INT_PROPERTY("y", y, set_y); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 19:46:34 +01:00
										 |  |  |     register_property( | 
					
						
							|  |  |  |         "focus_policy", [this]() -> JsonValue { | 
					
						
							|  |  |  |         auto policy = focus_policy(); | 
					
						
							|  |  |  |         if (policy == GUI::FocusPolicy::ClickFocus) | 
					
						
							|  |  |  |             return "ClickFocus"; | 
					
						
							|  |  |  |         if (policy == GUI::FocusPolicy::NoFocus) | 
					
						
							|  |  |  |             return "NoFocus"; | 
					
						
							|  |  |  |         if (policy == GUI::FocusPolicy::TabFocus) | 
					
						
							|  |  |  |             return "TabFocus"; | 
					
						
							|  |  |  |         if (policy == GUI::FocusPolicy::StrongFocus) | 
					
						
							|  |  |  |             return "StrongFocus"; | 
					
						
							|  |  |  |         return JsonValue(); }, | 
					
						
							|  |  |  |         [this](auto& value) { | 
					
						
							|  |  |  |             if (!value.is_string()) | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             if (value.as_string() == "ClickFocus") { | 
					
						
							|  |  |  |                 set_focus_policy(GUI::FocusPolicy::ClickFocus); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (value.as_string() == "NoFocus") { | 
					
						
							|  |  |  |                 set_focus_policy(GUI::FocusPolicy::NoFocus); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (value.as_string() == "TabFocus") { | 
					
						
							|  |  |  |                 set_focus_policy(GUI::FocusPolicy::TabFocus); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (value.as_string() == "StrongFocus") { | 
					
						
							|  |  |  |                 set_focus_policy(GUI::FocusPolicy::StrongFocus); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-01-02 17:27:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     register_property( | 
					
						
							|  |  |  |         "foreground_color", [this]() -> JsonValue { return palette().color(foreground_role()).to_string(); }, | 
					
						
							|  |  |  |         [this](auto& value) { | 
					
						
							|  |  |  |             auto c = Color::from_string(value.to_string()); | 
					
						
							|  |  |  |             if (c.has_value()) { | 
					
						
							|  |  |  |                 auto _palette = palette(); | 
					
						
							|  |  |  |                 _palette.set_color(foreground_role(), c.value()); | 
					
						
							|  |  |  |                 set_palette(_palette); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     register_property( | 
					
						
							|  |  |  |         "background_color", [this]() -> JsonValue { return palette().color(background_role()).to_string(); }, | 
					
						
							|  |  |  |         [this](auto& value) { | 
					
						
							|  |  |  |             auto c = Color::from_string(value.to_string()); | 
					
						
							|  |  |  |             if (c.has_value()) { | 
					
						
							|  |  |  |                 auto _palette = palette(); | 
					
						
							|  |  |  |                 _palette.set_color(background_role(), c.value()); | 
					
						
							|  |  |  |                 set_palette(_palette); | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | Widget::~Widget() | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::child_event(Core::ChildEvent& event) | 
					
						
							| 
									
										
										
										
											2019-03-15 23:24:40 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     if (event.type() == Event::ChildAdded) { | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |         if (event.child() && is<Widget>(*event.child()) && layout()) { | 
					
						
							| 
									
										
										
										
											2021-01-01 16:02:16 +01:00
										 |  |  |             if (event.insertion_before_child() && is<Widget>(event.insertion_before_child())) | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |                 layout()->insert_widget_before(downcast<Widget>(*event.child()), downcast<Widget>(*event.insertion_before_child())); | 
					
						
							| 
									
										
										
										
											2019-11-05 20:41:27 +01:00
										 |  |  |             else | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |                 layout()->add_widget(downcast<Widget>(*event.child())); | 
					
						
							| 
									
										
										
										
											2019-11-05 20:41:27 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |         if (window() && event.child() && is<Widget>(*event.child())) | 
					
						
							|  |  |  |             window()->did_add_widget({}, downcast<Widget>(*event.child())); | 
					
						
							| 
									
										
										
										
											2019-03-15 23:24:40 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     if (event.type() == Event::ChildRemoved) { | 
					
						
							| 
									
										
										
										
											2019-04-06 21:15:13 +02:00
										 |  |  |         if (layout()) { | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |             if (event.child() && is<Widget>(*event.child())) | 
					
						
							|  |  |  |                 layout()->remove_widget(downcast<Widget>(*event.child())); | 
					
						
							| 
									
										
										
										
											2019-04-06 21:15:13 +02:00
										 |  |  |             else | 
					
						
							|  |  |  |                 invalidate_layout(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |         if (window() && event.child() && is<Widget>(*event.child())) | 
					
						
							|  |  |  |             window()->did_remove_widget({}, downcast<Widget>(*event.child())); | 
					
						
							| 
									
										
										
										
											2019-04-18 23:25:30 +02:00
										 |  |  |         update(); | 
					
						
							| 
									
										
										
										
											2019-04-04 01:44:35 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     return Core::Object::child_event(event); | 
					
						
							| 
									
										
										
										
											2019-03-15 23:24:40 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  | void Widget::set_relative_rect(const Gfx::IntRect& a_rect) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-10 12:53:05 +01:00
										 |  |  |     // Get rid of negative width/height values.
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  |     Gfx::IntRect rect = { | 
					
						
							| 
									
										
										
										
											2019-11-10 12:53:05 +01:00
										 |  |  |         a_rect.x(), | 
					
						
							|  |  |  |         a_rect.y(), | 
					
						
							|  |  |  |         max(a_rect.width(), 0), | 
					
						
							|  |  |  |         max(a_rect.height(), 0) | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2019-10-23 19:51:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-24 23:40:12 +01:00
										 |  |  |     if (rect == m_relative_rect) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-04-16 22:59:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto old_rect = m_relative_rect; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-20 21:59:13 +01:00
										 |  |  |     bool size_changed = m_relative_rect.size() != rect.size(); | 
					
						
							| 
									
										
										
										
											2019-01-21 00:46:08 +01:00
										 |  |  |     m_relative_rect = rect; | 
					
						
							| 
									
										
										
										
											2019-02-20 21:59:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (size_changed) { | 
					
						
							| 
									
										
										
										
											2020-08-22 13:10:35 +02:00
										 |  |  |         ResizeEvent resize_event(rect.size()); | 
					
						
							| 
									
										
										
										
											2019-02-20 21:59:13 +01:00
										 |  |  |         event(resize_event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-16 22:59:27 +02:00
										 |  |  |     if (auto* parent = parent_widget()) | 
					
						
							|  |  |  |         parent->update(old_rect); | 
					
						
							| 
									
										
										
										
											2019-01-24 23:40:12 +01:00
										 |  |  |     update(); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::event(Core::Event& event) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-04 23:47:27 +01:00
										 |  |  |     if (!is_enabled()) { | 
					
						
							|  |  |  |         switch (event.type()) { | 
					
						
							|  |  |  |         case Event::MouseUp: | 
					
						
							|  |  |  |         case Event::MouseDown: | 
					
						
							|  |  |  |         case Event::MouseMove: | 
					
						
							|  |  |  |         case Event::MouseWheel: | 
					
						
							|  |  |  |         case Event::MouseDoubleClick: | 
					
						
							|  |  |  |         case Event::KeyUp: | 
					
						
							|  |  |  |         case Event::KeyDown: | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |     switch (event.type()) { | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     case Event::Paint: | 
					
						
							|  |  |  |         return handle_paint_event(static_cast<PaintEvent&>(event)); | 
					
						
							|  |  |  |     case Event::Resize: | 
					
						
							|  |  |  |         return handle_resize_event(static_cast<ResizeEvent&>(event)); | 
					
						
							|  |  |  |     case Event::FocusIn: | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |         return focusin_event(static_cast<FocusEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     case Event::FocusOut: | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |         return focusout_event(static_cast<FocusEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     case Event::Show: | 
					
						
							|  |  |  |         return show_event(static_cast<ShowEvent&>(event)); | 
					
						
							|  |  |  |     case Event::Hide: | 
					
						
							|  |  |  |         return hide_event(static_cast<HideEvent&>(event)); | 
					
						
							|  |  |  |     case Event::KeyDown: | 
					
						
							|  |  |  |         return keydown_event(static_cast<KeyEvent&>(event)); | 
					
						
							|  |  |  |     case Event::KeyUp: | 
					
						
							|  |  |  |         return keyup_event(static_cast<KeyEvent&>(event)); | 
					
						
							|  |  |  |     case Event::MouseMove: | 
					
						
							|  |  |  |         return mousemove_event(static_cast<MouseEvent&>(event)); | 
					
						
							|  |  |  |     case Event::MouseDown: | 
					
						
							|  |  |  |         return handle_mousedown_event(static_cast<MouseEvent&>(event)); | 
					
						
							|  |  |  |     case Event::MouseDoubleClick: | 
					
						
							|  |  |  |         return handle_mousedoubleclick_event(static_cast<MouseEvent&>(event)); | 
					
						
							|  |  |  |     case Event::MouseUp: | 
					
						
							|  |  |  |         return handle_mouseup_event(static_cast<MouseEvent&>(event)); | 
					
						
							|  |  |  |     case Event::MouseWheel: | 
					
						
							|  |  |  |         return mousewheel_event(static_cast<MouseEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2021-01-08 22:23:06 +01:00
										 |  |  |     case Event::DragEnter: | 
					
						
							|  |  |  |         return drag_enter_event(static_cast<DragEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2020-02-13 21:43:32 +01:00
										 |  |  |     case Event::DragMove: | 
					
						
							|  |  |  |         return drag_move_event(static_cast<DragEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2021-01-08 22:23:06 +01:00
										 |  |  |     case Event::DragLeave: | 
					
						
							|  |  |  |         return drag_leave_event(static_cast<Event&>(event)); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     case Event::Drop: | 
					
						
							|  |  |  |         return drop_event(static_cast<DropEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2020-03-16 13:36:21 +02:00
										 |  |  |     case Event::ThemeChange: | 
					
						
							|  |  |  |         return theme_change_event(static_cast<ThemeChangeEvent&>(event)); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     case Event::Enter: | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  |         return handle_enter_event(event); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     case Event::Leave: | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  |         return handle_leave_event(event); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     case Event::EnabledChange: | 
					
						
							|  |  |  |         return change_event(static_cast<Event&>(event)); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |         return Core::Object::event(event); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::handle_paint_event(PaintEvent& event) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-03-25 13:58:30 +01:00
										 |  |  |     ASSERT(is_visible()); | 
					
						
							| 
									
										
										
										
											2019-01-21 00:46:08 +01:00
										 |  |  |     if (fill_with_background_color()) { | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |         Painter painter(*this); | 
					
						
							| 
									
										
										
										
											2019-12-24 20:57:54 +01:00
										 |  |  |         painter.fill_rect(event.rect(), palette().color(background_role())); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-02-09 11:19:38 +01:00
										 |  |  |     paint_event(event); | 
					
						
							| 
									
										
										
										
											2020-08-25 21:24:45 +02:00
										 |  |  |     auto children_clip_rect = this->children_clip_rect(); | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:02 +02:00
										 |  |  |     for_each_child_widget([&](auto& child) { | 
					
						
							| 
									
										
										
										
											2019-05-27 03:52:33 +02:00
										 |  |  |         if (!child.is_visible()) | 
					
						
							|  |  |  |             return IterationDecision::Continue; | 
					
						
							|  |  |  |         if (child.relative_rect().intersects(event.rect())) { | 
					
						
							| 
									
										
										
										
											2020-08-25 21:24:45 +02:00
										 |  |  |             PaintEvent local_event(event.rect().intersected(children_clip_rect).intersected(child.relative_rect()).translated(-child.relative_position())); | 
					
						
							| 
									
										
										
										
											2019-09-20 20:37:31 +02:00
										 |  |  |             child.dispatch_event(local_event, this); | 
					
						
							| 
									
										
										
										
											2019-02-02 08:05:14 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-05-27 03:52:33 +02:00
										 |  |  |         return IterationDecision::Continue; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-04-11 03:34:37 +02:00
										 |  |  |     second_paint_event(event); | 
					
						
							| 
									
										
										
										
											2020-03-05 14:42:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 00:11:17 +01:00
										 |  |  |     auto* app = Application::the(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (app && app->dnd_debugging_enabled() && has_pending_drop()) { | 
					
						
							| 
									
										
										
										
											2020-03-05 14:42:05 +01:00
										 |  |  |         Painter painter(*this); | 
					
						
							| 
									
										
										
										
											2021-01-09 00:11:17 +01:00
										 |  |  |         painter.draw_rect(rect(), Color::Blue); | 
					
						
							| 
									
										
										
										
											2020-03-05 14:42:05 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-12 15:47:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 00:11:17 +01:00
										 |  |  |     if (app && app->focus_debugging_enabled() && is_focused()) { | 
					
						
							|  |  |  |         Painter painter(*this); | 
					
						
							|  |  |  |         painter.draw_rect(rect(), Color::Cyan); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_being_inspected()) { | 
					
						
							|  |  |  |         Painter painter(*this); | 
					
						
							|  |  |  |         painter.draw_rect(rect(), Color::Magenta); | 
					
						
							| 
									
										
										
										
											2020-05-12 15:47:13 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-05 09:21:46 +01:00
										 |  |  | void Widget::set_layout(NonnullRefPtr<Layout> layout) | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-05 09:21:46 +01:00
										 |  |  |     if (m_layout) { | 
					
						
							| 
									
										
										
										
											2019-05-31 15:44:04 +02:00
										 |  |  |         m_layout->notify_disowned({}, *this); | 
					
						
							| 
									
										
										
										
											2020-03-05 09:21:46 +01:00
										 |  |  |         m_layout->remove_from_parent(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  |     m_layout = move(layout); | 
					
						
							|  |  |  |     if (m_layout) { | 
					
						
							| 
									
										
										
										
											2020-03-05 09:21:46 +01:00
										 |  |  |         add_child(*m_layout); | 
					
						
							| 
									
										
										
										
											2019-05-31 15:44:04 +02:00
										 |  |  |         m_layout->notify_adopted({}, *this); | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  |         do_layout(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         update(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::do_layout() | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-26 12:27:01 +02:00
										 |  |  |     for_each_child_widget([&](auto& child) { | 
					
						
							|  |  |  |         child.do_layout(); | 
					
						
							|  |  |  |         return IterationDecision::Continue; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-09-01 20:51:20 +02:00
										 |  |  |     custom_layout(); | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  |     if (!m_layout) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_layout->run(*this); | 
					
						
							| 
									
										
										
										
											2020-02-11 11:26:25 +01:00
										 |  |  |     did_layout(); | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  |     update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::notify_layout_changed(Badge<Layout>) | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-18 22:57:24 +02:00
										 |  |  |     invalidate_layout(); | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::handle_resize_event(ResizeEvent& event) | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-30 00:26:19 +01:00
										 |  |  |     resize_event(event); | 
					
						
							| 
									
										
										
										
											2019-09-01 20:51:20 +02:00
										 |  |  |     do_layout(); | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::handle_mouseup_event(MouseEvent& event) | 
					
						
							| 
									
										
										
										
											2019-03-25 01:42:15 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     mouseup_event(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::handle_mousedown_event(MouseEvent& event) | 
					
						
							| 
									
										
										
										
											2019-04-01 22:03:32 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-30 10:58:27 +01:00
										 |  |  |     if (((unsigned)focus_policy() & (unsigned)FocusPolicy::ClickFocus)) | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |         set_focus(true, FocusSource::Mouse); | 
					
						
							| 
									
										
										
										
											2019-04-01 22:03:32 +02:00
										 |  |  |     mousedown_event(event); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     if (event.button() == MouseButton::Right) { | 
					
						
							|  |  |  |         ContextMenuEvent c_event(event.position(), screen_relative_rect().location().translated(event.position())); | 
					
						
							| 
									
										
										
										
											2019-04-18 04:12:27 +02:00
										 |  |  |         context_menu_event(c_event); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-01 22:03:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::handle_mousedoubleclick_event(MouseEvent& event) | 
					
						
							| 
									
										
										
										
											2019-05-15 22:17:09 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     doubleclick_event(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::handle_enter_event(Core::Event& event) | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-03 19:43:46 +02:00
										 |  |  |     if (auto* window = this->window()) | 
					
						
							|  |  |  |         window->update_cursor({}); | 
					
						
							| 
									
										
										
										
											2021-01-03 17:21:12 +01:00
										 |  |  |     show_or_hide_tooltip(); | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  |     enter_event(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::handle_leave_event(Core::Event& event) | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-03 19:43:46 +02:00
										 |  |  |     if (auto* window = this->window()) | 
					
						
							|  |  |  |         window->update_cursor({}); | 
					
						
							| 
									
										
										
										
											2020-07-04 16:52:01 +02:00
										 |  |  |     Application::the()->hide_tooltip(); | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  |     leave_event(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::doubleclick_event(MouseEvent&) | 
					
						
							| 
									
										
										
										
											2019-03-25 01:42:15 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::resize_event(ResizeEvent&) | 
					
						
							| 
									
										
										
										
											2019-02-09 11:19:38 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::paint_event(PaintEvent&) | 
					
						
							| 
									
										
										
										
											2019-02-09 11:19:38 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::second_paint_event(PaintEvent&) | 
					
						
							| 
									
										
										
										
											2019-04-11 03:34:37 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::show_event(ShowEvent&) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::hide_event(HideEvent&) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::keydown_event(KeyEvent& event) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-02 01:54:30 +01:00
										 |  |  |     if (!event.alt() && !event.ctrl() && !event.logo()) { | 
					
						
							|  |  |  |         if (event.key() == KeyCode::Key_Tab) { | 
					
						
							|  |  |  |             if (event.shift()) | 
					
						
							|  |  |  |                 focus_previous_widget(FocusSource::Keyboard, false); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 focus_next_widget(FocusSource::Keyboard, false); | 
					
						
							|  |  |  |             event.accept(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!event.shift() && (event.key() == KeyCode::Key_Left || event.key() == KeyCode::Key_Up)) { | 
					
						
							|  |  |  |             focus_previous_widget(FocusSource::Keyboard, true); | 
					
						
							|  |  |  |             event.accept(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!event.shift() && (event.key() == KeyCode::Key_Right || event.key() == KeyCode::Key_Down)) { | 
					
						
							|  |  |  |             focus_next_widget(FocusSource::Keyboard, true); | 
					
						
							|  |  |  |             event.accept(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-09-20 20:37:31 +02:00
										 |  |  |     event.ignore(); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-06 13:08:00 -06:00
										 |  |  | void Widget::keyup_event(KeyEvent& event) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-06 13:08:00 -06:00
										 |  |  |     event.ignore(); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::mousedown_event(MouseEvent&) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::mouseup_event(MouseEvent&) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::mousemove_event(MouseEvent&) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::mousewheel_event(MouseEvent&) | 
					
						
							| 
									
										
										
										
											2019-05-13 19:52:57 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::context_menu_event(ContextMenuEvent&) | 
					
						
							| 
									
										
										
										
											2019-04-18 04:12:27 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  | void Widget::focusin_event(FocusEvent&) | 
					
						
							| 
									
										
										
										
											2019-01-26 11:24:16 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  | void Widget::focusout_event(FocusEvent&) | 
					
						
							| 
									
										
										
										
											2019-01-26 11:24:16 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::enter_event(Core::Event&) | 
					
						
							| 
									
										
										
										
											2019-02-20 10:12:19 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::leave_event(Core::Event&) | 
					
						
							| 
									
										
										
										
											2019-02-20 10:12:19 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::change_event(Event&) | 
					
						
							| 
									
										
										
										
											2019-05-25 13:40:57 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 00:11:17 +01:00
										 |  |  | void Widget::drag_move_event(DragEvent&) | 
					
						
							| 
									
										
										
										
											2020-02-13 21:43:32 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-08 22:23:06 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Widget::drag_enter_event(DragEvent& event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-09 11:01:41 +01:00
										 |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     builder.join(',', event.mime_types()); | 
					
						
							|  |  |  |     dbgln("{} {:p} DRAG ENTER @ {}, {}", class_name(), this, event.position(), builder.string_view()); | 
					
						
							| 
									
										
										
										
											2021-01-08 22:23:06 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 00:11:17 +01:00
										 |  |  | void Widget::drag_leave_event(Event&) | 
					
						
							| 
									
										
										
										
											2021-01-08 22:23:06 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     dbgln("{} {:p} DRAG LEAVE", class_name(), this); | 
					
						
							| 
									
										
										
										
											2020-02-13 21:43:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::drop_event(DropEvent& event) | 
					
						
							| 
									
										
										
										
											2019-12-08 16:50:23 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-08 22:23:06 +01:00
										 |  |  |     dbgln("{} {:p} DROP @ {}, '{}'", class_name(), this, event.position(), event.text()); | 
					
						
							| 
									
										
										
										
											2019-12-08 16:50:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-16 13:36:21 +02:00
										 |  |  | void Widget::theme_change_event(ThemeChangeEvent&) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::update() | 
					
						
							| 
									
										
										
										
											2019-02-10 14:28:39 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-02 03:46:37 +02:00
										 |  |  |     if (rect().is_empty()) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-02-10 14:28:39 +01:00
										 |  |  |     update(rect()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  | void Widget::update(const Gfx::IntRect& rect) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-03-25 13:58:30 +01:00
										 |  |  |     if (!is_visible()) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-05-02 03:46:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-02 04:19:59 +02:00
										 |  |  |     if (!updates_enabled()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     Window* window = m_window; | 
					
						
							|  |  |  |     Widget* parent = parent_widget(); | 
					
						
							| 
									
										
										
										
											2019-05-02 03:46:37 +02:00
										 |  |  |     while (parent) { | 
					
						
							|  |  |  |         if (!parent->updates_enabled()) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         window = parent->m_window; | 
					
						
							|  |  |  |         parent = parent->parent_widget(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (window) | 
					
						
							|  |  |  |         window->update(rect.translated(window_relative_rect().location())); | 
					
						
							| 
									
										
										
										
											2019-02-09 14:30:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  | Gfx::IntRect Widget::window_relative_rect() const | 
					
						
							| 
									
										
										
										
											2019-02-09 14:30:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     auto rect = relative_rect(); | 
					
						
							|  |  |  |     for (auto* parent = parent_widget(); parent; parent = parent->parent_widget()) { | 
					
						
							|  |  |  |         rect.move_by(parent->relative_position()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rect; | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  | Gfx::IntRect Widget::screen_relative_rect() const | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-13 21:15:13 +02:00
										 |  |  |     auto window_position = window()->window_type() == WindowType::MenuApplet | 
					
						
							|  |  |  |         ? window()->rect_in_menubar().location() | 
					
						
							|  |  |  |         : window()->rect().location(); | 
					
						
							|  |  |  |     return window_relative_rect().translated(window_position); | 
					
						
							| 
									
										
										
										
											2019-04-08 18:58:44 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  | Widget* Widget::child_at(const Gfx::IntPoint& point) const | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-10 02:08:32 +02:00
										 |  |  |     for (int i = children().size() - 1; i >= 0; --i) { | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |         if (!is<Widget>(children()[i])) | 
					
						
							| 
									
										
										
										
											2019-03-15 16:45:27 +01:00
										 |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2020-07-26 17:16:35 +02:00
										 |  |  |         auto& child = downcast<Widget>(children()[i]); | 
					
						
							| 
									
										
										
										
											2019-03-15 16:45:27 +01:00
										 |  |  |         if (!child.is_visible()) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2020-04-24 18:55:29 +02:00
										 |  |  |         if (child.content_rect().contains(point)) | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |             return const_cast<Widget*>(&child); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  |     return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  | Widget::HitTestResult Widget::hit_test(const Gfx::IntPoint& position, ShouldRespectGreediness should_respect_greediness) | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-17 20:58:13 +02:00
										 |  |  |     if (should_respect_greediness == ShouldRespectGreediness::Yes && is_greedy_for_hits()) | 
					
						
							| 
									
										
										
										
											2019-04-16 13:25:00 +02:00
										 |  |  |         return { this, position }; | 
					
						
							|  |  |  |     if (auto* child = child_at(position)) | 
					
						
							|  |  |  |         return child->hit_test(position - child->relative_position()); | 
					
						
							|  |  |  |     return { this, position }; | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::set_window(Window* window) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_window == window) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_window = window; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 11:21:49 +02:00
										 |  |  | void Widget::set_focus_proxy(Widget* proxy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_focus_proxy == proxy) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												AK: Make RefPtr, NonnullRefPtr, WeakPtr thread safe
This makes most operations thread safe, especially so that they
can safely be used in the Kernel. This includes obtaining a strong
reference from a weak reference, which now requires an explicit
call to WeakPtr::strong_ref(). Another major change is that
Weakable::make_weak_ref() may require the explicit target type.
Previously we used reinterpret_cast in WeakPtr, assuming that it
can be properly converted. But WeakPtr does not necessarily have
the knowledge to be able to do this. Instead, we now ask the class
itself to deliver a WeakPtr to the type that we want.
Also, WeakLink is no longer specific to a target type. The reason
for this is that we want to be able to safely convert e.g. WeakPtr<T>
to WeakPtr<U>, and before this we just reinterpret_cast the internal
WeakLink<T> to WeakLink<U>, which is a bold assumption that it would
actually produce the correct code. Instead, WeakLink now operates
on just a raw pointer and we only make those constructors/operators
available if we can verify that it can be safely cast.
In order to guarantee thread safety, we now use the least significant
bit in the pointer for locking purposes. This also means that only
properly aligned pointers can be used.
											
										 
											2020-09-29 16:26:13 -06:00
										 |  |  |     m_focus_proxy = proxy; | 
					
						
							| 
									
										
										
										
											2020-08-25 11:21:49 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 10:58:27 +01:00
										 |  |  | FocusPolicy Widget::focus_policy() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_focus_proxy) | 
					
						
							|  |  |  |         return m_focus_proxy->focus_policy(); | 
					
						
							|  |  |  |     return m_focus_policy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Widget::set_focus_policy(FocusPolicy policy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_focus_proxy) | 
					
						
							|  |  |  |         return m_focus_proxy->set_focus_policy(policy); | 
					
						
							|  |  |  |     m_focus_policy = policy; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | bool Widget::is_focused() const | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-25 11:21:49 +02:00
										 |  |  |     if (m_focus_proxy) | 
					
						
							|  |  |  |         return m_focus_proxy->is_focused(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 11:24:16 +01:00
										 |  |  |     auto* win = window(); | 
					
						
							|  |  |  |     if (!win) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2020-07-14 19:17:00 -06:00
										 |  |  |     // Accessory windows are not active despite being the active
 | 
					
						
							|  |  |  |     // input window. So we can have focus if either we're the active
 | 
					
						
							|  |  |  |     // input window or we're the active window
 | 
					
						
							|  |  |  |     if (win->is_active_input() || win->is_active()) | 
					
						
							|  |  |  |         return win->focused_widget() == this; | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  | void Widget::set_focus(bool focus, FocusSource source) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-25 11:21:49 +02:00
										 |  |  |     if (m_focus_proxy) | 
					
						
							|  |  |  |         return m_focus_proxy->set_focus(focus, source); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-26 11:24:16 +01:00
										 |  |  |     auto* win = window(); | 
					
						
							|  |  |  |     if (!win) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-01-26 11:24:16 +01:00
										 |  |  |     if (focus) { | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |         win->set_focused_widget(this, source); | 
					
						
							| 
									
										
										
										
											2019-01-26 11:24:16 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         if (win->focused_widget() == this) | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |             win->set_focused_widget(nullptr, source); | 
					
						
							| 
									
										
										
										
											2019-01-26 11:24:16 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 11:56:38 +01:00
										 |  |  | void Widget::set_font(const Gfx::Font* font) | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-01 12:26:35 +02:00
										 |  |  |     if (m_font.ptr() == font) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |     if (!font) | 
					
						
							| 
									
										
										
										
											2020-12-29 18:25:13 +01:00
										 |  |  |         m_font = Gfx::FontDatabase::default_font(); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2019-09-01 12:26:35 +02:00
										 |  |  |         m_font = *font; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     did_change_font(); | 
					
						
							| 
									
										
										
										
											2019-02-12 10:08:35 +01:00
										 |  |  |     update(); | 
					
						
							| 
									
										
										
										
											2019-01-20 04:49:48 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-01-27 08:48:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::set_global_cursor_tracking(bool enabled) | 
					
						
							| 
									
										
										
										
											2019-01-27 08:48:34 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     auto* win = window(); | 
					
						
							|  |  |  |     if (!win) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     win->set_global_cursor_tracking_widget(enabled ? this : nullptr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | bool Widget::global_cursor_tracking() const | 
					
						
							| 
									
										
										
										
											2019-01-27 08:48:34 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     auto* win = window(); | 
					
						
							|  |  |  |     if (!win) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     return win->global_cursor_tracking_widget() == this; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-29 18:22:51 +01:00
										 |  |  | void Widget::set_min_size(const Gfx::IntSize& size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_min_size == size) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_min_size = size; | 
					
						
							|  |  |  |     invalidate_layout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Widget::set_max_size(const Gfx::IntSize& size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_max_size == size) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_max_size = size; | 
					
						
							|  |  |  |     invalidate_layout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::invalidate_layout() | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-26 12:27:01 +02:00
										 |  |  |     if (window()) | 
					
						
							|  |  |  |         window()->schedule_relayout(); | 
					
						
							| 
									
										
										
										
											2019-02-10 11:07:13 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-15 16:12:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::set_visible(bool visible) | 
					
						
							| 
									
										
										
										
											2019-03-15 16:12:06 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (visible == m_visible) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_visible = visible; | 
					
						
							|  |  |  |     if (auto* parent = parent_widget()) | 
					
						
							|  |  |  |         parent->invalidate_layout(); | 
					
						
							|  |  |  |     if (m_visible) | 
					
						
							|  |  |  |         update(); | 
					
						
							| 
									
										
										
										
											2019-10-02 20:24:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_visible) { | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |         ShowEvent e; | 
					
						
							| 
									
										
										
										
											2019-10-02 20:24:03 +02:00
										 |  |  |         event(e); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |         HideEvent e; | 
					
						
							| 
									
										
										
										
											2019-10-02 20:24:03 +02:00
										 |  |  |         event(e); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-03-15 16:12:06 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-29 02:20:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | bool Widget::spans_entire_window_horizontally() const | 
					
						
							| 
									
										
										
										
											2019-03-29 02:20:22 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     auto* w = window(); | 
					
						
							|  |  |  |     if (!w) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     auto* main_widget = w->main_widget(); | 
					
						
							|  |  |  |     if (!main_widget) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     if (main_widget == this) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     auto wrr = window_relative_rect(); | 
					
						
							|  |  |  |     return wrr.left() == main_widget->rect().left() && wrr.right() == main_widget->rect().right(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-12 02:51:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::set_enabled(bool enabled) | 
					
						
							| 
									
										
										
										
											2019-04-12 02:51:16 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_enabled == enabled) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_enabled = enabled; | 
					
						
							| 
									
										
										
										
											2020-05-08 13:49:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for_each_child_widget([enabled](auto& child) { | 
					
						
							|  |  |  |         child.set_enabled(enabled); | 
					
						
							|  |  |  |         return IterationDecision::Continue; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 00:33:46 +01:00
										 |  |  |     if (!m_enabled && window() && window()->focused_widget() == this) { | 
					
						
							|  |  |  |         window()->did_disable_focused_widget({}); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     Event e(Event::EnabledChange); | 
					
						
							| 
									
										
										
										
											2019-05-25 13:40:57 +02:00
										 |  |  |     event(e); | 
					
						
							| 
									
										
										
										
											2019-04-12 02:51:16 +02:00
										 |  |  |     update(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-12 17:10:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::move_to_front() | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     auto* parent = parent_widget(); | 
					
						
							|  |  |  |     if (!parent) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (parent->children().size() == 1) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:02 +02:00
										 |  |  |     parent->children().remove_first_matching([this](auto& entry) { | 
					
						
							| 
									
										
										
										
											2019-04-16 04:01:14 +02:00
										 |  |  |         return entry == this; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  |     parent->children().append(*this); | 
					
						
							| 
									
										
										
										
											2019-04-16 04:01:14 +02:00
										 |  |  |     parent->update(); | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::move_to_back() | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     auto* parent = parent_widget(); | 
					
						
							|  |  |  |     if (!parent) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (parent->children().size() == 1) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:02 +02:00
										 |  |  |     parent->children().remove_first_matching([this](auto& entry) { | 
					
						
							| 
									
										
										
										
											2019-04-16 04:01:14 +02:00
										 |  |  |         return entry == this; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  |     parent->children().prepend(*this); | 
					
						
							| 
									
										
										
										
											2019-04-16 04:01:14 +02:00
										 |  |  |     parent->update(); | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | bool Widget::is_frontmost() const | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     auto* parent = parent_widget(); | 
					
						
							|  |  |  |     if (!parent) | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  |     return &parent->children().last() == this; | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | bool Widget::is_backmost() const | 
					
						
							| 
									
										
										
										
											2019-04-16 03:47:55 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     auto* parent = parent_widget(); | 
					
						
							|  |  |  |     if (!parent) | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2019-09-22 00:17:53 +02:00
										 |  |  |     return &parent->children().first() == this; | 
					
						
							| 
									
										
										
										
											2019-04-12 17:10:30 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-20 21:56:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | Action* Widget::action_for_key_event(const KeyEvent& event) | 
					
						
							| 
									
										
										
										
											2019-04-20 21:56:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     Shortcut shortcut(event.modifiers(), (KeyCode)event.key()); | 
					
						
							| 
									
										
										
										
											2020-11-23 18:41:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!shortcut.is_valid()) { | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     Action* found_action = nullptr; | 
					
						
							|  |  |  |     for_each_child_of_type<Action>([&](auto& action) { | 
					
						
							| 
									
										
										
										
											2020-02-02 01:57:57 +01:00
										 |  |  |         if (action.shortcut() == shortcut) { | 
					
						
							|  |  |  |             found_action = &action; | 
					
						
							|  |  |  |             return IterationDecision::Break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return IterationDecision::Continue; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     return found_action; | 
					
						
							| 
									
										
										
										
											2019-04-20 21:56:56 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-02 03:46:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::set_updates_enabled(bool enabled) | 
					
						
							| 
									
										
										
										
											2019-05-02 03:46:37 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_updates_enabled == enabled) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_updates_enabled = enabled; | 
					
						
							|  |  |  |     if (enabled) | 
					
						
							|  |  |  |         update(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 01:54:30 +01:00
										 |  |  | void Widget::focus_previous_widget(FocusSource source, bool siblings_only) | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-30 10:58:27 +01:00
										 |  |  |     auto focusable_widgets = window()->focusable_widgets(source); | 
					
						
							| 
									
										
										
										
											2021-01-02 01:54:30 +01:00
										 |  |  |     if (siblings_only) | 
					
						
							|  |  |  |         focusable_widgets.remove_all_matching([this](auto& entry) { return entry->parent() != parent(); }); | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  |     for (int i = focusable_widgets.size() - 1; i >= 0; --i) { | 
					
						
							|  |  |  |         if (focusable_widgets[i] != this) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         if (i > 0) | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |             focusable_widgets[i - 1]->set_focus(true, source); | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |             focusable_widgets.last()->set_focus(true, source); | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 01:54:30 +01:00
										 |  |  | void Widget::focus_next_widget(FocusSource source, bool siblings_only) | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-30 10:58:27 +01:00
										 |  |  |     auto focusable_widgets = window()->focusable_widgets(source); | 
					
						
							| 
									
										
										
										
											2021-01-02 01:54:30 +01:00
										 |  |  |     if (siblings_only) | 
					
						
							|  |  |  |         focusable_widgets.remove_all_matching([this](auto& entry) { return entry->parent() != parent(); }); | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |     for (size_t i = 0; i < focusable_widgets.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  |         if (focusable_widgets[i] != this) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         if (i < focusable_widgets.size() - 1) | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |             focusable_widgets[i + 1]->set_focus(true, source); | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2020-08-14 19:56:40 +02:00
										 |  |  |             focusable_widgets.first()->set_focus(true, source); | 
					
						
							| 
									
										
										
										
											2019-05-15 02:39:58 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-08-03 11:35:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | Vector<Widget*> Widget::child_widgets() const | 
					
						
							| 
									
										
										
										
											2019-11-11 19:12:32 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     Vector<Widget*> widgets; | 
					
						
							| 
									
										
										
										
											2019-11-11 19:12:32 +01:00
										 |  |  |     widgets.ensure_capacity(children().size()); | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |     for (auto& child : const_cast<Widget*>(this)->children()) { | 
					
						
							| 
									
										
										
										
											2021-01-01 16:02:16 +01:00
										 |  |  |         if (is<Widget>(child)) | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  |             widgets.append(static_cast<Widget*>(&child)); | 
					
						
							| 
									
										
										
										
											2019-11-11 19:12:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return widgets; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-12-24 20:57:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | void Widget::set_palette(const Palette& palette) | 
					
						
							| 
									
										
										
										
											2019-12-24 20:57:54 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-29 00:47:49 +01:00
										 |  |  |     m_palette = palette.impl(); | 
					
						
							| 
									
										
										
										
											2019-12-24 20:57:54 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 23:53:11 +01:00
										 |  |  | void Widget::set_background_role(ColorRole role) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_background_role = role; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Widget::set_foreground_role(ColorRole role) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_foreground_role = role; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Gfx::Palette Widget::palette() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return Gfx::Palette(*m_palette); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-05 14:42:05 +01:00
										 |  |  | void Widget::did_begin_inspection() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Widget::did_end_inspection() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 18:55:29 +02:00
										 |  |  | void Widget::set_content_margins(const Margins& margins) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_content_margins == margins) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_content_margins = margins; | 
					
						
							|  |  |  |     invalidate_layout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:57:59 +02:00
										 |  |  | Gfx::IntRect Widget::content_rect() const | 
					
						
							| 
									
										
										
										
											2020-04-24 18:55:29 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     auto rect = relative_rect(); | 
					
						
							|  |  |  |     rect.move_by(m_content_margins.left(), m_content_margins.top()); | 
					
						
							|  |  |  |     rect.set_width(rect.width() - (m_content_margins.left() + m_content_margins.right())); | 
					
						
							|  |  |  |     rect.set_height(rect.height() - (m_content_margins.top() + m_content_margins.bottom())); | 
					
						
							|  |  |  |     return rect; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-15 11:44:34 +02:00
										 |  |  | void Widget::set_tooltip(const StringView& tooltip) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_tooltip = tooltip; | 
					
						
							| 
									
										
										
										
											2021-01-03 17:21:12 +01:00
										 |  |  |     if (Application::the()->tooltip_source_widget() == this) | 
					
						
							|  |  |  |         show_or_hide_tooltip(); | 
					
						
							| 
									
										
										
										
											2020-08-15 11:44:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-03 17:21:12 +01:00
										 |  |  | void Widget::show_or_hide_tooltip() | 
					
						
							| 
									
										
										
										
											2020-08-15 11:44:34 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (has_tooltip()) | 
					
						
							| 
									
										
										
										
											2020-12-28 21:26:47 +01:00
										 |  |  |         Application::the()->show_tooltip(m_tooltip, this); | 
					
						
							| 
									
										
										
										
											2021-01-03 17:21:12 +01:00
										 |  |  |     else | 
					
						
							|  |  |  |         Application::the()->hide_tooltip(); | 
					
						
							| 
									
										
										
										
											2020-08-15 11:44:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 21:24:45 +02:00
										 |  |  | Gfx::IntRect Widget::children_clip_rect() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return rect(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-11 14:17:35 +02:00
										 |  |  | void Widget::set_override_cursor(Gfx::StandardCursor cursor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_override_cursor == cursor) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_override_cursor = cursor; | 
					
						
							|  |  |  |     if (auto* window = this->window()) | 
					
						
							|  |  |  |         window->update_cursor({}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-20 11:47:44 +01:00
										 |  |  | bool Widget::load_from_gml(const StringView& gml_string) | 
					
						
							| 
									
										
										
										
											2021-01-11 14:01:15 -05:00
										 |  |  | { | 
					
						
							|  |  |  |     return load_from_gml(gml_string, [](const String& class_name) -> RefPtr<Widget> { | 
					
						
							|  |  |  |         dbgln("Class '{}' not registered", class_name); | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Widget::load_from_gml(const StringView& gml_string, RefPtr<Widget> (*unregistered_child_handler)(const String&)) | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-20 11:47:44 +01:00
										 |  |  |     auto value = parse_gml(gml_string); | 
					
						
							| 
									
										
										
										
											2020-12-20 14:28:41 +01:00
										 |  |  |     if (!value.is_object()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-01-11 14:01:15 -05:00
										 |  |  |     return load_from_json(value.as_object(), unregistered_child_handler); | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 14:01:15 -05:00
										 |  |  | bool Widget::load_from_json(const JsonObject& json, RefPtr<Widget> (*unregistered_child_handler)(const String&)) | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-14 16:01:12 +02:00
										 |  |  |     json.for_each_member([&](auto& key, auto& value) { | 
					
						
							|  |  |  |         set_property(key, value); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto layout_value = json.get("layout"); | 
					
						
							| 
									
										
										
										
											2020-09-14 13:01:09 +02:00
										 |  |  |     if (!layout_value.is_null() && !layout_value.is_object()) { | 
					
						
							| 
									
										
										
										
											2021-01-09 18:51:44 +01:00
										 |  |  |         dbgln("layout is not an object"); | 
					
						
							| 
									
										
										
										
											2020-09-14 13:01:09 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  |     if (layout_value.is_object()) { | 
					
						
							|  |  |  |         auto& layout = layout_value.as_object(); | 
					
						
							|  |  |  |         auto class_name = layout.get("class"); | 
					
						
							|  |  |  |         if (class_name.is_null()) { | 
					
						
							| 
									
										
										
										
											2021-01-09 18:51:44 +01:00
										 |  |  |             dbgln("Invalid layout class name"); | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (class_name.to_string() == "GUI::VerticalBoxLayout") { | 
					
						
							|  |  |  |             set_layout<GUI::VerticalBoxLayout>(); | 
					
						
							|  |  |  |         } else if (class_name.to_string() == "GUI::HorizontalBoxLayout") { | 
					
						
							|  |  |  |             set_layout<GUI::HorizontalBoxLayout>(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             dbg() << "Unknown layout class: '" << class_name.to_string() << "'"; | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 21:33:37 +02:00
										 |  |  |         layout.for_each_member([&](auto& key, auto& value) { | 
					
						
							|  |  |  |             this->layout()->set_property(key, value); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto children = json.get("children"); | 
					
						
							|  |  |  |     if (children.is_array()) { | 
					
						
							|  |  |  |         for (auto& child_json_value : children.as_array().values()) { | 
					
						
							|  |  |  |             if (!child_json_value.is_object()) | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             auto& child_json = child_json_value.as_object(); | 
					
						
							|  |  |  |             auto class_name = child_json.get("class"); | 
					
						
							|  |  |  |             if (!class_name.is_string()) { | 
					
						
							| 
									
										
										
										
											2021-01-09 18:51:44 +01:00
										 |  |  |                 dbgln("No class name in entry"); | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 14:01:15 -05:00
										 |  |  |             RefPtr<Widget> child_widget; | 
					
						
							|  |  |  |             if (auto* registration = WidgetClassRegistration::find(class_name.as_string())) { | 
					
						
							|  |  |  |                 child_widget = registration->construct(); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 child_widget = unregistered_child_handler(class_name.as_string()); | 
					
						
							|  |  |  |                 if (!child_widget) | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  |             add_child(*child_widget); | 
					
						
							| 
									
										
										
										
											2021-01-11 14:01:15 -05:00
										 |  |  |             child_widget->load_from_json(child_json, unregistered_child_handler); | 
					
						
							| 
									
										
										
										
											2020-09-14 12:46:53 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 23:38:42 +01:00
										 |  |  | bool Widget::has_focus_within() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto* window = this->window(); | 
					
						
							|  |  |  |     if (!window) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     if (!window->focused_widget()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     auto& effective_focus_widget = focus_proxy() ? *focus_proxy() : *this; | 
					
						
							|  |  |  |     return window->focused_widget() == &effective_focus_widget || is_ancestor_of(*window->focused_widget()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-04 18:17:14 +01:00
										 |  |  | void Widget::set_shrink_to_fit(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_shrink_to_fit == b) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_shrink_to_fit = b; | 
					
						
							|  |  |  |     invalidate_layout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 00:11:17 +01:00
										 |  |  | bool Widget::has_pending_drop() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return Application::the()->pending_drop_widget() == this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 15:07:41 +01:00
										 |  |  | } |