diff --git a/webview/__init__.py b/webview/__init__.py index 1f4df18e..5538a3aa 100755 --- a/webview/__init__.py +++ b/webview/__init__.py @@ -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. @@ -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] @@ -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 diff --git a/webview/cocoa.py b/webview/cocoa.py index 1ab7ccf2..a1621b98 100644 --- a/webview/cocoa.py +++ b/webview/cocoa.py @@ -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 @@ -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): """ @@ -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 @@ -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() @@ -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) @@ -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': diff --git a/webview/gtk.py b/webview/gtk.py index 664677bc..408b16db 100755 --- a/webview/gtk.py +++ b/webview/gtk.py @@ -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) diff --git a/webview/qt.py b/webview/qt.py index 58db6698..92073f21 100755 --- a/webview/qt.py +++ b/webview/qt.py @@ -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(): diff --git a/webview/win32.py b/webview/win32.py index d5cb7524..1b741327 100644 --- a/webview/win32.py +++ b/webview/win32.py @@ -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() diff --git a/webview/winforms.py b/webview/winforms.py index 74a57f3d..128543b9 100644 --- a/webview/winforms.py +++ b/webview/winforms.py @@ -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)