Repository navigation
Expand file tree
/
Copy pathmain_message_loop_external_pump_mac.mm
More file actions
163 lines (127 loc) · 4.4 KB
/
Copy pathmain_message_loop_external_pump_mac.mm
File metadata and controls
163 lines (127 loc) · 4.4 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "main_message_loop_external_pump.h"
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include "include/cef_app.h"
@class EventHandler;
class MainMessageLoopExternalPumpMac : public MainMessageLoopExternalPump {
public:
MainMessageLoopExternalPumpMac();
~MainMessageLoopExternalPumpMac();
// MainMessageLoopStd methods:
void Quit() OVERRIDE;
int Run() OVERRIDE;
// MainMessageLoopExternalPump methods:
void OnScheduleMessagePumpWork(int64 delay_ms) OVERRIDE;
// Internal methods used for processing the event callbacks. They are public
// for simplicity but should not be used directly.
void HandleScheduleWork(int64 delay_ms);
void HandleTimerTimeout();
protected:
// MainMessageLoopExternalPump methods:
void SetTimer(int64 delay_ms) OVERRIDE;
void KillTimer() OVERRIDE;
bool IsTimerPending() OVERRIDE { return timer_ != nil; }
private:
// Owner thread that will run events.
NSThread* owner_thread_;
// Pending work timer.
NSTimer* timer_;
// Used to handle event callbacks on the owner thread.
EventHandler* event_handler_;
};
// Object that handles event callbacks on the owner thread.
@interface EventHandler : NSObject {
@private
MainMessageLoopExternalPumpMac* pump_;
}
- (id)initWithPump:(MainMessageLoopExternalPumpMac*)pump;
- (void)scheduleWork:(NSNumber*)delay_ms;
- (void)timerTimeout:(id)obj;
@end
@implementation EventHandler
- (id)initWithPump:(MainMessageLoopExternalPumpMac*)pump {
if (self = [super init]) {
pump_ = pump;
}
return self;
}
- (void)scheduleWork:(NSNumber*)delay_ms {
pump_->HandleScheduleWork([delay_ms integerValue]);
}
- (void)timerTimeout:(id)obj {
pump_->HandleTimerTimeout();
}
@end
MainMessageLoopExternalPumpMac::MainMessageLoopExternalPumpMac()
: owner_thread_([[NSThread currentThread] retain]),
timer_(nil) {
event_handler_ = [[[EventHandler alloc] initWithPump:this] retain];
}
MainMessageLoopExternalPumpMac::~MainMessageLoopExternalPumpMac() {
KillTimer();
[owner_thread_ release];
[event_handler_ release];
}
void MainMessageLoopExternalPumpMac::Quit() {
[NSApp stop:nil];
}
int MainMessageLoopExternalPumpMac::Run() {
// Run the message loop.
[NSApp run];
KillTimer();
// We need to run the message pump until it is idle. However we don't have
// that information here so we run the message loop "for a while".
for (int i = 0; i < 10; ++i) {
// Let default runloop observers run.
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, 1);
// Do some work.
CefDoMessageLoopWork();
// Sleep to allow the CEF proc to do work.
[NSThread sleepForTimeInterval: 0.05];
}
return 0;
}
void MainMessageLoopExternalPumpMac::OnScheduleMessagePumpWork(int64 delay_ms) {
// This method may be called on any thread.
NSNumber* number = [NSNumber numberWithInt:static_cast<int>(delay_ms)];
[event_handler_ performSelector:@selector(scheduleWork:)
onThread:owner_thread_
withObject:number
waitUntilDone:NO];
}
void MainMessageLoopExternalPumpMac::HandleScheduleWork(int64 delay_ms) {
OnScheduleWork(delay_ms);
}
void MainMessageLoopExternalPumpMac::HandleTimerTimeout() {
OnTimerTimeout();
}
void MainMessageLoopExternalPumpMac::SetTimer(int64 delay_ms) {
DCHECK_GT(delay_ms, 0);
DCHECK(!timer_);
const double delay_s = static_cast<double>(delay_ms) / 1000.0;
timer_ = [[NSTimer timerWithTimeInterval: delay_s
target: event_handler_
selector: @selector(timerTimeout:)
userInfo: nil
repeats: NO] retain];
// Add the timer to default and tracking runloop modes.
NSRunLoop* owner_runloop = [NSRunLoop currentRunLoop];
[owner_runloop addTimer: timer_ forMode: NSRunLoopCommonModes];
[owner_runloop addTimer: timer_ forMode: NSEventTrackingRunLoopMode];
}
void MainMessageLoopExternalPumpMac::KillTimer() {
if (timer_ != nil) {
[timer_ invalidate];
[timer_ release];
timer_ = nil;
}
}
// static
scoped_ptr<MainMessageLoopExternalPump>
MainMessageLoopExternalPump::Create() {
return scoped_ptr<MainMessageLoopExternalPump>(
new MainMessageLoopExternalPumpMac());
}