Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frameless windows (macOS implementation) #177

Merged
merged 15 commits into from
Mar 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions webview/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def load_html(content, uid='master'):

def create_window(title, url=None, js_api=None, width=800, height=600,
resizable=True, fullscreen=False, min_size=(200, 100), strings={}, confirm_quit=False,
background_color='#FFFFFF', debug=False):
background_color='#FFFFFF', debug=False, frameless=False):
"""
Create a web view window using a native GUI. The execution blocks after this function is invoked, so other
program logic must be executed in a separate thread.
Expand All @@ -192,6 +192,7 @@ def create_window(title, url=None, js_api=None, width=800, height=600,
:param strings: a dictionary with localized strings
:param confirm_quit: Display a quit confirmation dialog. Default is False
:param background_color: Background color as a hex string that is displayed before the content of webview is loaded. Default is white.
:param frameless: Whether the window should have a frame.
:return:
"""
uid = 'child_' + uuid4().hex[:8]
Expand All @@ -213,7 +214,7 @@ def create_window(title, url=None, js_api=None, width=800, height=600,
_webview_ready.clear()
gui.create_window(uid, _make_unicode(title), _transform_url(url),
width, height, resizable, fullscreen, min_size, confirm_quit,
background_color, debug, js_api, _webview_ready)
background_color, debug, js_api, frameless, _webview_ready)

return uid

Expand Down
74 changes: 68 additions & 6 deletions webview/cocoa.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def printView(frameview):
def webView_decidePolicyForNavigationAction_request_frame_decisionListener_(self, webview, action, request, frame, listener):
# The event that might have triggered the navigation
event = AppKit.NSApp.currentEvent()
action_type = action['WebActionNavigationTypeKey']
action_type = action['WebActionNavigationTypeKey']

""" Disable back navigation on pressing the Delete key: """
# Check if the requested navigation action is Back/Forward
Expand Down Expand Up @@ -199,6 +199,49 @@ def onChange_(self, sender):
option = sender.indexOfSelectedItem()
self.window().setAllowedFileTypes_(self.filter[option][1])

class DragBar(AppKit.NSView):
default_height = 22
# Fallbacks, in case these constants are not wrapped by PyObjC
try:
NSFullSizeContentViewWindowMask = AppKit.NSFullSizeContentViewWindowMask
except AttributeError:
NSFullSizeContentViewWindowMask = 1 << 15
try:
NSWindowTitleHidden = AppKit.NSWindowTitleHidden
except AttributeError:
NSWindowTitleHidden = 1

def mouseDragged_(self, theEvent):
screenFrame = AppKit.NSScreen.mainScreen().frame()
if screenFrame is None:
raise RuntimeError('Failed to obtain screen')

window = self.window()
windowFrame = window.frame()
if windowFrame is None:
raise RuntimeError('Failed to obtain frame')

currentLocation = window.convertBaseToScreen_(window.mouseLocationOutsideOfEventStream())
newOrigin = AppKit.NSMakePoint((currentLocation.x - self.initialLocation.x),
(currentLocation.y - self.initialLocation.y))
if (newOrigin.y + windowFrame.size.height) > \
(screenFrame.origin.y + screenFrame.size.height):
newOrigin.y = screenFrame.origin.y + \
(screenFrame.size.height + windowFrame.size.height)
window.setFrameOrigin_(newOrigin)

def mouseDown_(self, theEvent):
window = self.window()

windowFrame = window.frame()
if windowFrame is None:
raise RuntimeError('Failed to obtain screen')

self.initialLocation = \
window.convertBaseToScreen_(theEvent.locationInWindow())
self.initialLocation.x -= windowFrame.origin.x
self.initialLocation.y -= windowFrame.origin.y

class WebKitHost(WebKit.WebView):
def performKeyEquivalent_(self, theEvent):
"""
Expand Down Expand Up @@ -237,8 +280,9 @@ def performKeyEquivalent_(self, theEvent):

return handled


def __init__(self, uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready):
confirm_quit, background_color, debug, js_api, frameless, webview_ready):
BrowserView.instances[uid] = self
self.uid = uid

Expand Down Expand Up @@ -271,8 +315,6 @@ def __init__(self, uid, title, url, width, height, resizable, fullscreen, min_si
self.window.setBackgroundColor_(BrowserView.nscolor_from_hex(background_color))
self.window.setMinSize_(AppKit.NSSize(min_size[0], min_size[1]))
BrowserView.cascade_loc = self.window.cascadeTopLeftFromPoint_(BrowserView.cascade_loc)
# Set the titlebar color (so that it does not change with the window color)
self.window.contentView().superview().subviews().lastObject().setBackgroundColor_(AppKit.NSColor.windowBackgroundColor())

self.webkit = BrowserView.WebKitHost.alloc().initWithFrame_(rect).retain()

Expand All @@ -285,6 +327,26 @@ def __init__(self, uid, title, url, width, height, resizable, fullscreen, min_si
self.window.setDelegate_(self._windowDelegate)
BrowserView.app.setDelegate_(self._appDelegate)

if frameless:
# Make content full size and titlebar transparent
window_mask = window_mask | BrowserView.DragBar.NSFullSizeContentViewWindowMask | AppKit.NSTexturedBackgroundWindowMask
self.window.setStyleMask_(window_mask)
self.window.setTitlebarAppearsTransparent_(True)
self.window.setTitleVisibility_(BrowserView.DragBar.NSWindowTitleHidden)

# Flip the webview so our bar is position from the top, not bottom
self.webkit.setFlipped_(True)

rect = AppKit.NSMakeRect(0, 0, width, BrowserView.DragBar.default_height)
drag_bar = BrowserView.DragBar.alloc().initWithFrame_(rect)
drag_bar.setAutoresizingMask_(AppKit.NSViewWidthSizable)

# Add DragBar on top of the webview
self.webkit.addSubview_(drag_bar)
else:
# Set the titlebar color (so that it does not change with the window color)
self.window.contentView().superview().subviews().lastObject().setBackgroundColor_(AppKit.NSColor.windowBackgroundColor())

if url:
self.url = url
self.load_url(url)
Expand Down Expand Up @@ -585,10 +647,10 @@ def _set_debugging():


def create_window(uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready):
confirm_quit, background_color, debug, js_api, frameless, webview_ready):
def create():
browser = BrowserView(uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready)
confirm_quit, background_color, debug, js_api, frameless, webview_ready)
browser.show()

if uid == 'master':
Expand Down
2 changes: 1 addition & 1 deletion webview/gtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ def create_bridge():


def create_window(uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready):
confirm_quit, background_color, debug, js_api, frameless, webview_ready):
def create():
browser = BrowserView(uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready)
Expand Down
2 changes: 1 addition & 1 deletion webview/qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ def on_create_window(func):


def create_window(uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready):
confirm_quit, background_color, debug, js_api, frameless, webview_ready):
app = QApplication.instance() or QApplication([])

def _create():
Expand Down
2 changes: 1 addition & 1 deletion webview/win32.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def DocumentComplete(self, *args):


def create_window(uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready):
confirm_quit, background_color, debug, js_api, frameless, webview_ready):
set_ie_mode()
browser_view = BrowserView(title, url, width, height, resizable, fullscreen, min_size, webview_ready)
browser_view.show()
Expand Down
2 changes: 1 addition & 1 deletion webview/winforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def toggle_fullscreen(self):


def create_window(uid, title, url, width, height, resizable, fullscreen, min_size,
confirm_quit, background_color, debug, js_api, webview_ready):
confirm_quit, background_color, debug, js_api, frameless, webview_ready):
def create():
window = BrowserView.BrowserForm(uid, title, url, width, height, resizable, fullscreen,
min_size, confirm_quit, background_color, debug, js_api, webview_ready)
Expand Down