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

Allow fixing window position to any side #763

Merged
merged 3 commits into from
Oct 17, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion webview/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,4 @@ def create_window(title, url=None, html=None, js_api=None, width=800, height=600
def screens():
guilib = initialize()
screens = guilib.get_screens()
return screens
return screens
26 changes: 22 additions & 4 deletions webview/platforms/cef.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from webview.js import dom
from webview import _debug, _user_agent
from webview.util import parse_api_js, default_html, js_bridge_call
from webview.window import FixPoint


sys.excepthook = cef.ExceptHook
Expand Down Expand Up @@ -109,8 +110,25 @@ def initialize(self):
def close(self):
self.browser.CloseBrowser(True)

def resize(self, width, height):
windll.user32.SetWindowPos(self.inner_hwnd, 0, 0, 0, width - 16, height - 38,
def resize(self, width, height, fix_point):

# How much to move to the right
move_x = 0
# How much to move to the bottom
move_y = 0

rect = windll.?.RECT()
rect = windll.user32.GetWindowRect(self.inner_hwnd, rect)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@r0x0r How would I do this correctly? Do you know?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CEF code is not needed at all. The only thing the CEF code does is resizing of the CEF component. Its position always stays the same relative to the parent window.


if fix_point & FixPoint.EAST:
current_width = rect.right - rect.left
move_x = current_width - width

if fix_point & FixPoint.SOUTH:
current_height = rect.bottom - rect.top
move_y = current_height - height

windll.user32.SetWindowPos(self.inner_hwnd, 0, move_x, move_y, width - 16, height - 38,
0x0002 | 0x0004 | 0x0010)
self.browser.NotifyMoveOrResizeStarted()

Expand Down Expand Up @@ -288,9 +306,9 @@ def get_current_url(uid):


@_cef_call
def resize(width, height, uid):
def resize(width, height, uid, fix_point):
instance = instances[uid]
instance.resize(width, height)
instance.resize(width, height, fix_point)


@_cef_call
Expand Down
17 changes: 11 additions & 6 deletions webview/platforms/cocoa.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from webview.util import parse_api_js, default_html, js_bridge_call
from webview.js.css import disable_text_select
from webview.screen import Screen
from webview.window import FixPoint

settings = {}

Expand Down Expand Up @@ -475,13 +476,17 @@ def toggle():
AppHelper.callAfter(toggle)
self.is_fullscreen = not self.is_fullscreen

def resize(self, width, height):
def resize(self, width, height, fix_point):
def _resize():
frame = self.window.frame()

# Keep the top left of the window in the same place
frame.origin.y += frame.size.height
frame.origin.y -= height
if fix_point & FixPoint.EAST:
# Keep the right of the window in the same place
frame.origin.x += frame.size.width - width

if fix_point & FixPoint.NORTH:
# Keep the top of the window in the same place
frame.origin.y += frame.size.height - height

frame.size.width = width
frame.size.height = height
Expand Down Expand Up @@ -838,8 +843,8 @@ def _set_on_top():
AppHelper.callAfter(_set_on_top)


def resize(width, height, uid):
BrowserView.instances[uid].resize(width, height)
def resize(width, height, uid, fix_point):
BrowserView.instances[uid].resize(width, height, fix_point)


def minimize(uid):
Expand Down
24 changes: 21 additions & 3 deletions webview/platforms/gtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from webview.util import parse_api_js, default_html, js_bridge_call
from webview.js.css import disable_text_select
from webview.screen import Screen
from webview.window import FixPoint

logger = logging.getLogger('pywebview')

Expand Down Expand Up @@ -286,7 +287,24 @@ def toggle_fullscreen(self):

self.is_fullscreen = not self.is_fullscreen

def resize(self, width, height):
def resize(self, width, height, fix_point):
if fix_point & FixPoint.NORTH and fix_point & FixPoint.WEST:
self.window.set_gravity(Gdk.Gravity.NORTH_WEST)
elif fix_point & FixPoint.NORTH and fix_point & FixPoint.EAST:
self.window.set_gravity(Gdk.Gravity.NORTH_EAST)
elif fix_point & FixPoint.SOUTH and fix_point & FixPoint.EAST:
self.window.set_gravity(Gdk.Gravity.SOUTH_EAST)
elif fix_point & FixPoint.SOUTH and fix_point & FixPoint.WEST:
self.window.set_gravity(Gdk.Gravity.SOUTH_WEST)
elif fix_point & FixPoint.SOUTH:
self.window.set_gravity(Gdk.Gravity.SOUTH)
elif fix_point & FixPoint.NORTH:
self.window.set_gravity(Gdk.Gravity.NORTH)
elif fix_point & FixPoint.WEST:
self.window.set_gravity(Gdk.Gravity.WEST)
elif fix_point & FixPoint.EAST:
self.window.set_gravity(Gdk.Gravity.EAST)

self.window.resize(width, height)

def move(self, x, y):
Expand Down Expand Up @@ -448,9 +466,9 @@ def _set_on_top():
glib.idle_add(_set_on_top)


def resize(width, height, uid):
def resize(width, height, uid, fix_point):
def _resize():
BrowserView.instances[uid].resize(width,height)
BrowserView.instances[uid].resize(width, height, fix_point)
glib.idle_add(_resize)


Expand Down
22 changes: 17 additions & 5 deletions webview/platforms/qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from webview.util import convert_string, default_html, parse_api_js, js_bridge_call
from webview.js.css import disable_text_select
from webview.screen import Screen
from webview.window import FixPoint


logger = logging.getLogger('pywebview')
Expand Down Expand Up @@ -413,7 +414,18 @@ def on_fullscreen(self):

self.is_fullscreen = not self.is_fullscreen

def on_window_size(self, width, height):
def on_window_size(self, width, height, fix_point):
geo = self.geometry()

if fix_point & FixPoint.EAST:
# Keep the right of the window in the same place
geo.setX(geo.x() + geo.width() - width)

if fix_point & FixPoint.SOUTH:
# Keep the top of the window in the same place
geo.setY(geo.y() + geo.height() - height)

self.setGeometry(geo)
self.setFixedSize(width, height)

def on_window_move(self, x, y):
Expand Down Expand Up @@ -506,8 +518,8 @@ def destroy_(self):
def toggle_fullscreen(self):
self.fullscreen_trigger.emit()

def resize_(self, width, height):
self.window_size_trigger.emit(width, height)
def resize_(self, width, height, fix_point):
self.window_size_trigger.emit(width, height, fix_point)

def move_window(self, x, y):
self.window_move_trigger.emit(x, y)
Expand Down Expand Up @@ -672,8 +684,8 @@ def set_on_top(uid, top):
BrowserView.instances[uid].set_on_top(top)


def resize(width, height, uid):
BrowserView.instances[uid].resize_(width, height)
def resize(width, height, uid, fix_point):
BrowserView.instances[uid].resize_(width, height, fix_point)


def move(x, y, uid):
Expand Down
20 changes: 15 additions & 5 deletions webview/platforms/winforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from webview.util import parse_file_type, inject_base_uri
from webview.js import alert
from webview.screen import Screen
from webview.window import FixPoint

try:
import _winreg as winreg # Python 2
Expand Down Expand Up @@ -334,9 +335,18 @@ def _set():
else:
_set()

def resize(self, width, height):
windll.user32.SetWindowPos(self.Handle.ToInt32(), None, self.Location.X, self.Location.Y,
width, height, 64)
def resize(self, width, height, fix_point):

x = self.Location.X
y = self.Location.Y

if fix_point & FixPoint.EAST:
x = x + self.Width - width

if fix_point & FixPoint.SOUTH:
y = y + self.Height - height

windll.user32.SetWindowPos(self.Handle.ToInt32(), None, x, y, width, height, 64)

def move(self, x, y):
SWP_NOSIZE = 0x0001 # Retains the current size
Expand Down Expand Up @@ -588,9 +598,9 @@ def set_on_top(uid, on_top):
window.on_top = on_top


def resize(width, height, uid):
def resize(width, height, uid, fix_point):
window = BrowserView.instances[uid]
window.resize(width, height)
window.resize(width, height, fix_point)


def move(x, y, uid):
Expand Down
18 changes: 15 additions & 3 deletions webview/window.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import inspect
import logging
import os
from enum import Flag, auto
from functools import wraps

from webview.event import Event
Expand Down Expand Up @@ -44,6 +45,13 @@ def _loaded_call(function):
return _api_call(function, 'loaded')


class FixPoint(Flag):
NORTH = auto()
WEST = auto()
EAST = auto()
SOUTH = auto()


class Window:
def __init__(self, uid, title, url, html, width, height, x, y, resizable, fullscreen,
min_size, hidden, frameless, easy_drag, minimized, on_top, confirm_close,
Expand Down Expand Up @@ -234,16 +242,20 @@ def set_window_size(self, width, height):
:param height: desired height of target window
"""
logger.warning('This function is deprecated and will be removed in future releases. Use resize() instead')
self.gui.resize(width, height, self.uid)
self.resize(width, height)

@_shown_call
def resize(self, width, height):
def resize(self, width, height, fix_point=FixPoint.NORTH | FixPoint.WEST):
"""
Resize window
:param width: desired width of target window
:param height: desired height of target window
:param fix_point: Fix window to specified point during resize.
Must be of type FixPoint. Different points can be combined
with bitwise operators.
Example: FixPoint.NORTH | FixPoint.WEST
"""
self.gui.resize(width, height, self.uid)
self.gui.resize(width, height, self.uid, fix_point)

@_shown_call
def minimize(self):
Expand Down