title: CEFpython browser loads blank white page on windows, but works perfectly on mac
body: <p>I edited the code from CEFpython's github page, the one that uses wxPython.  It works fine on my mac but when the browser launches on windows it only loads a blank white screen.</p>
  
  <p>I'm trying out both wxPython and CEFpython for the first time.
  I am trying to use wxPython as a wrapper for the cef browser, using django as the server in the background. 
   I followed the tutorial on CEFpython's Github page <a href="https://github.com/cztomczak/cefpython/blob/master/examples/wxpython.py" rel="nofollow noreferrer">https://github.com/cztomczak/cefpython/blob/master/examples/wxpython.py</a>
  I edited it and it works on mac but when I tried to run it on windows all I get is a blank white page with a small square top left.
  What I've tried:
  1) I tried loading google.com instead of 127.0.0.1:8000.
  2) I guessed that it might have been that the server had not started before the frame containing the browser, I used a thread to delay for about 15 seconds and called Reload on the browser
  3) It works perfectly on Mac so I edited the code and leaving only the windows related code, the same thing. 
  Please Help!
  Sorry if I pasted all the code, I really have no idea what I'm doing wrong.
  Thank you in advance. </p>
  
  <p>browser.py </p>
  
  <pre class="lang-py prettyprint-override"><code>import wx
  from cefpython3 import cefpython as cef
  import sys
  import platform
  import os
  
  # Platforms
  WINDOWS = (platform.system() == "Windows")
  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)
  
  
  def check_versions():
      print("[wxpython.py] CEF Python {ver}".format(ver=cef.__version__))
      print("[wxpython.py] Python {ver} {arch}".format(
              ver=platform.python_version(), arch=platform.architecture()[0]))
      print("[wxpython.py] wxPython {ver}".format(ver=wx.version()))
      # CEF Python version requirement
      assert cef.__version__ &gt;= "66.0", "CEF Python v66.0+ required to run this"
  
  
  def scale_window_size_for_high_dpi(width, height):
      """Scale window size for high DPI devices. This func can be
      called on all operating systems, but scales only for Windows.
      If scaled value is bigger than the work area on the display
      then it will be reduced."""
      if not WINDOWS:
          return width, height
      (_, _, max_width, max_height) = wx.GetClientDisplayRect().Get()
      # noinspection PyUnresolvedReferences
      (width, height) = cef.DpiAware.Scale((width, height))
      if width &gt; max_width:
          width = max_width
      if height &gt; max_height:
          height = max_height
      return width, height
  
  
  class BrowserFrame(wx.Frame):
  
      def __init__(self):
          self.browser = None
          wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title="NETS Framework")
          self.ShowFullScreen(True)
          # Set wx.WANTS_CHARS style for the keyboard to work.
          # This style also needs to be set for all parent controls.
          self.browser_panel = wx.Panel(self, style=wx.WANTS_CHARS)
          self.browser_panel.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
          self.browser_panel.Bind(wx.EVT_SIZE, self.OnSize)
          check_versions()
          sys.excepthook = cef.ExceptHook  # To shutdown all CEF processes on error
          settings = {}
          settings["context_menu"] = {'enabled':False}
          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 fix.
              settings["external_message_pump"] = True
  
          if WINDOWS:
              # noinspection PyUnresolvedReferences, PyArgumentList
              cef.DpiAware.EnableHighDpiSupport()
          cef.Initialize(settings=settings)
          if MAC:
              # 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
              # is available (Issue #347).
              self.Show()
              # In wxPython 3.0 and wxPython 4.0 on Linux handle is
              # still not yet available, so must delay embedding browser
              # (Issue #349).
              if wx.version().startswith("3.") or wx.version().startswith("4."):
                  wx.CallLater(100, self.embed_browser)
              else:
                  # This works fine in wxPython 2.8 on Linux
                  self.embed_browser()
          else:
              self.embed_browser()
              self.Show()
  
      def embed_browser(self):
          window_info = cef.WindowInfo()
          (width, height) = self.browser_panel.GetClientSize().Get()
          assert self.browser_panel.GetHandle()
          window_info.SetAsChild(self.browser_panel.GetHandle(),
                                 [0, 0, width, height])
          self.browser = cef.CreateBrowserSync(window_info,
                                               url="http://127.0.0.1:8000")
          self.browser.SetClientHandler(FocusHandler())
  
      def OnSetFocus(self, _):
          if not self.browser:
              return
          if WINDOWS:
              cef.WindowUtils.OnSetFocus(self.browser_panel.GetHandle(),
                                         0, 0, 0)
          self.browser.SetFocus(True)
  
      def OnSize(self, _):
          if not self.browser:
              return
          if WINDOWS:
              cef.WindowUtils.OnSize(self.browser_panel.GetHandle(),
                                     0, 0, 0)
          elif LINUX:
              (x, y) = (0, 0)
              (width, height) = self.browser_panel.GetSize().Get()
              self.browser.SetBounds(x, y, width, height)
          self.browser.NotifyMoveOrResizeStarted()
  
      def OnClose(self, event):
          print("[wxpython.py] OnClose called")
          if not self.browser:
              # May already be closing, may be called multiple times on Mac
              return
  
          if not MAC:
              # On Mac shutdown is called in OnClose
              cef.Shutdown()
  
          if MAC:
              # On Mac things work differently, other steps are required
              self.browser.CloseBrowser()
              self.clear_browser_references()
              self.Destroy()
              global g_count_windows
              g_count_windows -= 1
              if g_count_windows == 0:
                  cef.Shutdown()
                  wx.GetApp().ExitMainLoop()
                  # Call _exit otherwise app exits with code 255 (Issue #162).
                  # noinspection PyProtectedMember
                  os._exit(0)
          else:
              # Calling browser.CloseBrowser() and/or self.Destroy()
              # in OnClose may cause app crash on some paltforms in
              # some use cases, details in Issue #107.
              self.browser.ParentWindowWillClose()
              event.Skip()
              self.clear_browser_references()
  
      def clear_browser_references(self):
          # Clear browser references that you keep anywhere in your
          # code. All references must be cleared for CEF to shutdown cleanly.
          self.browser = None
  
  
  class FocusHandler(object):
      def OnGotFocus(self, browser, **_):
          # Temporary fix for focus issues on Linux (Issue #284).
          if LINUX:
              print("[wxpython.py] FocusHandler.OnGotFocus:"
                    " keyboard focus fix (Issue #284)")
              browser.SetFocus(True)
  
  </code></pre>
  
  <p>main.py</p>
  
  <pre class="lang-py prettyprint-override"><code>#!/usr/bin/env python
  import wx
  import time
  from icecream import ic
  
  from threading import Thread
  from source.Nets.wxBrowser import BrowserFrame
  from source.Nets.server import start_server_subprocess
  
  
  # This puts the server in a subprocess, don't forget to close it
  class ServerThread(Thread):
      def __init__(self):
          Thread.__init__(self)
          self.start()
  
      def run(self):
          ic("Starting Server")
          start_server_subprocess()
  
  
  class StartPanel(wx.Panel):
  
      def __init__(self, parent):
          wx.Panel.__init__(self, parent)
          # create the text display to basic info
          self.app_info = wx.StaticText(self, label="Enter the IP Address of Mother Server"
                                                    " \n If you want to use the practice mode simply click"
                                                    " practice mode button and carry on with the program")
          # create the text entry box to enter the ip
          self.ip_address = wx.TextCtrl(self, value="http://127.0.0.1:8000", )
          # create two buttons to either select client mode or practice mode
          self.client_button = wx.Button(self, -1, "Client Mode", )
          self.practice_button = wx.Button(self, -1, "Practice Mode", )
          # Add the buttons to a Horizontal sizer
          # This allows the client and practice buttons to stack side by side
          self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
          self.sizer2.Add(self.client_button, 1, wx.EXPAND)
          self.sizer2.Add(self.practice_button, 1, wx.EXPAND)
          # Add the app_info and ip_text to a vertical sizer to allow them
          # stack on each other add the sizer2 to the button
          self.sizer = wx.BoxSizer(wx.VERTICAL)
          self.sizer.Add(self.app_info, 1, wx.EXPAND)
          self.sizer.Add(self.ip_address, 1, wx.EXPAND)
          self.sizer.Add(self.sizer2, 0, wx.EXPAND)
          self.SetSizer(self.sizer)
          self.SetAutoLayout(1)
          self.sizer.Fit(self)
          # Create button Bind actions
          self.practice_button.Bind(wx.EVT_BUTTON, self.onPractice)
          self.Bind(wx.EVT_BUTTON, self.onClient, self.client_button)
  
      def onClient(self, event):
          # load the new frame using max screen and browser to the
          # IP provided, use thread to wait, and use error handling
          # to fail gracefully
          print("Hit client")
  
      def onPractice(self, event):
          # Use a thread to start the local django server
          # Verify that the server has started
          # TODO At some point implement a method to check for an updated sqlite server that has more questions
          # Switch to the browser frame and local server
          self.practice_button.Disable()
          self.client_button.Disable()
          ic("Attempting to start server")
          ServerThread()
          self.practice_button.SetLabelText("Loading Process, Please wait")
          self.app_info.SetLabel("You will be logged into the practice mode. Enjoy!")
          time.sleep(3)
          # TODO Implement button
          # This allows the whole pre-existing panel to be destroyed and we implement a button that can allow the app
          # To gracefully close all frames including cef and django sub-process
          #self.Destroy()
          #self.close_all_button = wx.Button(self, -1, "Quit NETS")
          browser_frame = BrowserFrame()
  
  
  
  
  
  
  class StartFrame(wx.Frame):
  
      def __init__(self, parent, title):
          # The style = wx.DEFAULT_FRAME_STYLE &amp; ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX) command helps to fix the size of
          # the page to make it non resizable and of fixed width and height.
          # This can also be achived using
          # self.SetMaxSize(wx.Size(400, 300))
          # self.SetMinSize(wx.Size(400, 300))
          wx.Frame.__init__(self, parent, title=title,
                            style=wx.DEFAULT_FRAME_STYLE &amp; ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX), size=(400, 300))
  
          start_panel = StartPanel(self)
          # Create status bar
          self.status_bar = self.CreateStatusBar()
          self.status_bar.SetStatusText("NETS: Active")
  
  
  if __name__ == "__main__":
      app = wx.App(False)
      frame = StartFrame(None, "Nets").Show()
      app.MainLoop()
  
  </code></pre>
  
  <p>server.py </p>
  
  <pre class="lang-py prettyprint-override"><code>#!/usr/bin/env python
  import os
  import django
  from django.core.management import call_command
  from subprocess import Popen, PIPE
  
  # TODO Clean up and select which process to use to start django
  # TODO Note, any method you implement must be able to give some form of log
  # TODO FOR debugging ease,  You must ensure that you kill the server process
  # TODO ON exit from the app itself
  
  
  def start_server_subprocess():
      process = Popen(['python', 'manage.py', 'runserver'], stdout=PIPE, stderr=PIPE)
      process.wait()
      return process
  
  
  # This method starts the server in the same thread as the main app
  # This leads to freezing, the subprocess method has been chosen
  # This is kept for learning purposes!!!
  def start_server():
      os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Nets.settings')
      django.setup()
      try:
          call_command("runserver", noreload=True)
      except Exception as e:
          template = "An exception of type {0} occurred. Arguments:\n{1!r}"
          message = template.format(type(e).__name__, e.args)
          print(message)
  
  </code></pre>