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

favicon arg for ui.run does not work when native is true, even with default nicegui favicon. #620

Closed
Skjolbir opened this issue Mar 24, 2023 · 8 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@Skjolbir
Copy link

No description provided.

@falkoschindler
Copy link
Contributor

Can you, please, give a minimal reproducible example and explain, what exactly does not work. What do you expect? What is happening instead?

@falkoschindler falkoschindler added the question Further information is requested label Mar 24, 2023
@Skjolbir
Copy link
Author

Skjolbir commented Mar 24, 2023

Of course

from nicegui import ui

ui.button('Button', on_click=lambda: ui.notify('Click'))

ui.run(native=True, title="example", favicon= r"favicon.ico", reload=True)

native=True:
s6xgDL2_d

native=False:
muSilRr_d

The favicon= r"favicon.ico" appears to work when not native and in browser, but not when native. I assume with the pywebview renderer being used, it needs an argument passed somewhere with that favicon.ico file reference, but I am unfamiliar with pywebview enough to know where off the top of my head.

@rodja
Copy link
Member

rodja commented Mar 25, 2023

A native window does not have a favicon at all. Or could you share a screenshot where the icon should appear?

@Skjolbir
Copy link
Author

Skjolbir commented Mar 25, 2023

Its the small icon to the left of the "example" window title text.
I dug into the pywebview module and found that indeed, setting the icon is not supported.
For windows users, the following code can set the window icon, although its not bullet proof.
@rodja do you have any way to get the window hWnd and hInstance so this code snippet can reference the webview window directly?

from nicegui import ui, app
import ctypes

icon_path = r"favicon.ico"

def set_icon(icon_path):
    print("setting icon")
    # Load the necessary Windows API functions using ctypes
    user32 = ctypes.windll.user32
    kernel32 = ctypes.windll.kernel32

    # Get the handle of the current process and the current window
    # Ideally replace this to directly reference the created webview window
    hWnd = user32.GetForegroundWindow()

    # Constants for Win32 API calls
    ICON_SMALL = 0
    ICON_BIG = 1
    WM_SETICON = 0x0080

    # Load the icon file
    hIcon = user32.LoadImageW(None, icon_path, 1, 0, 0, 0x00000010)

    # Set the window icon using WM_SETICON message
    ctypes.windll.user32.SendMessageW(hWnd, WM_SETICON, ICON_SMALL, hIcon)
    ctypes.windll.user32.SendMessageW(hWnd, WM_SETICON, ICON_BIG, hIcon)

# Button to manually change the icon
ui.button('Change Icon', on_click=lambda: set_icon(icon_path))

# Change icon on connection instead. Not ideal, as if created window does not have focus
# the icon will be set incorrectly elsewhere.
app.on_connect(lambda: set_icon("favicon.ico"))

ui.run(native=True, title="example", reload=True)

@rodja
Copy link
Member

rodja commented Mar 25, 2023

@Skjolbir thank you for the example code and in-depth research. What do you mean with

get the window hWnd and hInstance

You are already retrieving them in your code, or not? Are you looking for a better way? Is there a more elegant way with pywebview? If you have an example code for that, we could figure out a way on how to bring similar configuration options to NiceGUI.

@Skjolbir
Copy link
Author

Skjolbir commented Mar 25, 2023

GetForegroundWindow function (winuser.h)
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getforegroundwindow
"Retrieves a handle to the foreground window (the window with which the user is currently working)."

GetModuleHandleW function (libloaderapi.h)
https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew
"[...] If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file)."

LoadImageW function (winuser.h)
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadimagew
"Loads an icon, cursor, animated cursor, or bitmap."

Upon reading that GetModuleHandleW is optional, I have edited/removed it from the code example above.
The issue with GetForegroundWindow is that it will get the window handle of whatever window is focused, and so if the user has windows focus on another program when that code is executed, that other program will have its icon updated.

I will dig through pywebviews documentation a bit more, to see if there is anywhere I can pull the created window handle from, and if thats the case then it should be a guarantee that the webview window will have its icon set.

I also notice that the icon is changed a little delayed when called from app.on_connect, so an event that fires when the window is created would be much appreciated for a more instant icon update.
This might help in that regard:
https://pywebview.flowrl.com/examples/events.html#events
events.shown is what would be good for this.

@Skjolbir
Copy link
Author

Skjolbir commented Mar 25, 2023

I've made a pull request with added icon support.
Never used github really though, so unsure if I have done it right.
The code works like a charm though.
#633

edit: yeah, I think I messed up, its showing changes on 4 files, but it should just be changing 2; native_mode.py and run.py
new pull request with fixed files:
#634

@rodja rodja linked a pull request Mar 27, 2023 that will close this issue
@rodja rodja added enhancement New feature or request and removed question Further information is requested labels Mar 27, 2023
@falkoschindler falkoschindler added the help wanted Extra attention is needed label Oct 5, 2023
@falkoschindler
Copy link
Contributor

I'll close this stale issue in favor of a new feature request #1745.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants