File: headless_screen_mac.mm

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (92 lines) | stat: -rw-r--r-- 3,016 bytes parent folder | download | duplicates (5)
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
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "headless/lib/browser/headless_screen_mac.h"

#import <Cocoa/Cocoa.h>

#include <optional>

#import "base/apple/scoped_objc_class_swizzler.h"
#include "base/check_deref.h"
#include "components/headless/display_util/headless_display_util.h"
#include "ui/display/screen.h"
#import "ui/gfx/mac/coordinate_conversion.h"

// Class to donate the headless screen configuration aware implementation of
// -[NSScreen frame].
@interface HeadlessScreenNSScreenDonor : NSObject
- (NSRect)frame;
@end

@implementation HeadlessScreenNSScreenDonor
- (NSRect)frame {
  display::Screen& screen = CHECK_DEREF(display::Screen::GetScreen());
  display::Display primary_display = screen.GetPrimaryDisplay();
  const gfx::Rect bounds = primary_display.bounds();
  CHECK_EQ(bounds.x(), 0);
  CHECK_EQ(bounds.y(), 0);
  return NSMakeRect(0, 0, bounds.width(), bounds.height());
}
@end

namespace headless {

// Holds Apple Class Swizzler instance.
class HeadlessScreenMac::ClassSwizzler {
 public:
  ClassSwizzler() {
    swizzler_ = std::make_unique<base::apple::ScopedObjCClassSwizzler>(
        [NSScreen class], [HeadlessScreenNSScreenDonor class],
        @selector(frame));
  }

 private:
  std::unique_ptr<base::apple::ScopedObjCClassSwizzler> swizzler_;
};

// static
HeadlessScreenMac* HeadlessScreenMac::Create(
    const gfx::Size& window_size,
    std::string_view screen_info_spec) {
  return new HeadlessScreenMac(window_size, screen_info_spec);
}

HeadlessScreenMac::HeadlessScreenMac(const gfx::Size& window_size,
                                     std::string_view screen_info_spec)
    : HeadlessScreen(window_size, screen_info_spec) {
  // Override [NSScreen frame] with the headless screen aware implementation.
  class_swizzler_ = std::make_unique<ClassSwizzler>();
}

HeadlessScreenMac::~HeadlessScreenMac() = default;

display::Display HeadlessScreenMac::GetDisplayNearestWindow(
    gfx::NativeWindow window) const {
  // There are no NSWindows in headless, so this method should not be called at
  // all, however content::RenderWidgetHostViewMac ctor calls it with nil
  // keyWindow, so return our best guess.
  return GetPrimaryDisplay();
}

display::Display HeadlessScreenMac::GetDisplayNearestView(
    gfx::NativeView view) const {
  // On Mac native window (i.e. NSWindow) does not exist in headless, so we have
  // to rely on native view (i.e. NSView) for nearest display determination.
  if (view && view.GetNativeNSView()) {
    NSView* ns_view = view.GetNativeNSView();
    while (NSView* parent = [ns_view superview]) {
      ns_view = parent;
    }

    const gfx::Rect bounds = gfx::ScreenRectFromNSRect([ns_view frame]);
    if (std::optional<display::Display> display =
            GetDisplayFromScreenRect(display_list().displays(), bounds)) {
      return display.value();
    }
  }
  return GetPrimaryDisplay();
}

}  // namespace headless