summaryrefslogtreecommitdiff
path: root/Userland/Services/WindowServer/Cursor.cpp
blob: 07ce2ab1f8454129d5f0e447012a8316e154820c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <AK/LexicalPath.h>
#include <WindowServer/Cursor.h>
#include <WindowServer/Screen.h>
#include <WindowServer/WindowManager.h>

namespace WindowServer {

Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor, Gfx::CursorParams const& cursor_params)
    : m_params(cursor_params.constrained(*bitmap))
    , m_rect(bitmap->rect())
{
    m_bitmaps.set(scale_factor, move(bitmap));
    update_rect_if_animated();
}

void Cursor::update_rect_if_animated()
{
    if (m_params.frames() > 1) {
        VERIFY(m_rect.width() % m_params.frames() == 0);
        m_rect.set_width(m_rect.width() / m_params.frames());
    }
}

NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor)
{
    auto hotspot = bitmap->rect().center();
    return adopt_ref(*new Cursor(move(bitmap), scale_factor, Gfx::CursorParams(hotspot)));
}

RefPtr<Cursor> Cursor::create(const StringView& filename, const StringView& default_filename)
{
    auto cursor = adopt_ref(*new Cursor());
    if (cursor->load(filename, default_filename))
        return cursor;
    return {};
}

bool Cursor::load(const StringView& filename, const StringView& default_filename)
{
    bool did_load_any = false;

    auto load_bitmap = [&](const StringView& path, int scale_factor) {
        auto bitmap = Gfx::Bitmap::try_load_from_file(path, scale_factor);
        if (bitmap) {
            did_load_any = true;
            m_bitmaps.set(scale_factor, bitmap.release_nonnull());
        }
    };

    Screen::for_each_scale_factor_in_use([&](int scale_factor) {
        load_bitmap(filename, scale_factor);
        return IterationDecision::Continue;
    });
    if (!did_load_any) {
        Screen::for_each_scale_factor_in_use([&](int scale_factor) {
            load_bitmap(default_filename, scale_factor);
            return IterationDecision::Continue;
        });
    }
    if (did_load_any) {
        auto& bitmap = this->bitmap(1);
        m_rect = bitmap.rect();
        m_params = Gfx::CursorParams::parse_from_filename(filename, m_rect.center()).constrained(bitmap);
        update_rect_if_animated();
    }
    return did_load_any;
}

RefPtr<Cursor> Cursor::create(Gfx::StandardCursor standard_cursor)
{
    switch (standard_cursor) {
    case Gfx::StandardCursor::None:
        return nullptr;
    case Gfx::StandardCursor::Hidden:
        return WindowManager::the().hidden_cursor();
    case Gfx::StandardCursor::Arrow:
        return WindowManager::the().arrow_cursor();
    case Gfx::StandardCursor::Crosshair:
        return WindowManager::the().crosshair_cursor();
    case Gfx::StandardCursor::IBeam:
        return WindowManager::the().i_beam_cursor();
    case Gfx::StandardCursor::ResizeHorizontal:
        return WindowManager::the().resize_horizontally_cursor();
    case Gfx::StandardCursor::ResizeVertical:
        return WindowManager::the().resize_vertically_cursor();
    case Gfx::StandardCursor::ResizeDiagonalTLBR:
        return WindowManager::the().resize_diagonally_tlbr_cursor();
    case Gfx::StandardCursor::ResizeDiagonalBLTR:
        return WindowManager::the().resize_diagonally_bltr_cursor();
    case Gfx::StandardCursor::ResizeColumn:
        return WindowManager::the().resize_column_cursor();
    case Gfx::StandardCursor::ResizeRow:
        return WindowManager::the().resize_row_cursor();
    case Gfx::StandardCursor::Hand:
        return WindowManager::the().hand_cursor();
    case Gfx::StandardCursor::Help:
        return WindowManager::the().help_cursor();
    case Gfx::StandardCursor::Drag:
        return WindowManager::the().drag_cursor();
    case Gfx::StandardCursor::Move:
        return WindowManager::the().move_cursor();
    case Gfx::StandardCursor::Wait:
        return WindowManager::the().wait_cursor();
    case Gfx::StandardCursor::Disallowed:
        return WindowManager::the().disallowed_cursor();
    case Gfx::StandardCursor::Eyedropper:
        return WindowManager::the().eyedropper_cursor();
    case Gfx::StandardCursor::Zoom:
        return WindowManager::the().zoom_cursor();
    default:
        VERIFY_NOT_REACHED();
    }
}

}