Skip to content

Commit

Permalink
Further changes to message loop issues on Mac (#442).
Browse files Browse the repository at this point in the history
Minor fix to CefAppProtocol implementation, see CEF Forum
topic for details.

Updated Qt example so that message loop work is not
called in a timer when message pump is enabled. This
is not required.

In wxPython apps it is still required to enable both
message pump and message looper timer work.
  • Loading branch information
cztomczak committed Aug 8, 2018
1 parent d32f4b6 commit 18c4a58
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 38 deletions.
6 changes: 4 additions & 2 deletions api/ApplicationSettings.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,10 @@ on these platforms. See [Issue #246](https://github.com/cztomczak/cefpython/issu
for more details.

IMPORTANT: Currently there are issues on Mac with both message loop work
and external message pump. The working solution is to call
a message loop work in a timer and enable external message pump
and external message pump. In Qt apps calling message loop
work in a timer doesn't work anymore, you have to use external
message pump. In wxPython apps it is required to call a message
loop work in a timer and enable external message pump
both at the same time (an incorrect approach, but it works).
This is just a temporary solution and how this affects
performance was not tested. See [Issue #442](../../../issues/442)
Expand Down
26 changes: 16 additions & 10 deletions docs/Migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Table of contents:
* [v66+ Threads removed: TID_DB, TID_PROCESS_LAUNCHER, TID_CACHE](#v66-threads-removed-tid_db-tid_process_launcher-tid_cache)
* [v66+ cef.Request.Flags changed](#v66-cefrequestflags-changed)
* [v66+ RequestHandler.GetCookieManager not getting called in some cases](#v66-requesthandlergetcookiemanager-not-getting-called-in-some-cases)
* [v66+ Changes to Mac apps that integrate into existing message loops (Qt, wxPython)](#v66-changes-to-mac-apps-that-integrate-into-existing-message-loops-qt-wxpython)
* [v66+ Changes to Mac apps that integrate into existing message loop (Qt, wxPython)](#v66-changes-to-mac-apps-that-integrate-into-existing-message-loop-qt-wxpython)



Expand Down Expand Up @@ -386,18 +386,24 @@ callback is not getting called due to a race condition.
This bug is to be fixed in Issue [#429](../../../issues/429).


## v66+ Changes to Mac apps that integrate into existing message loops (Qt, wxPython)
## v66+ Changes to Mac apps that integrate into existing message loop (Qt, wxPython)

The `qt.py` and `wxpython.py` examples were modified to set
In Qt apps calling message loop work in a timer doesn't work anymore.
You have to enable external message pump by setting
ApplicationSettings.[external_message_pump](../api/ApplicationSettings.md#external_message_pump)
to `True`. Due to Issue [#442](../../../issues/442) it is required
to implement both approaches to integrating with existing message
loops at the same time:
to `True`. The `qt.py` example was updated to disable calling
message loop work in a timer. External message pump
is a recommended way over calling message loop work in a timer on Mac,
so this should make Qt apps work smoothly.

In wxPython apps you have to implement both approaches for
integrating with existing message loop at the same time:
1. Call `cef.DoMessageLoopWork` in a 10ms timer
2. Set `ApplicationSettings.external_message_pump` to True

This is not a correct approach and is only a temporary fix. More
testing is required to check if that resolves all the issues with message
loop freezing. Only basic testing was performed. It was not tested of
how this change affects performance.
This is not a correct approach and is only a temporary fix for wxPython
apps. More testing is required to check if that resolves all the issues
with message loop freezing. Only basic testing was performed. It was not
tested of how this change affects performance.

See Issue [#442](../../../issues/442) for more details on the issues.
12 changes: 7 additions & 5 deletions examples/qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,19 @@ def main():
settings = {}
if MAC:
# Issue #442 requires enabling message pump on Mac
# and calling message loop work in a timer both at
# the same time. This is an incorrect approach
# and only a temporary solution.
# in Qt example. Calling cef.DoMessageLoopWork in a timer
# doesn't work anymore.
settings["external_message_pump"] = True

cef.Initialize(settings)
app = CefApplication(sys.argv)
main_window = MainWindow()
main_window.show()
main_window.activateWindow()
main_window.raise_()
app.exec_()
app.stopTimer()
if not cef.GetAppSetting("external_message_pump"):
app.stopTimer()
del main_window # Just to be safe, similarly to "del app"
del app # Must destroy app object before calling Shutdown
cef.Shutdown()
Expand Down Expand Up @@ -266,7 +267,8 @@ def resizeEvent(self, event):
class CefApplication(QApplication):
def __init__(self, args):
super(CefApplication, self).__init__(args)
self.timer = self.createTimer()
if not cef.GetAppSetting("external_message_pump"):
self.timer = self.createTimer()
self.setupIcon()

def createTimer(self):
Expand Down
33 changes: 18 additions & 15 deletions examples/wxpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@
LINUX = (platform.system() == "Linux")
MAC = (platform.system() == "Darwin")

if MAC:
try:
# noinspection PyUnresolvedReferences
from AppKit import NSApp
except ImportError:
print("[wxpython.py] Error: PyObjC package is missing, "
"cannot fix Issue #371")
print("[wxpython.py] To install PyObjC type: "
"pip install -U pyobjc")
sys.exit(1)

# Configuration
WIDTH = 800
HEIGHT = 600
Expand All @@ -37,7 +48,7 @@ def main():
# Issue #442 requires enabling message pump on Mac
# and calling message loop work in a timer both at
# the same time. This is an incorrect approach
# and only a temporary solution.
# and only a temporary fix.
settings["external_message_pump"] = True
if WINDOWS:
# noinspection PyUnresolvedReferences, PyArgumentList
Expand Down Expand Up @@ -87,20 +98,12 @@ def __init__(self):
self.browser_panel.Bind(wx.EVT_SIZE, self.OnSize)

if MAC:
try:
# noinspection PyUnresolvedReferences
from AppKit import NSApp
# Make the content view for the window have a layer.
# This will make all sub-views have layers. This is
# necessary to ensure correct layer ordering of all
# child views and their layers. This fixes Window
# glitchiness during initial loading on Mac (Issue #371).
NSApp.windows()[0].contentView().setWantsLayer_(True)
except ImportError:
print("[wxpython.py] Warning: PyObjC package is missing, "
"cannot fix Issue #371")
print("[wxpython.py] To install PyObjC type: "
"pip install -U pyobjc")
# Make the content view for the window have a layer.
# This will make all sub-views have layers. This is
# necessary to ensure correct layer ordering of all
# child views and their layers. This fixes Window
# glitchiness during initial loading on Mac (Issue #371).
NSApp.windows()[0].contentView().setWantsLayer_(True)

if LINUX:
# On Linux must show before embedding browser, so that handle
Expand Down
8 changes: 5 additions & 3 deletions src/cefpython.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,7 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):

Debug("Initialize() called")

# Mac initialization. Need to call NSApplication.sharedApplication()
# and do NSApplication methods swizzling to implement
# CrAppControlProtocol. See Issue 156.
# Additional initialization on Mac, see util_mac.mm.
IF UNAME_SYSNAME == "Darwin":
MacInitialize()

Expand Down Expand Up @@ -944,6 +942,10 @@ def Shutdown():
with nogil:
CefShutdown()

# Additional cleanup on Mac, see util_mac.mm.
IF UNAME_SYSNAME == "Darwin":
MacShutdown()

def SetOsModalLoop(py_bool modalLoop):
cdef cpp_bool cefModalLoop = bool(modalLoop)
with nogil:
Expand Down
1 change: 1 addition & 0 deletions src/client_handler/util_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "include/cef_browser.h"

void MacInitialize();
void MacShutdown();
void MacSetWindowTitle(CefRefPtr<CefBrowser> browser, char* title);

#endif // CEFPYTHON_UTIL_MAC_H_
24 changes: 21 additions & 3 deletions src/client_handler/util_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

// Copyright (c) 2015 CEF Python, see the Authors file.
// All rights reserved. Licensed under BSD 3-clause license.
// Project website: https://github.com/cztomczak/cefpython

// Some code was copied from here:
// java-cef: src/master/native/util_mac.mm
// upstream cef: src/tests/ceftests/run_all_unittests_mac.mm
// upstream cef: src/tests/cefclient/cefclient_mac.mm
// upstream cef: src/tests/cefsimple/cefsimple_mac.mm

#import "util_mac.h"
#import <Cocoa/Cocoa.h>
#include <objc/runtime.h>
Expand All @@ -11,13 +21,14 @@

namespace {

// static NSAutoreleasePool* g_autopool = nil;
BOOL g_handling_send_event = false;

} // namespace

// Add the necessary CrAppControlProtocol
// functionality to NSApplication using categories and swizzling.
@interface NSApplication (CEFPythonApplication)
// Add the necessary CefAppProtocol functionality to NSApplication
// using categories and swizzling (Issue #442, Issue #156).
@interface NSApplication (CEFPythonApplication)<CefAppProtocol>

- (BOOL)isHandlingSendEvent;
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent;
Expand Down Expand Up @@ -63,9 +74,16 @@ - (void)_swizzled_terminate:(id)sender {
@end

void MacInitialize() {
// OFF: it's causing a crash during shutdown release
// g_autopool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
}

void MacShutdown() {
// OFF: it's causing a crash during shutdown release
// [g_autopool release];
}

void MacSetWindowTitle(CefRefPtr<CefBrowser> browser, char* title) {
NSView* view = browser->GetHost()->GetWindowHandle();
NSString* nstitle = [NSString stringWithFormat:@"%s" , title];
Expand Down
1 change: 1 addition & 0 deletions src/extern/mac.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ from cef_browser cimport CefBrowser

cdef extern from "client_handler/util_mac.h":
void MacInitialize()
void MacShutdown()
void MacSetWindowTitle(CefRefPtr[CefBrowser] browser, char* title)

0 comments on commit 18c4a58

Please sign in to comment.