| 1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | /// @docImport 'package:flutter/material.dart'; |
| 6 | /// @docImport 'package:flutter/rendering.dart'; |
| 7 | library; |
| 8 | |
| 9 | import 'package:flutter/foundation.dart'; |
| 10 | import 'package:flutter/gestures.dart'; |
| 11 | |
| 12 | import 'system_channels.dart'; |
| 13 | |
| 14 | export 'package:flutter/foundation.dart' show DiagnosticLevel, DiagnosticPropertiesBuilder; |
| 15 | export 'package:flutter/gestures.dart' show PointerEvent; |
| 16 | |
| 17 | /// Maintains the state of mouse cursors and manages how cursors are searched |
| 18 | /// for. |
| 19 | /// |
| 20 | /// This is typically created as a global singleton and owned by [MouseTracker]. |
| 21 | class MouseCursorManager { |
| 22 | /// Create a [MouseCursorManager] by specifying the fallback cursor. |
| 23 | /// |
| 24 | /// The `fallbackMouseCursor` must not be [MouseCursor.defer] (typically |
| 25 | /// [SystemMouseCursors.basic]). |
| 26 | MouseCursorManager(this.fallbackMouseCursor) : assert(fallbackMouseCursor != MouseCursor.defer); |
| 27 | |
| 28 | /// The mouse cursor to use if all cursor candidates choose to defer. |
| 29 | /// |
| 30 | /// See also: |
| 31 | /// |
| 32 | /// * [MouseCursor.defer], the mouse cursor object to use to defer. |
| 33 | final MouseCursor fallbackMouseCursor; |
| 34 | |
| 35 | /// Returns the active mouse cursor of a device. |
| 36 | /// |
| 37 | /// The return value is the last [MouseCursor] activated onto this |
| 38 | /// device, even if the activation failed. |
| 39 | /// |
| 40 | /// Only valid when asserts are enabled. In release builds, always returns |
| 41 | /// null. |
| 42 | MouseCursor? debugDeviceActiveCursor(int device) { |
| 43 | MouseCursor? result; |
| 44 | assert(() { |
| 45 | result = _lastSession[device]?.cursor; |
| 46 | return true; |
| 47 | }()); |
| 48 | return result; |
| 49 | } |
| 50 | |
| 51 | final Map<int, MouseCursorSession> _lastSession = <int, MouseCursorSession>{}; |
| 52 | |
| 53 | /// Handles the changes that cause a pointer device to have a new list of mouse |
| 54 | /// cursor candidates. |
| 55 | /// |
| 56 | /// This change can be caused by a pointer event, in which case |
| 57 | /// `triggeringEvent` should not be null, or by other changes, such as when a |
| 58 | /// widget has moved under a still mouse, which is detected after the current |
| 59 | /// frame is complete. In either case, `cursorCandidates` should be the list of |
| 60 | /// cursors at the location of the mouse in hit-test order. |
| 61 | void handleDeviceCursorUpdate( |
| 62 | int device, |
| 63 | PointerEvent? triggeringEvent, |
| 64 | Iterable<MouseCursor> cursorCandidates, |
| 65 | ) { |
| 66 | if (triggeringEvent is PointerRemovedEvent) { |
| 67 | _lastSession.remove(device); |
| 68 | return; |
| 69 | } |
| 70 | |
| 71 | final MouseCursorSession? lastSession = _lastSession[device]; |
| 72 | final MouseCursor nextCursor = |
| 73 | _DeferringMouseCursor.firstNonDeferred(cursorCandidates) ?? fallbackMouseCursor; |
| 74 | assert(nextCursor is! _DeferringMouseCursor); |
| 75 | if (lastSession?.cursor == nextCursor) { |
| 76 | return; |
| 77 | } |
| 78 | |
| 79 | final MouseCursorSession nextSession = nextCursor.createSession(device); |
| 80 | _lastSession[device] = nextSession; |
| 81 | |
| 82 | lastSession?.dispose(); |
| 83 | nextSession.activate(); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | /// Manages the duration that a pointing device should display a specific mouse |
| 88 | /// cursor. |
| 89 | /// |
| 90 | /// While [MouseCursor] classes describe the kind of cursors, [MouseCursorSession] |
| 91 | /// classes represents a continuous use of the cursor on a pointing device. The |
| 92 | /// [MouseCursorSession] classes can be stateful. For example, a cursor that |
| 93 | /// needs to load resources might want to set a temporary cursor first, then |
| 94 | /// switch to the correct cursor after the load is completed. |
| 95 | /// |
| 96 | /// A [MouseCursorSession] has the following lifecycle: |
| 97 | /// |
| 98 | /// * When a pointing device should start displaying a cursor, [MouseTracker] |
| 99 | /// creates a session by calling [MouseCursor.createSession] on the target |
| 100 | /// cursor, and stores it in a table associated with the device. |
| 101 | /// * [MouseTracker] then immediately calls the session's [activate], where the |
| 102 | /// session should fetch resources and make system calls. |
| 103 | /// * When the pointing device should start displaying a different cursor, |
| 104 | /// [MouseTracker] calls [dispose] on this session. After [dispose], this session |
| 105 | /// will no longer be used in the future. |
| 106 | abstract class MouseCursorSession { |
| 107 | /// Create a session. |
| 108 | MouseCursorSession(this.cursor, this.device); |
| 109 | |
| 110 | /// The cursor that created this session. |
| 111 | final MouseCursor cursor; |
| 112 | |
| 113 | /// The device ID of the pointing device. |
| 114 | final int device; |
| 115 | |
| 116 | /// Override this method to do the work of changing the cursor of the device. |
| 117 | /// |
| 118 | /// Called right after this session is created. |
| 119 | /// |
| 120 | /// This method has full control over the cursor until the [dispose] call, and |
| 121 | /// can make system calls to change the pointer cursor as many times as |
| 122 | /// necessary (usually through [SystemChannels.mouseCursor]). It can also |
| 123 | /// collect resources, and store the result in this object. |
| 124 | @protected |
| 125 | Future<void> activate(); |
| 126 | |
| 127 | /// Called when device stops displaying the cursor. |
| 128 | /// |
| 129 | /// After this call, this session instance will no longer be used in the |
| 130 | /// future. |
| 131 | /// |
| 132 | /// When implementing this method in subclasses, you should release resources |
| 133 | /// and prevent [activate] from causing side effects after disposal. |
| 134 | @protected |
| 135 | void dispose(); |
| 136 | } |
| 137 | |
| 138 | /// An interface for mouse cursor definitions. |
| 139 | /// |
| 140 | /// A mouse cursor is a graphical image on the screen that echoes the movement |
| 141 | /// of a pointing device, such as a mouse or a stylus. A [MouseCursor] object |
| 142 | /// defines a kind of mouse cursor, such as an arrow, a pointing hand, or an |
| 143 | /// I-beam. |
| 144 | /// |
| 145 | /// During the painting phase, [MouseCursor] objects are assigned to regions on |
| 146 | /// the screen via annotations. Later during a device update (e.g. when a mouse |
| 147 | /// moves), [MouseTracker] finds the _active cursor_ of each mouse device, which |
| 148 | /// is the front-most region associated with the position of each mouse cursor, |
| 149 | /// or defaults to [SystemMouseCursors.basic] if no cursors are associated with |
| 150 | /// the position. [MouseTracker] changes the cursor of the pointer if the new |
| 151 | /// active cursor is different from the previous active cursor, whose effect is |
| 152 | /// defined by the session created by [createSession]. |
| 153 | /// |
| 154 | /// ## Cursor classes |
| 155 | /// |
| 156 | /// A [SystemMouseCursor] is a cursor that is natively supported by the |
| 157 | /// platform that the program is running on. All supported system mouse cursors |
| 158 | /// are enumerated in [SystemMouseCursors]. |
| 159 | /// |
| 160 | /// ## Using cursors |
| 161 | /// |
| 162 | /// A [MouseCursor] object is used by being assigned to a [MouseRegion] or |
| 163 | /// another widget that exposes the [MouseRegion] API, such as |
| 164 | /// [InkResponse.mouseCursor]. |
| 165 | /// |
| 166 | /// {@tool dartpad} |
| 167 | /// This sample creates a rectangular region that is wrapped by a [MouseRegion] |
| 168 | /// with a system mouse cursor. The mouse pointer becomes an I-beam when |
| 169 | /// hovering over the region. |
| 170 | /// |
| 171 | /// ** See code in examples/api/lib/services/mouse_cursor/mouse_cursor.0.dart ** |
| 172 | /// {@end-tool} |
| 173 | /// |
| 174 | /// Assigning regions with mouse cursors on platforms that do not support mouse |
| 175 | /// cursors, or when there are no mice connected, will have no effect. |
| 176 | /// |
| 177 | /// ## Related classes |
| 178 | /// |
| 179 | /// [MouseCursorSession] represents the duration when a pointing device displays |
| 180 | /// a cursor, and defines the states and behaviors of the cursor. Every mouse |
| 181 | /// cursor class usually has a corresponding [MouseCursorSession] class. |
| 182 | /// |
| 183 | /// [MouseCursorManager] is a class that adds the feature of changing |
| 184 | /// cursors to [MouseTracker], which tracks the relationship between mouse |
| 185 | /// devices and annotations. [MouseCursorManager] is usually used as a part |
| 186 | /// of [MouseTracker]. |
| 187 | @immutable |
| 188 | abstract class MouseCursor with Diagnosticable { |
| 189 | /// Abstract const constructor. This constructor enables subclasses to provide |
| 190 | /// const constructors so that they can be used in const expressions. |
| 191 | const MouseCursor(); |
| 192 | |
| 193 | /// Associate a pointing device to this cursor. |
| 194 | /// |
| 195 | /// A mouse cursor class usually has a corresponding [MouseCursorSession] |
| 196 | /// class, and instantiates such class in this method. |
| 197 | /// |
| 198 | /// This method is called each time a pointing device starts displaying this |
| 199 | /// cursor. A given cursor can be displayed by multiple devices at the same |
| 200 | /// time, in which case this method will be called separately for each device. |
| 201 | @protected |
| 202 | @factory |
| 203 | MouseCursorSession createSession(int device); |
| 204 | |
| 205 | /// A very short description of the mouse cursor. |
| 206 | /// |
| 207 | /// The [debugDescription] should be a few words that can describe this cursor |
| 208 | /// to make debug information more readable. It is returned as the [toString] |
| 209 | /// when the diagnostic level is at or above [DiagnosticLevel.info]. |
| 210 | /// |
| 211 | /// The [debugDescription] must not be empty. |
| 212 | String get debugDescription; |
| 213 | |
| 214 | @override |
| 215 | String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { |
| 216 | final String debugDescription = this.debugDescription; |
| 217 | if (minLevel.index >= DiagnosticLevel.info.index) { |
| 218 | return debugDescription; |
| 219 | } |
| 220 | return super.toString(minLevel: minLevel); |
| 221 | } |
| 222 | |
| 223 | /// A special class that indicates that the region with this cursor defers the |
| 224 | /// choice of cursor to the next region behind it. |
| 225 | /// |
| 226 | /// When an event occurs, [MouseTracker] will update each pointer's cursor by |
| 227 | /// finding the list of regions that contain the pointer's location, from front |
| 228 | /// to back in hit-test order. The pointer's cursor will be the first cursor in |
| 229 | /// the list that is not a [MouseCursor.defer]. |
| 230 | static const MouseCursor defer = _DeferringMouseCursor._(); |
| 231 | |
| 232 | /// A special value that doesn't change cursor by itself, but make a region |
| 233 | /// that blocks other regions behind it from changing the cursor. |
| 234 | /// |
| 235 | /// When a pointer enters a region with a cursor of [uncontrolled], the pointer |
| 236 | /// retains its previous cursor and keeps so until it moves out of the region. |
| 237 | /// Technically, this region absorb the mouse cursor hit test without changing |
| 238 | /// the pointer's cursor. |
| 239 | /// |
| 240 | /// This is useful in a region that displays a platform view, which let the |
| 241 | /// operating system handle pointer events and change cursors accordingly. To |
| 242 | /// achieve this, the region's cursor must not be any Flutter cursor, since |
| 243 | /// that might overwrite the system request upon pointer entering; the cursor |
| 244 | /// must not be null either, since that allows the widgets behind the region to |
| 245 | /// change cursors. |
| 246 | static const MouseCursor uncontrolled = _NoopMouseCursor._(); |
| 247 | } |
| 248 | |
| 249 | class _DeferringMouseCursor extends MouseCursor { |
| 250 | const _DeferringMouseCursor._(); |
| 251 | |
| 252 | @override |
| 253 | MouseCursorSession createSession(int device) { |
| 254 | assert(false, '_DeferringMouseCursor can not create a session' ); |
| 255 | throw UnimplementedError(); |
| 256 | } |
| 257 | |
| 258 | @override |
| 259 | String get debugDescription => 'defer' ; |
| 260 | |
| 261 | /// Returns the first cursor that is not a [MouseCursor.defer]. |
| 262 | static MouseCursor? firstNonDeferred(Iterable<MouseCursor> cursors) { |
| 263 | for (final MouseCursor cursor in cursors) { |
| 264 | if (cursor != MouseCursor.defer) { |
| 265 | return cursor; |
| 266 | } |
| 267 | } |
| 268 | return null; |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | class _NoopMouseCursorSession extends MouseCursorSession { |
| 273 | _NoopMouseCursorSession(_NoopMouseCursor super.cursor, super.device); |
| 274 | |
| 275 | @override |
| 276 | Future<void> activate() async { |
| 277 | /* Nothing */ |
| 278 | } |
| 279 | |
| 280 | @override |
| 281 | void dispose() { |
| 282 | /* Nothing */ |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | /// A mouse cursor that doesn't change the cursor when activated. |
| 287 | /// |
| 288 | /// Although setting a region's cursor to [_NoopMouseCursor] doesn't change the |
| 289 | /// cursor, it blocks regions behind it from changing the cursor, in contrast to |
| 290 | /// setting the cursor to null. More information about the usage of this class |
| 291 | /// can be found at [MouseCursor.uncontrolled]. |
| 292 | /// |
| 293 | /// To use this class, use [MouseCursor.uncontrolled]. Directly |
| 294 | /// instantiating this class is not allowed. |
| 295 | class _NoopMouseCursor extends MouseCursor { |
| 296 | // Application code shouldn't directly instantiate this class, since its only |
| 297 | // instance is accessible at [SystemMouseCursors.releaseControl]. |
| 298 | const _NoopMouseCursor._(); |
| 299 | |
| 300 | @override |
| 301 | @protected |
| 302 | _NoopMouseCursorSession createSession(int device) => _NoopMouseCursorSession(this, device); |
| 303 | |
| 304 | @override |
| 305 | String get debugDescription => 'uncontrolled' ; |
| 306 | } |
| 307 | |
| 308 | class _SystemMouseCursorSession extends MouseCursorSession { |
| 309 | _SystemMouseCursorSession(SystemMouseCursor super.cursor, super.device); |
| 310 | |
| 311 | @override |
| 312 | SystemMouseCursor get cursor => super.cursor as SystemMouseCursor; |
| 313 | |
| 314 | @override |
| 315 | Future<void> activate() { |
| 316 | return SystemChannels.mouseCursor.invokeMethod<void>('activateSystemCursor' , <String, dynamic>{ |
| 317 | 'device' : device, |
| 318 | 'kind' : cursor.kind, |
| 319 | }); |
| 320 | } |
| 321 | |
| 322 | @override |
| 323 | void dispose() { |
| 324 | /* Nothing */ |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | /// A mouse cursor that is natively supported on the platform that the |
| 329 | /// application is running on. |
| 330 | /// |
| 331 | /// System cursors can be used without external resources, and their appearances |
| 332 | /// match the experience of native apps. Examples of system cursors are a |
| 333 | /// pointing arrow, a pointing hand, a double arrow for resizing, or a text |
| 334 | /// I-beam, etc. |
| 335 | /// |
| 336 | /// An instance of [SystemMouseCursor] refers to one cursor from each platform |
| 337 | /// that represents the same concept, such as being text, being clickable, |
| 338 | /// or being a forbidden operation. Since the set of system cursors supported by |
| 339 | /// each platform varies, multiple instances can correspond to the same system |
| 340 | /// cursor. |
| 341 | /// |
| 342 | /// Each cursor is noted with its corresponding native cursors on each platform: |
| 343 | /// |
| 344 | /// * Android: API name in Java |
| 345 | /// * Web: CSS cursor |
| 346 | /// * Windows: Win32 API |
| 347 | /// * Windows UWP: WinRT API, `winrt::Windows::UI::Core::CoreCursorType` |
| 348 | /// * Linux: GDK, `gdk_cursor_new_from_name` |
| 349 | /// * macOS: API name in Objective C |
| 350 | /// |
| 351 | /// If the platform that the application is running on is not listed for a cursor, |
| 352 | /// using this cursor falls back to [SystemMouseCursors.basic]. |
| 353 | /// |
| 354 | /// [SystemMouseCursors] enumerates the complete set of system cursors supported |
| 355 | /// by Flutter, which are hard-coded in the engine. Therefore, manually |
| 356 | /// instantiating this class is not supported. |
| 357 | class SystemMouseCursor extends MouseCursor { |
| 358 | // Application code shouldn't directly instantiate system mouse cursors, since |
| 359 | // the supported system cursors are enumerated in [SystemMouseCursors]. |
| 360 | const SystemMouseCursor._({required this.kind}); |
| 361 | |
| 362 | /// A string that identifies the kind of the cursor. |
| 363 | /// |
| 364 | /// The interpretation of [kind] is platform-dependent. |
| 365 | final String kind; |
| 366 | |
| 367 | @override |
| 368 | String get debugDescription => ' ${objectRuntimeType(this, 'SystemMouseCursor' )}( $kind)' ; |
| 369 | |
| 370 | @override |
| 371 | @protected |
| 372 | MouseCursorSession createSession(int device) => _SystemMouseCursorSession(this, device); |
| 373 | |
| 374 | @override |
| 375 | bool operator ==(Object other) { |
| 376 | if (other.runtimeType != runtimeType) { |
| 377 | return false; |
| 378 | } |
| 379 | return other is SystemMouseCursor && other.kind == kind; |
| 380 | } |
| 381 | |
| 382 | @override |
| 383 | int get hashCode => kind.hashCode; |
| 384 | |
| 385 | @override |
| 386 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| 387 | super.debugFillProperties(properties); |
| 388 | properties.add(DiagnosticsProperty<String>('kind' , kind, level: DiagnosticLevel.debug)); |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | /// A collection of system [MouseCursor]s. |
| 393 | /// |
| 394 | /// System cursors are standard mouse cursors that are provided by the current |
| 395 | /// platform. They don't require external resources. |
| 396 | /// |
| 397 | /// [SystemMouseCursors] is a superset of the system cursors of every platform |
| 398 | /// that Flutter supports, therefore some of these objects might map to the same |
| 399 | /// result, or fallback to the [basic] arrow. This mapping is defined by the |
| 400 | /// Flutter engine. |
| 401 | /// |
| 402 | /// The cursors should be named based on the cursors' use cases instead of their |
| 403 | /// appearance, because different platforms might (although not commonly) use |
| 404 | /// different shapes for the same use case. |
| 405 | abstract final class SystemMouseCursors { |
| 406 | // The mapping in this class must be kept in sync with the following files in |
| 407 | // the engine: |
| 408 | // |
| 409 | // * Android: shell/platform/android/io/flutter/plugin/mouse/MouseCursorPlugin.java |
| 410 | // * Web: lib/web_ui/lib/src/engine/mouse_cursor.dart |
| 411 | // * Windows: shell/platform/windows/flutter_windows_engine.cc |
| 412 | // * Linux: shell/platform/linux/fl_mouse_cursor_plugin.cc |
| 413 | // * macOS: shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.mm |
| 414 | |
| 415 | /// Hide the cursor. |
| 416 | /// |
| 417 | /// Any cursor other than [none] or [MouseCursor.uncontrolled] unhides the |
| 418 | /// cursor. |
| 419 | static const SystemMouseCursor none = SystemMouseCursor._(kind: 'none' ); |
| 420 | |
| 421 | // STATUS |
| 422 | |
| 423 | /// The platform-dependent basic cursor. |
| 424 | /// |
| 425 | /// Typically the shape of an arrow. |
| 426 | /// |
| 427 | /// Corresponds to: |
| 428 | /// |
| 429 | /// * Android: TYPE_DEFAULT, TYPE_ARROW |
| 430 | /// * Web: default |
| 431 | /// * Windows: IDC_ARROW |
| 432 | /// * Windows UWP: CoreCursorType::Arrow |
| 433 | /// * Linux: default |
| 434 | /// * macOS: arrowCursor |
| 435 | static const SystemMouseCursor basic = SystemMouseCursor._(kind: 'basic' ); |
| 436 | |
| 437 | /// A cursor that emphasizes an element being clickable, such as a hyperlink. |
| 438 | /// |
| 439 | /// Typically the shape of a pointing hand. |
| 440 | /// |
| 441 | /// Corresponds to: |
| 442 | /// |
| 443 | /// * Android: TYPE_HAND |
| 444 | /// * Web: pointer |
| 445 | /// * Windows: IDC_HAND |
| 446 | /// * Windows UWP: CoreCursorType::Hand |
| 447 | /// * Linux: pointer |
| 448 | /// * macOS: pointingHandCursor |
| 449 | static const SystemMouseCursor click = SystemMouseCursor._(kind: 'click' ); |
| 450 | |
| 451 | /// A cursor indicating an operation that will not be carried out. |
| 452 | /// |
| 453 | /// Typically the shape of a circle with a diagonal line. May fall back to |
| 454 | /// [noDrop]. |
| 455 | /// |
| 456 | /// Corresponds to: |
| 457 | /// |
| 458 | /// * Android: TYPE_NO_DROP |
| 459 | /// * Web: not-allowed |
| 460 | /// * Windows: IDC_NO |
| 461 | /// * Windows UWP: CoreCursorType::UniversalNo |
| 462 | /// * Linux: not-allowed |
| 463 | /// * macOS: operationNotAllowedCursor |
| 464 | /// |
| 465 | /// See also: |
| 466 | /// |
| 467 | /// * [noDrop], which indicates somewhere that the current item may not be |
| 468 | /// dropped. |
| 469 | static const SystemMouseCursor forbidden = SystemMouseCursor._(kind: 'forbidden' ); |
| 470 | |
| 471 | /// A cursor indicating the status that the program is busy and therefore |
| 472 | /// can not be interacted with. |
| 473 | /// |
| 474 | /// Typically the shape of an hourglass or a watch. |
| 475 | /// |
| 476 | /// This cursor is not available as a system cursor on macOS. Although macOS |
| 477 | /// displays a "spinning ball" cursor when busy, it's handled by the OS and not |
| 478 | /// exposed for applications to choose. |
| 479 | /// |
| 480 | /// Corresponds to: |
| 481 | /// |
| 482 | /// * Android: TYPE_WAIT |
| 483 | /// * Windows: IDC_WAIT |
| 484 | /// * Web: wait |
| 485 | /// * Linux: wait |
| 486 | /// |
| 487 | /// See also: |
| 488 | /// |
| 489 | /// * [progress], which is similar to [wait] but the program can still be |
| 490 | /// interacted with. |
| 491 | static const SystemMouseCursor wait = SystemMouseCursor._(kind: 'wait' ); |
| 492 | |
| 493 | /// A cursor indicating the status that the program is busy but can still be |
| 494 | /// interacted with. |
| 495 | /// |
| 496 | /// Typically the shape of an arrow with an hourglass or a watch at the corner. |
| 497 | /// Does *not* fall back to [wait] if unavailable. |
| 498 | /// |
| 499 | /// Corresponds to: |
| 500 | /// |
| 501 | /// * Web: progress |
| 502 | /// * Windows: IDC_APPSTARTING |
| 503 | /// * Linux: progress |
| 504 | /// |
| 505 | /// See also: |
| 506 | /// |
| 507 | /// * [wait], which is similar to [progress] but the program can not be |
| 508 | /// interacted with. |
| 509 | static const SystemMouseCursor progress = SystemMouseCursor._(kind: 'progress' ); |
| 510 | |
| 511 | /// A cursor indicating somewhere the user can trigger a context menu. |
| 512 | /// |
| 513 | /// Typically the shape of an arrow with a small menu at the corner. |
| 514 | /// |
| 515 | /// Corresponds to: |
| 516 | /// |
| 517 | /// * Android: TYPE_CONTEXT_MENU |
| 518 | /// * Web: context-menu |
| 519 | /// * Linux: context-menu |
| 520 | /// * macOS: contextualMenuCursor |
| 521 | static const SystemMouseCursor contextMenu = SystemMouseCursor._(kind: 'contextMenu' ); |
| 522 | |
| 523 | /// A cursor indicating help information. |
| 524 | /// |
| 525 | /// Typically the shape of a question mark, or an arrow therewith. |
| 526 | /// |
| 527 | /// Corresponds to: |
| 528 | /// |
| 529 | /// * Android: TYPE_HELP |
| 530 | /// * Windows: IDC_HELP |
| 531 | /// * Windows UWP: CoreCursorType::Help |
| 532 | /// * Web: help |
| 533 | /// * Linux: help |
| 534 | static const SystemMouseCursor help = SystemMouseCursor._(kind: 'help' ); |
| 535 | |
| 536 | // SELECTION |
| 537 | |
| 538 | /// A cursor indicating selectable text. |
| 539 | /// |
| 540 | /// Typically the shape of a capital I. |
| 541 | /// |
| 542 | /// Corresponds to: |
| 543 | /// |
| 544 | /// * Android: TYPE_TEXT |
| 545 | /// * Web: text |
| 546 | /// * Windows: IDC_IBEAM |
| 547 | /// * Windows UWP: CoreCursorType::IBeam |
| 548 | /// * Linux: text |
| 549 | /// * macOS: IBeamCursor |
| 550 | static const SystemMouseCursor text = SystemMouseCursor._(kind: 'text' ); |
| 551 | |
| 552 | /// A cursor indicating selectable vertical text. |
| 553 | /// |
| 554 | /// Typically the shape of a capital I rotated to be horizontal. May fall back |
| 555 | /// to [text]. |
| 556 | /// |
| 557 | /// Corresponds to: |
| 558 | /// |
| 559 | /// * Android: TYPE_VERTICAL_TEXT |
| 560 | /// * Web: vertical-text |
| 561 | /// * Linux: vertical-text |
| 562 | /// * macOS: IBeamCursorForVerticalLayout |
| 563 | static const SystemMouseCursor verticalText = SystemMouseCursor._(kind: 'verticalText' ); |
| 564 | |
| 565 | /// A cursor indicating selectable table cells. |
| 566 | /// |
| 567 | /// Typically the shape of a hollow plus sign. |
| 568 | /// |
| 569 | /// Corresponds to: |
| 570 | /// |
| 571 | /// * Android: TYPE_CELL |
| 572 | /// * Web: cell |
| 573 | /// * Linux: cell |
| 574 | static const SystemMouseCursor cell = SystemMouseCursor._(kind: 'cell' ); |
| 575 | |
| 576 | /// A cursor indicating precise selection, such as selecting a pixel in a |
| 577 | /// bitmap. |
| 578 | /// |
| 579 | /// Typically the shape of a crosshair. |
| 580 | /// |
| 581 | /// Corresponds to: |
| 582 | /// |
| 583 | /// * Android: TYPE_CROSSHAIR |
| 584 | /// * Web: crosshair |
| 585 | /// * Windows: IDC_CROSS |
| 586 | /// * Windows UWP: CoreCursorType::Cross |
| 587 | /// * Linux: crosshair |
| 588 | /// * macOS: crosshairCursor |
| 589 | static const SystemMouseCursor precise = SystemMouseCursor._(kind: 'precise' ); |
| 590 | |
| 591 | // DRAG-AND-DROP |
| 592 | |
| 593 | /// A cursor indicating moving something. |
| 594 | /// |
| 595 | /// Typically the shape of four-way arrow. May fall back to [allScroll]. |
| 596 | /// |
| 597 | /// Corresponds to: |
| 598 | /// |
| 599 | /// * Android: TYPE_ALL_SCROLL |
| 600 | /// * Windows: IDC_SIZEALL |
| 601 | /// * Windows UWP: CoreCursorType::SizeAll |
| 602 | /// * Web: move |
| 603 | /// * Linux: move |
| 604 | static const SystemMouseCursor move = SystemMouseCursor._(kind: 'move' ); |
| 605 | |
| 606 | /// A cursor indicating something that can be dragged. |
| 607 | /// |
| 608 | /// Typically the shape of an open hand. |
| 609 | /// |
| 610 | /// Corresponds to: |
| 611 | /// |
| 612 | /// * Android: TYPE_GRAB |
| 613 | /// * Web: grab |
| 614 | /// * Linux: grab |
| 615 | /// * macOS: openHandCursor |
| 616 | static const SystemMouseCursor grab = SystemMouseCursor._(kind: 'grab' ); |
| 617 | |
| 618 | /// A cursor indicating something that is being dragged. |
| 619 | /// |
| 620 | /// Typically the shape of a closed hand. |
| 621 | /// |
| 622 | /// Corresponds to: |
| 623 | /// |
| 624 | /// * Android: TYPE_GRABBING |
| 625 | /// * Web: grabbing |
| 626 | /// * Linux: grabbing |
| 627 | /// * macOS: closedHandCursor |
| 628 | static const SystemMouseCursor grabbing = SystemMouseCursor._(kind: 'grabbing' ); |
| 629 | |
| 630 | /// A cursor indicating somewhere that the current item may not be dropped. |
| 631 | /// |
| 632 | /// Typically the shape of a hand with a [forbidden] sign at the corner. May |
| 633 | /// fall back to [forbidden]. |
| 634 | /// |
| 635 | /// Corresponds to: |
| 636 | /// |
| 637 | /// * Android: TYPE_NO_DROP |
| 638 | /// * Web: no-drop |
| 639 | /// * Windows: IDC_NO |
| 640 | /// * Windows UWP: CoreCursorType::UniversalNo |
| 641 | /// * Linux: no-drop |
| 642 | /// * macOS: operationNotAllowedCursor |
| 643 | /// |
| 644 | /// See also: |
| 645 | /// |
| 646 | /// * [forbidden], which indicates an action that will not be carried out. |
| 647 | static const SystemMouseCursor noDrop = SystemMouseCursor._(kind: 'noDrop' ); |
| 648 | |
| 649 | /// A cursor indicating that the current operation will create an alias of, or |
| 650 | /// a shortcut of the item. |
| 651 | /// |
| 652 | /// Typically the shape of an arrow with a shortcut icon at the corner. |
| 653 | /// |
| 654 | /// Corresponds to: |
| 655 | /// |
| 656 | /// * Android: TYPE_ALIAS |
| 657 | /// * Web: alias |
| 658 | /// * Linux: alias |
| 659 | /// * macOS: dragLinkCursor |
| 660 | static const SystemMouseCursor alias = SystemMouseCursor._(kind: 'alias' ); |
| 661 | |
| 662 | /// A cursor indicating that the current operation will copy the item. |
| 663 | /// |
| 664 | /// Typically the shape of an arrow with a boxed plus sign at the corner. |
| 665 | /// |
| 666 | /// Corresponds to: |
| 667 | /// |
| 668 | /// * Android: TYPE_COPY |
| 669 | /// * Web: copy |
| 670 | /// * Linux: copy |
| 671 | /// * macOS: dragCopyCursor |
| 672 | static const SystemMouseCursor copy = SystemMouseCursor._(kind: 'copy' ); |
| 673 | |
| 674 | /// A cursor indicating that the current operation will result in the |
| 675 | /// disappearance of the item. |
| 676 | /// |
| 677 | /// Typically the shape of an arrow with a cloud of smoke at the corner. |
| 678 | /// |
| 679 | /// Corresponds to: |
| 680 | /// |
| 681 | /// * macOS: disappearingItemCursor |
| 682 | static const SystemMouseCursor disappearing = SystemMouseCursor._(kind: 'disappearing' ); |
| 683 | |
| 684 | // RESIZING AND SCROLLING |
| 685 | |
| 686 | /// A cursor indicating scrolling in any direction. |
| 687 | /// |
| 688 | /// Typically the shape of a dot surrounded by 4 arrows. |
| 689 | /// |
| 690 | /// Corresponds to: |
| 691 | /// |
| 692 | /// * Android: TYPE_ALL_SCROLL |
| 693 | /// * Windows: IDC_SIZEALL |
| 694 | /// * Windows UWP: CoreCursorType::SizeAll |
| 695 | /// * Web: all-scroll |
| 696 | /// * Linux: all-scroll |
| 697 | /// |
| 698 | /// See also: |
| 699 | /// |
| 700 | /// * [move], which indicates moving in any direction. |
| 701 | static const SystemMouseCursor allScroll = SystemMouseCursor._(kind: 'allScroll' ); |
| 702 | |
| 703 | /// A cursor indicating resizing an object bidirectionally from its left or |
| 704 | /// right edge. |
| 705 | /// |
| 706 | /// Typically the shape of a bidirectional arrow pointing left and right. |
| 707 | /// |
| 708 | /// Corresponds to: |
| 709 | /// |
| 710 | /// * Android: TYPE_HORIZONTAL_DOUBLE_ARROW |
| 711 | /// * Web: ew-resize |
| 712 | /// * Windows: IDC_SIZEWE |
| 713 | /// * Windows UWP: CoreCursorType::SizeWestEast |
| 714 | /// * Linux: ew-resize |
| 715 | /// * macOS: resizeLeftRightCursor |
| 716 | static const SystemMouseCursor resizeLeftRight = SystemMouseCursor._(kind: 'resizeLeftRight' ); |
| 717 | |
| 718 | /// A cursor indicating resizing an object bidirectionally from its top or |
| 719 | /// bottom edge. |
| 720 | /// |
| 721 | /// Typically the shape of a bidirectional arrow pointing up and down. |
| 722 | /// |
| 723 | /// Corresponds to: |
| 724 | /// |
| 725 | /// * Android: TYPE_VERTICAL_DOUBLE_ARROW |
| 726 | /// * Web: ns-resize |
| 727 | /// * Windows: IDC_SIZENS |
| 728 | /// * Windows UWP: CoreCursorType::SizeNorthSouth |
| 729 | /// * Linux: ns-resize |
| 730 | /// * macOS: resizeUpDownCursor |
| 731 | static const SystemMouseCursor resizeUpDown = SystemMouseCursor._(kind: 'resizeUpDown' ); |
| 732 | |
| 733 | /// A cursor indicating resizing an object bidirectionally from its top left or |
| 734 | /// bottom right corner. |
| 735 | /// |
| 736 | /// Typically the shape of a bidirectional arrow pointing upper left and lower right. |
| 737 | /// |
| 738 | /// Corresponds to: |
| 739 | /// |
| 740 | /// * Android: TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW |
| 741 | /// * Web: nwse-resize |
| 742 | /// * Windows: IDC_SIZENWSE |
| 743 | /// * Windows UWP: CoreCursorType::SizeNorthwestSoutheast |
| 744 | /// * Linux: nwse-resize |
| 745 | static const SystemMouseCursor resizeUpLeftDownRight = SystemMouseCursor._( |
| 746 | kind: 'resizeUpLeftDownRight' , |
| 747 | ); |
| 748 | |
| 749 | /// A cursor indicating resizing an object bidirectionally from its top right or |
| 750 | /// bottom left corner. |
| 751 | /// |
| 752 | /// Typically the shape of a bidirectional arrow pointing upper right and lower left. |
| 753 | /// |
| 754 | /// Corresponds to: |
| 755 | /// |
| 756 | /// * Android: TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW |
| 757 | /// * Windows: IDC_SIZENESW |
| 758 | /// * Windows UWP: CoreCursorType::SizeNortheastSouthwest |
| 759 | /// * Web: nesw-resize |
| 760 | /// * Linux: nesw-resize |
| 761 | static const SystemMouseCursor resizeUpRightDownLeft = SystemMouseCursor._( |
| 762 | kind: 'resizeUpRightDownLeft' , |
| 763 | ); |
| 764 | |
| 765 | /// A cursor indicating resizing an object from its top edge. |
| 766 | /// |
| 767 | /// Typically the shape of an arrow pointing up. May fallback to [resizeUpDown]. |
| 768 | /// |
| 769 | /// Corresponds to: |
| 770 | /// |
| 771 | /// * Android: TYPE_VERTICAL_DOUBLE_ARROW |
| 772 | /// * Web: n-resize |
| 773 | /// * Windows: IDC_SIZENS |
| 774 | /// * Windows UWP: CoreCursorType::SizeNorthSouth |
| 775 | /// * Linux: n-resize |
| 776 | /// * macOS: resizeUpCursor |
| 777 | static const SystemMouseCursor resizeUp = SystemMouseCursor._(kind: 'resizeUp' ); |
| 778 | |
| 779 | /// A cursor indicating resizing an object from its bottom edge. |
| 780 | /// |
| 781 | /// Typically the shape of an arrow pointing down. May fallback to [resizeUpDown]. |
| 782 | /// |
| 783 | /// Corresponds to: |
| 784 | /// |
| 785 | /// * Android: TYPE_VERTICAL_DOUBLE_ARROW |
| 786 | /// * Web: s-resize |
| 787 | /// * Windows: IDC_SIZENS |
| 788 | /// * Windows UWP: CoreCursorType::SizeNorthSouth |
| 789 | /// * Linux: s-resize |
| 790 | /// * macOS: resizeDownCursor |
| 791 | static const SystemMouseCursor resizeDown = SystemMouseCursor._(kind: 'resizeDown' ); |
| 792 | |
| 793 | /// A cursor indicating resizing an object from its left edge. |
| 794 | /// |
| 795 | /// Typically the shape of an arrow pointing left. May fallback to [resizeLeftRight]. |
| 796 | /// |
| 797 | /// Corresponds to: |
| 798 | /// |
| 799 | /// * Android: TYPE_HORIZONTAL_DOUBLE_ARROW |
| 800 | /// * Web: w-resize |
| 801 | /// * Windows: IDC_SIZEWE |
| 802 | /// * Windows UWP: CoreCursorType::SizeWestEast |
| 803 | /// * Linux: w-resize |
| 804 | /// * macOS: resizeLeftCursor |
| 805 | static const SystemMouseCursor resizeLeft = SystemMouseCursor._(kind: 'resizeLeft' ); |
| 806 | |
| 807 | /// A cursor indicating resizing an object from its right edge. |
| 808 | /// |
| 809 | /// Typically the shape of an arrow pointing right. May fallback to [resizeLeftRight]. |
| 810 | /// |
| 811 | /// Corresponds to: |
| 812 | /// |
| 813 | /// * Android: TYPE_HORIZONTAL_DOUBLE_ARROW |
| 814 | /// * Web: e-resize |
| 815 | /// * Windows: IDC_SIZEWE |
| 816 | /// * Windows UWP: CoreCursorType::SizeWestEast |
| 817 | /// * Linux: e-resize |
| 818 | /// * macOS: resizeRightCursor |
| 819 | static const SystemMouseCursor resizeRight = SystemMouseCursor._(kind: 'resizeRight' ); |
| 820 | |
| 821 | /// A cursor indicating resizing an object from its top-left corner. |
| 822 | /// |
| 823 | /// Typically the shape of an arrow pointing upper left. May fallback to [resizeUpLeftDownRight]. |
| 824 | /// |
| 825 | /// Corresponds to: |
| 826 | /// |
| 827 | /// * Android: TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW |
| 828 | /// * Web: nw-resize |
| 829 | /// * Windows: IDC_SIZENWSE |
| 830 | /// * Windows UWP: CoreCursorType::SizeNorthwestSoutheast |
| 831 | /// * Linux: nw-resize |
| 832 | static const SystemMouseCursor resizeUpLeft = SystemMouseCursor._(kind: 'resizeUpLeft' ); |
| 833 | |
| 834 | /// A cursor indicating resizing an object from its top-right corner. |
| 835 | /// |
| 836 | /// Typically the shape of an arrow pointing upper right. May fallback to [resizeUpRightDownLeft]. |
| 837 | /// |
| 838 | /// Corresponds to: |
| 839 | /// |
| 840 | /// * Android: TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW |
| 841 | /// * Web: ne-resize |
| 842 | /// * Windows: IDC_SIZENESW |
| 843 | /// * Windows UWP: CoreCursorType::SizeNortheastSouthwest |
| 844 | /// * Linux: ne-resize |
| 845 | static const SystemMouseCursor resizeUpRight = SystemMouseCursor._(kind: 'resizeUpRight' ); |
| 846 | |
| 847 | /// A cursor indicating resizing an object from its bottom-left corner. |
| 848 | /// |
| 849 | /// Typically the shape of an arrow pointing lower left. May fallback to [resizeUpRightDownLeft]. |
| 850 | /// |
| 851 | /// Corresponds to: |
| 852 | /// |
| 853 | /// * Android: TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW |
| 854 | /// * Web: sw-resize |
| 855 | /// * Windows: IDC_SIZENESW |
| 856 | /// * Windows UWP: CoreCursorType::SizeNortheastSouthwest |
| 857 | /// * Linux: sw-resize |
| 858 | static const SystemMouseCursor resizeDownLeft = SystemMouseCursor._(kind: 'resizeDownLeft' ); |
| 859 | |
| 860 | /// A cursor indicating resizing an object from its bottom-right corner. |
| 861 | /// |
| 862 | /// Typically the shape of an arrow pointing lower right. May fallback to [resizeUpLeftDownRight]. |
| 863 | /// |
| 864 | /// Corresponds to: |
| 865 | /// |
| 866 | /// * Android: TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW |
| 867 | /// * Web: se-resize |
| 868 | /// * Windows: IDC_SIZENWSE |
| 869 | /// * Windows UWP: CoreCursorType::SizeNorthwestSoutheast |
| 870 | /// * Linux: se-resize |
| 871 | static const SystemMouseCursor resizeDownRight = SystemMouseCursor._(kind: 'resizeDownRight' ); |
| 872 | |
| 873 | /// A cursor indicating resizing a column, or an item horizontally. |
| 874 | /// |
| 875 | /// Typically the shape of arrows pointing left and right with a vertical bar |
| 876 | /// separating them. May fallback to [resizeLeftRight]. |
| 877 | /// |
| 878 | /// Corresponds to: |
| 879 | /// |
| 880 | /// * Android: TYPE_HORIZONTAL_DOUBLE_ARROW |
| 881 | /// * Web: col-resize |
| 882 | /// * Windows: IDC_SIZEWE |
| 883 | /// * Windows UWP: CoreCursorType::SizeWestEast |
| 884 | /// * Linux: col-resize |
| 885 | /// * macOS: resizeLeftRightCursor |
| 886 | static const SystemMouseCursor resizeColumn = SystemMouseCursor._(kind: 'resizeColumn' ); |
| 887 | |
| 888 | /// A cursor indicating resizing a row, or an item vertically. |
| 889 | /// |
| 890 | /// Typically the shape of arrows pointing up and down with a horizontal bar |
| 891 | /// separating them. May fallback to [resizeUpDown]. |
| 892 | /// |
| 893 | /// Corresponds to: |
| 894 | /// |
| 895 | /// * Android: TYPE_VERTICAL_DOUBLE_ARROW |
| 896 | /// * Web: row-resize |
| 897 | /// * Windows: IDC_SIZENS |
| 898 | /// * Windows UWP: CoreCursorType::SizeNorthSouth |
| 899 | /// * Linux: row-resize |
| 900 | /// * macOS: resizeUpDownCursor |
| 901 | static const SystemMouseCursor resizeRow = SystemMouseCursor._(kind: 'resizeRow' ); |
| 902 | |
| 903 | // OTHER OPERATIONS |
| 904 | |
| 905 | /// A cursor indicating zooming in. |
| 906 | /// |
| 907 | /// Typically a magnifying glass with a plus sign. |
| 908 | /// |
| 909 | /// Corresponds to: |
| 910 | /// |
| 911 | /// * Android: TYPE_ZOOM_IN |
| 912 | /// * Web: zoom-in |
| 913 | /// * Linux: zoom-in |
| 914 | static const SystemMouseCursor zoomIn = SystemMouseCursor._(kind: 'zoomIn' ); |
| 915 | |
| 916 | /// A cursor indicating zooming out. |
| 917 | /// |
| 918 | /// Typically a magnifying glass with a minus sign. |
| 919 | /// |
| 920 | /// Corresponds to: |
| 921 | /// |
| 922 | /// * Android: TYPE_ZOOM_OUT |
| 923 | /// * Web: zoom-out |
| 924 | /// * Linux: zoom-out |
| 925 | static const SystemMouseCursor zoomOut = SystemMouseCursor._(kind: 'zoomOut' ); |
| 926 | } |
| 927 | |