Serenity Operating System
at master 123 lines 4.4 kB view raw
1/* 2 * Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/LexicalPath.h> 8#include <WindowServer/Cursor.h> 9#include <WindowServer/Screen.h> 10#include <WindowServer/WindowManager.h> 11 12namespace WindowServer { 13 14Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap const>&& bitmap, int scale_factor, Gfx::CursorParams const& cursor_params) 15 : m_params(cursor_params.constrained(*bitmap)) 16 , m_rect(bitmap->rect()) 17{ 18 m_bitmaps.set(scale_factor, move(bitmap)); 19 update_rect_if_animated(); 20} 21 22void Cursor::update_rect_if_animated() 23{ 24 if (m_params.frames() > 1) { 25 VERIFY(m_rect.width() % m_params.frames() == 0); 26 m_rect.set_width(m_rect.width() / m_params.frames()); 27 } 28} 29 30NonnullRefPtr<Cursor const> Cursor::create(NonnullRefPtr<Gfx::Bitmap const>&& bitmap, int scale_factor) 31{ 32 auto hotspot = bitmap->rect().center(); 33 return adopt_ref(*new Cursor(move(bitmap), scale_factor, Gfx::CursorParams(hotspot))); 34} 35 36RefPtr<Cursor const> Cursor::create(StringView filename, StringView default_filename) 37{ 38 auto cursor = adopt_ref(*new Cursor()); 39 if (cursor->load(filename, default_filename)) 40 return cursor; 41 return {}; 42} 43 44bool Cursor::load(StringView filename, StringView default_filename) 45{ 46 bool did_load_any = false; 47 48 auto load_bitmap = [&](StringView path, int scale_factor) { 49 auto bitmap_or_error = Gfx::Bitmap::load_from_file(path, scale_factor); 50 if (bitmap_or_error.is_error()) 51 return; 52 did_load_any = true; 53 m_bitmaps.set(scale_factor, bitmap_or_error.release_value()); 54 }; 55 56 Screen::for_each_scale_factor_in_use([&](int scale_factor) { 57 load_bitmap(filename, scale_factor); 58 return IterationDecision::Continue; 59 }); 60 if (!did_load_any) { 61 Screen::for_each_scale_factor_in_use([&](int scale_factor) { 62 load_bitmap(default_filename, scale_factor); 63 return IterationDecision::Continue; 64 }); 65 } 66 if (did_load_any) { 67 auto& bitmap = this->bitmap(1); 68 m_rect = bitmap.rect(); 69 m_params = Gfx::CursorParams::parse_from_filename(filename, m_rect.center()).constrained(bitmap); 70 update_rect_if_animated(); 71 } 72 return did_load_any; 73} 74 75RefPtr<Cursor const> Cursor::create(Gfx::StandardCursor standard_cursor) 76{ 77 switch (standard_cursor) { 78 case Gfx::StandardCursor::None: 79 return nullptr; 80 case Gfx::StandardCursor::Hidden: 81 return WindowManager::the().hidden_cursor(); 82 case Gfx::StandardCursor::Arrow: 83 return WindowManager::the().arrow_cursor(); 84 case Gfx::StandardCursor::Crosshair: 85 return WindowManager::the().crosshair_cursor(); 86 case Gfx::StandardCursor::IBeam: 87 return WindowManager::the().i_beam_cursor(); 88 case Gfx::StandardCursor::ResizeHorizontal: 89 return WindowManager::the().resize_horizontally_cursor(); 90 case Gfx::StandardCursor::ResizeVertical: 91 return WindowManager::the().resize_vertically_cursor(); 92 case Gfx::StandardCursor::ResizeDiagonalTLBR: 93 return WindowManager::the().resize_diagonally_tlbr_cursor(); 94 case Gfx::StandardCursor::ResizeDiagonalBLTR: 95 return WindowManager::the().resize_diagonally_bltr_cursor(); 96 case Gfx::StandardCursor::ResizeColumn: 97 return WindowManager::the().resize_column_cursor(); 98 case Gfx::StandardCursor::ResizeRow: 99 return WindowManager::the().resize_row_cursor(); 100 case Gfx::StandardCursor::Hand: 101 return WindowManager::the().hand_cursor(); 102 case Gfx::StandardCursor::Help: 103 return WindowManager::the().help_cursor(); 104 case Gfx::StandardCursor::Drag: 105 return WindowManager::the().drag_cursor(); 106 case Gfx::StandardCursor::DragCopy: 107 return WindowManager::the().drag_copy_cursor(); 108 case Gfx::StandardCursor::Move: 109 return WindowManager::the().move_cursor(); 110 case Gfx::StandardCursor::Wait: 111 return WindowManager::the().wait_cursor(); 112 case Gfx::StandardCursor::Disallowed: 113 return WindowManager::the().disallowed_cursor(); 114 case Gfx::StandardCursor::Eyedropper: 115 return WindowManager::the().eyedropper_cursor(); 116 case Gfx::StandardCursor::Zoom: 117 return WindowManager::the().zoom_cursor(); 118 default: 119 VERIFY_NOT_REACHED(); 120 } 121} 122 123}