summaryrefslogtreecommitdiff
path: root/LibGUI
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-05-03 01:38:24 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-03 01:38:24 +0200
commitea9a39a9f2203b12271ffe65ad3920a1a32c856f (patch)
tree590f6242d24450a55d0785845bd4274f9edf8045 /LibGUI
parent34c5db61aa140b83f781425da86cd84404c6bc1e (diff)
downloadserenity-ea9a39a9f2203b12271ffe65ad3920a1a32c856f.zip
LibGUI+WindowServer: Add a GResizeCorner widget.
This widget is automatically included in GStatusBar, but can be added in any other place, too. When clicked (with the left button), it initiates a window resize (using a WM request.) In this patch I also fixed up some issues with override cursors being cleared after the WindowServer finishes a drag or resize.
Diffstat (limited to 'LibGUI')
-rw-r--r--LibGUI/GEventLoop.cpp14
-rw-r--r--LibGUI/GEventLoop.h5
-rw-r--r--LibGUI/GResizeCorner.cpp46
-rw-r--r--LibGUI/GResizeCorner.h18
-rw-r--r--LibGUI/GStatusBar.cpp3
-rw-r--r--LibGUI/GStatusBar.h2
-rw-r--r--LibGUI/GWindow.cpp9
-rw-r--r--LibGUI/GWindow.h4
-rw-r--r--LibGUI/Makefile1
9 files changed, 97 insertions, 5 deletions
diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp
index 5731d30387..ae41ad7da1 100644
--- a/LibGUI/GEventLoop.cpp
+++ b/LibGUI/GEventLoop.cpp
@@ -24,6 +24,7 @@
//#define COALESCING_DEBUG
int GEventLoop::s_event_fd = -1;
+int GEventLoop::s_my_client_id = -1;
pid_t GEventLoop::s_server_pid = -1;
void GEventLoop::connect_to_server()
@@ -59,8 +60,7 @@ void GEventLoop::connect_to_server()
request.type = WSAPI_ClientMessage::Type::Greeting;
request.greeting.client_pid = getpid();
auto response = sync_request(request, WSAPI_ServerMessage::Type::Greeting);
- s_server_pid = response.greeting.server_pid;
- GDesktop::the().did_receive_screen_rect(Badge<GEventLoop>(), response.greeting.screen_rect);
+ handle_greeting(response);
}
GEventLoop::GEventLoop()
@@ -235,8 +235,7 @@ void GEventLoop::process_unprocessed_bundles()
for (auto& bundle : unprocessed_bundles) {
auto& event = bundle.message;
if (event.type == WSAPI_ServerMessage::Type::Greeting) {
- s_server_pid = event.greeting.server_pid;
- GDesktop::the().did_receive_screen_rect(Badge<GEventLoop>(), event.greeting.screen_rect);
+ handle_greeting(event);
continue;
}
@@ -402,3 +401,10 @@ WSAPI_ServerMessage GEventLoop::sync_request(const WSAPI_ClientMessage& request,
ASSERT(success);
return response;
}
+
+void GEventLoop::handle_greeting(WSAPI_ServerMessage& message)
+{
+ s_server_pid = message.greeting.server_pid;
+ s_my_client_id = message.greeting.your_client_id;
+ GDesktop::the().did_receive_screen_rect(Badge<GEventLoop>(), message.greeting.screen_rect);
+}
diff --git a/LibGUI/GEventLoop.h b/LibGUI/GEventLoop.h
index a88194a4ed..4e235aa21d 100644
--- a/LibGUI/GEventLoop.h
+++ b/LibGUI/GEventLoop.h
@@ -21,6 +21,7 @@ public:
WSAPI_ServerMessage sync_request(const WSAPI_ClientMessage& request, WSAPI_ServerMessage::Type response_type);
static pid_t server_pid() { return s_server_pid; }
+ static int my_client_id() { return s_my_client_id; }
virtual void take_pending_events_from(CEventLoop& other) override
{
@@ -59,6 +60,7 @@ private:
void handle_menu_event(const WSAPI_ServerMessage&);
void handle_window_entered_or_left_event(const WSAPI_ServerMessage&, GWindow&);
void handle_wm_event(const WSAPI_ServerMessage&, GWindow&);
+ void handle_greeting(WSAPI_ServerMessage&);
void connect_to_server();
struct IncomingWSMessageBundle {
@@ -68,5 +70,6 @@ private:
Vector<IncomingWSMessageBundle, 64> m_unprocessed_bundles;
static pid_t s_server_pid;
- static pid_t s_event_fd;
+ static int s_my_client_id;
+ static int s_event_fd;
};
diff --git a/LibGUI/GResizeCorner.cpp b/LibGUI/GResizeCorner.cpp
new file mode 100644
index 0000000000..91407a509f
--- /dev/null
+++ b/LibGUI/GResizeCorner.cpp
@@ -0,0 +1,46 @@
+#include <LibGUI/GResizeCorner.h>
+#include <LibGUI/GPainter.h>
+#include <LibGUI/GWindow.h>
+#include <SharedGraphics/GraphicsBitmap.h>
+#include <WindowServer/WSAPITypes.h>
+
+GResizeCorner::GResizeCorner(GWidget* parent)
+ : GWidget(parent)
+{
+ set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
+ set_preferred_size({ 16, 16 });
+ m_bitmap = GraphicsBitmap::load_from_file("/res/icons/resize-corner.png");
+ ASSERT(m_bitmap);
+}
+
+GResizeCorner::~GResizeCorner()
+{
+}
+
+void GResizeCorner::paint_event(GPaintEvent& event)
+{
+ GPainter painter(*this);
+ painter.add_clip_rect(event.rect());
+ painter.fill_rect(rect(), background_color());
+ painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect());
+ GWidget::paint_event(event);
+}
+
+void GResizeCorner::mousedown_event(GMouseEvent& event)
+{
+ if (event.button() == GMouseButton::Left)
+ window()->start_wm_resize();
+ GWidget::mousedown_event(event);
+}
+
+void GResizeCorner::enter_event(CEvent& event)
+{
+ window()->set_override_cursor(GStandardCursor::ResizeDiagonalTLBR);
+ GWidget::enter_event(event);
+}
+
+void GResizeCorner::leave_event(CEvent& event)
+{
+ window()->set_override_cursor(GStandardCursor::None);
+ GWidget::leave_event(event);
+}
diff --git a/LibGUI/GResizeCorner.h b/LibGUI/GResizeCorner.h
new file mode 100644
index 0000000000..2d6ae0c670
--- /dev/null
+++ b/LibGUI/GResizeCorner.h
@@ -0,0 +1,18 @@
+#include <LibGUI/GWidget.h>
+
+class GResizeCorner : public GWidget {
+public:
+ explicit GResizeCorner(GWidget* parent);
+ virtual ~GResizeCorner() override;
+
+ virtual const char* class_name() const override { return "GResizeCorner"; }
+
+protected:
+ virtual void paint_event(GPaintEvent&) override;
+ virtual void mousedown_event(GMouseEvent&) override;
+ virtual void enter_event(CEvent&) override;
+ virtual void leave_event(CEvent&) override;
+
+private:
+ RetainPtr<GraphicsBitmap> m_bitmap;
+};
diff --git a/LibGUI/GStatusBar.cpp b/LibGUI/GStatusBar.cpp
index 65d0b2ade5..74c6816f22 100644
--- a/LibGUI/GStatusBar.cpp
+++ b/LibGUI/GStatusBar.cpp
@@ -3,6 +3,7 @@
#include <LibGUI/GBoxLayout.h>
#include <SharedGraphics/StylePainter.h>
#include <LibGUI/GPainter.h>
+#include <LibGUI/GResizeCorner.h>
GStatusBar::GStatusBar(GWidget* parent)
: GWidget(parent)
@@ -17,6 +18,8 @@ GStatusBar::GStatusBar(GWidget* parent)
m_label->set_frame_shape(FrameShape::Panel);
m_label->set_frame_thickness(1);
m_label->set_text_alignment(TextAlignment::CenterLeft);
+
+ m_corner = new GResizeCorner(this);
}
GStatusBar::~GStatusBar()
diff --git a/LibGUI/GStatusBar.h b/LibGUI/GStatusBar.h
index d01648ff52..9bac204c30 100644
--- a/LibGUI/GStatusBar.h
+++ b/LibGUI/GStatusBar.h
@@ -3,6 +3,7 @@
#include <LibGUI/GWidget.h>
class GLabel;
+class GResizeCorner;
class GStatusBar : public GWidget {
public:
@@ -18,4 +19,5 @@ private:
virtual void paint_event(GPaintEvent&) override;
GLabel* m_label { nullptr };
+ GResizeCorner* m_corner { nullptr };
};
diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp
index 36dbd2fe11..c1384ebe97 100644
--- a/LibGUI/GWindow.cpp
+++ b/LibGUI/GWindow.cpp
@@ -490,3 +490,12 @@ void GWindow::set_icon_path(const String& path)
message.text_length = path.length();
GEventLoop::post_message_to_server(message);
}
+
+void GWindow::start_wm_resize()
+{
+ WSAPI_ClientMessage message;
+ message.type = WSAPI_ClientMessage::Type::WM_StartWindowResize;
+ message.wm.client_id = GEventLoop::my_client_id();
+ message.wm.window_id = m_window_id;
+ GEventLoop::post_message_to_server(message);
+}
diff --git a/LibGUI/GWindow.h b/LibGUI/GWindow.h
index cddebcef02..4adf2f7f9d 100644
--- a/LibGUI/GWindow.h
+++ b/LibGUI/GWindow.h
@@ -16,6 +16,8 @@ enum class GStandardCursor {
IBeam,
ResizeHorizontal,
ResizeVertical,
+ ResizeDiagonalTLBR,
+ ResizeDiagonalBLTR,
};
class GWindow : public CObject {
@@ -71,6 +73,8 @@ public:
void hide();
void close();
+ void start_wm_resize();
+
GWidget* main_widget() { return m_main_widget; }
const GWidget* main_widget() const { return m_main_widget; }
void set_main_widget(GWidget*);
diff --git a/LibGUI/Makefile b/LibGUI/Makefile
index 0255d05520..14b0427c43 100644
--- a/LibGUI/Makefile
+++ b/LibGUI/Makefile
@@ -53,6 +53,7 @@ LIBGUI_OBJS = \
GSpinBox.o \
GGroupBox.o \
GSlider.o \
+ GResizeCorner.o \
GWindow.o
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)