mirror of
https://github.com/RGBCube/serenity
synced 2025-05-23 19:15:07 +00:00
WindowServer: Add support for per-window override cursors.
Use this to implement automatic switching to an I-beam cursor when hovering over a GTextEditor. :^)
This commit is contained in:
parent
42c95959a8
commit
dcf6726487
13 changed files with 110 additions and 0 deletions
|
@ -3,6 +3,7 @@
|
|||
#include <LibGUI/GFontDatabase.h>
|
||||
#include <LibGUI/GClipboard.h>
|
||||
#include <LibGUI/GPainter.h>
|
||||
#include <LibGUI/GWindow.h>
|
||||
#include <Kernel/KeyCode.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <unistd.h>
|
||||
|
@ -801,3 +802,15 @@ void GTextEditor::paste()
|
|||
printf("Paste: \"%s\"\n", paste_text.characters());
|
||||
insert_at_cursor_or_replace_selection(paste_text);
|
||||
}
|
||||
|
||||
void GTextEditor::enter_event(GEvent&)
|
||||
{
|
||||
ASSERT(window());
|
||||
window()->set_override_cursor(GStandardCursor::IBeam);
|
||||
}
|
||||
|
||||
void GTextEditor::leave_event(GEvent&)
|
||||
{
|
||||
ASSERT(window());
|
||||
window()->set_override_cursor(GStandardCursor::None);
|
||||
}
|
||||
|
|
|
@ -111,6 +111,9 @@ private:
|
|||
virtual void focusout_event(GEvent&) override;
|
||||
virtual void timer_event(GTimerEvent&) override;
|
||||
virtual bool accepts_focus() const override { return true; }
|
||||
virtual void enter_event(GEvent&) override;
|
||||
virtual void leave_event(GEvent&) override;
|
||||
|
||||
void paint_ruler(Painter&);
|
||||
void update_content_size();
|
||||
|
||||
|
|
|
@ -140,6 +140,17 @@ void GWindow::set_rect(const Rect& a_rect)
|
|||
GEventLoop::current().post_message_to_server(request);
|
||||
}
|
||||
|
||||
void GWindow::set_override_cursor(GStandardCursor cursor)
|
||||
{
|
||||
if (!m_window_id)
|
||||
return;
|
||||
WSAPI_ClientMessage request;
|
||||
request.type = WSAPI_ClientMessage::Type::SetWindowOverrideCursor;
|
||||
request.window_id = m_window_id;
|
||||
request.cursor.cursor = (WSAPI_StandardCursor)cursor;
|
||||
GEventLoop::current().post_message_to_server(request);
|
||||
}
|
||||
|
||||
void GWindow::event(GEvent& event)
|
||||
{
|
||||
if (event.is_mouse_event()) {
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
|
||||
class GWidget;
|
||||
|
||||
enum class GStandardCursor {
|
||||
None = 0,
|
||||
Arrow,
|
||||
IBeam,
|
||||
};
|
||||
|
||||
class GWindow : public GObject {
|
||||
public:
|
||||
GWindow(GObject* parent = nullptr);
|
||||
|
@ -84,6 +90,8 @@ public:
|
|||
Size base_size() const { return m_base_size; }
|
||||
void set_base_size(const Size& size) { m_base_size = size; }
|
||||
|
||||
void set_override_cursor(GStandardCursor);
|
||||
|
||||
virtual const char* class_name() const override { return "GWindow"; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -47,6 +47,11 @@ struct WSAPI_KeyModifiers { enum {
|
|||
Ctrl = 1 << 2,
|
||||
}; };
|
||||
|
||||
enum class WSAPI_StandardCursor : unsigned char {
|
||||
None = 0,
|
||||
Arrow,
|
||||
IBeam,
|
||||
};
|
||||
|
||||
struct WSAPI_ServerMessage {
|
||||
enum Type : unsigned {
|
||||
|
@ -164,6 +169,7 @@ struct WSAPI_ClientMessage {
|
|||
Greeting,
|
||||
SetWallpaper,
|
||||
GetWallpaper,
|
||||
SetWindowOverrideCursor,
|
||||
};
|
||||
Type type { Invalid };
|
||||
int window_id { -1 };
|
||||
|
@ -203,6 +209,9 @@ struct WSAPI_ClientMessage {
|
|||
int shared_buffer_id;
|
||||
int contents_size;
|
||||
} clipboard;
|
||||
struct {
|
||||
WSAPI_StandardCursor cursor;
|
||||
} cursor;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -491,6 +491,18 @@ void WSClientConnection::handle_request(WSAPISetGlobalCursorTrackingRequest& req
|
|||
window.set_global_cursor_tracking_enabled(request.value());
|
||||
}
|
||||
|
||||
void WSClientConnection::handle_request(WSAPISetWindowOverrideCursorRequest& request)
|
||||
{
|
||||
int window_id = request.window_id();
|
||||
auto it = m_windows.find(window_id);
|
||||
if (it == m_windows.end()) {
|
||||
post_error("Bad window ID");
|
||||
return;
|
||||
}
|
||||
auto& window = *(*it).value;
|
||||
window.set_override_cursor(WSCursor::create(request.cursor()));
|
||||
}
|
||||
|
||||
void WSClientConnection::on_request(WSAPIClientRequest& request)
|
||||
{
|
||||
switch (request.type()) {
|
||||
|
@ -542,6 +554,8 @@ void WSClientConnection::on_request(WSAPIClientRequest& request)
|
|||
return handle_request(static_cast<WSAPISetWallpaperRequest&>(request));
|
||||
case WSMessage::APIGetWallpaperRequest:
|
||||
return handle_request(static_cast<WSAPIGetWallpaperRequest&>(request));
|
||||
case WSMessage::APISetWindowOverrideCursorRequest:
|
||||
return handle_request(static_cast<WSAPISetWindowOverrideCursorRequest&>(request));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ private:
|
|||
void handle_request(WSAPISetWindowOpacityRequest&);
|
||||
void handle_request(WSAPISetWallpaperRequest&);
|
||||
void handle_request(WSAPIGetWallpaperRequest&);
|
||||
void handle_request(WSAPISetWindowOverrideCursorRequest&);
|
||||
|
||||
void post_error(const String&);
|
||||
|
||||
|
|
|
@ -19,3 +19,16 @@ Retained<WSCursor> WSCursor::create(Retained<GraphicsBitmap>&& bitmap, const Poi
|
|||
{
|
||||
return adopt(*new WSCursor(move(bitmap), hotspot));
|
||||
}
|
||||
|
||||
RetainPtr<WSCursor> WSCursor::create(WSStandardCursor standard_cursor)
|
||||
{
|
||||
switch (standard_cursor) {
|
||||
case WSStandardCursor::None:
|
||||
return nullptr;
|
||||
case WSStandardCursor::Arrow:
|
||||
return create(*GraphicsBitmap::load_from_file("/res/cursors/arrow.png"));
|
||||
case WSStandardCursor::IBeam:
|
||||
return create(*GraphicsBitmap::load_from_file("/res/cursors/i-beam.png"));
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
|
|
@ -2,10 +2,17 @@
|
|||
|
||||
#include <SharedGraphics/GraphicsBitmap.h>
|
||||
|
||||
enum class WSStandardCursor {
|
||||
None = 0,
|
||||
Arrow,
|
||||
IBeam,
|
||||
};
|
||||
|
||||
class WSCursor : public Retainable<WSCursor> {
|
||||
public:
|
||||
static Retained<WSCursor> create(Retained<GraphicsBitmap>&&, const Point& hotspot);
|
||||
static Retained<WSCursor> create(Retained<GraphicsBitmap>&&);
|
||||
static RetainPtr<WSCursor> create(WSStandardCursor);
|
||||
~WSCursor();
|
||||
|
||||
Point hotspot() const { return m_hotspot; }
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <AK/AKString.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/KeyCode.h>
|
||||
#include <WindowServer/WSCursor.h>
|
||||
|
||||
class WSMessage {
|
||||
public:
|
||||
|
@ -49,6 +50,7 @@ public:
|
|||
APIGetClipboardContentsRequest,
|
||||
APISetWallpaperRequest,
|
||||
APIGetWallpaperRequest,
|
||||
APISetWindowOverrideCursorRequest,
|
||||
__End_API_Client_Requests,
|
||||
};
|
||||
|
||||
|
@ -229,6 +231,23 @@ private:
|
|||
int m_menu_id { 0 };
|
||||
};
|
||||
|
||||
class WSAPISetWindowOverrideCursorRequest final : public WSAPIClientRequest {
|
||||
public:
|
||||
explicit WSAPISetWindowOverrideCursorRequest(int client_id, int window_id, WSStandardCursor cursor)
|
||||
: WSAPIClientRequest(WSMessage::APISetWindowOverrideCursorRequest, client_id)
|
||||
, m_window_id(window_id)
|
||||
, m_cursor(cursor)
|
||||
{
|
||||
}
|
||||
|
||||
int window_id() const { return m_window_id; }
|
||||
WSStandardCursor cursor() const { return m_cursor; }
|
||||
|
||||
private:
|
||||
int m_window_id { 0 };
|
||||
WSStandardCursor m_cursor { WSStandardCursor::None };
|
||||
};
|
||||
|
||||
class WSAPISetWallpaperRequest final : public WSAPIClientRequest {
|
||||
public:
|
||||
explicit WSAPISetWallpaperRequest(int client_id, String&& wallpaper)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <WindowServer/WSScreen.h>
|
||||
#include <WindowServer/WSClientConnection.h>
|
||||
#include <WindowServer/WSAPITypes.h>
|
||||
#include <WindowServer/WSCursor.h>
|
||||
#include <Kernel/KeyCode.h>
|
||||
#include <Kernel/MousePacket.h>
|
||||
#include <LibC/sys/socket.h>
|
||||
|
@ -330,6 +331,9 @@ void WSMessageLoop::on_receive_from_client(int client_id, const WSAPI_ClientMess
|
|||
break;
|
||||
case WSAPI_ClientMessage::Type::GetWallpaper:
|
||||
post_message(client, make<WSAPIGetWallpaperRequest>(client_id));
|
||||
break;
|
||||
case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
|
||||
post_message(client, make<WSAPISetWindowOverrideCursorRequest>(client_id, message.window_id, (WSStandardCursor)message.cursor.cursor));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <WindowServer/WSWindowType.h>
|
||||
|
||||
class WSClientConnection;
|
||||
class WSCursor;
|
||||
class WSMenu;
|
||||
class WSMouseEvent;
|
||||
|
||||
|
@ -100,6 +101,9 @@ public:
|
|||
const GraphicsBitmap& icon() const { return *m_icon; }
|
||||
void set_icon(Retained<GraphicsBitmap>&& icon) { m_icon = move(icon); }
|
||||
|
||||
const WSCursor* override_cursor() const { return m_override_cursor.ptr(); }
|
||||
void set_override_cursor(RetainPtr<WSCursor>&& cursor) { m_override_cursor = move(cursor); }
|
||||
|
||||
// For InlineLinkedList.
|
||||
// FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
|
||||
WSWindow* m_next { nullptr };
|
||||
|
@ -128,4 +132,5 @@ private:
|
|||
Size m_size_increment;
|
||||
Size m_base_size;
|
||||
Retained<GraphicsBitmap> m_icon;
|
||||
RetainPtr<WSCursor> m_override_cursor;
|
||||
};
|
||||
|
|
|
@ -1261,5 +1261,8 @@ const WSCursor& WSWindowManager::active_cursor() const
|
|||
}
|
||||
}
|
||||
|
||||
if (m_hovered_window && m_hovered_window->override_cursor())
|
||||
return *m_hovered_window->override_cursor();
|
||||
|
||||
return *m_arrow_cursor;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue