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

refactor: cleanup icon, return error code, fix incompatible hwnd ptr type warning #26

Merged
merged 4 commits into from
Oct 5, 2023
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
4 changes: 1 addition & 3 deletions examples/project-structure/src/main.v
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ fn main() {
app.bind(w)
w.set_title('V webview examples')
w.set_size(800, 600, .@none)
$if !macos {
w.set_icon('${@VMODROOT}/assets/icon.ico')!
}
w.set_icon('${@VMODROOT}/assets/icon.ico')!
w.navigate('file://${@VMODROOT}/ui/index.html')
w.run()
w.destroy()
Expand Down
4 changes: 1 addition & 3 deletions examples/v-js-interop-app/main.v
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ fn main() {
w := webview.create(debug: true)
w.set_title('V webview examples')
w.set_size(800, 600, .@none)
$if !macos {
w.set_icon('${@VMODROOT}/icon.ico')!
}
w.set_icon('${@VMODROOT}/icon.ico')!

// Bind V callbacks to appear as global javascript functions.
// The first string argument is the functions name in the JS frontend.
Expand Down
45 changes: 25 additions & 20 deletions src/icon/c/icon.c
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
#include "icon.h"

enum SetIconErrorCode set_icon(const void *ptr, const char *iconFilePath) {

#ifdef _WIN32
BOOL set_icon_win32(const void *ptr, const wchar_t *iconFilePath) {
HICON hIcon = LoadImageW(NULL, iconFilePath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
if (hIcon == NULL) {
fprintf(stderr, "Failed to load icon from file!\n");
return FALSE;

HWND window = (HWND)ptr;
if (window == NULL) {
return WINDOW_NOT_FOUND;
}
HWND hwnd = ((const HWND *)ptr);
if (hwnd == NULL) {
DestroyIcon(hIcon);
fprintf(stderr, "Failed to find the application window!\n");
return FALSE;
size_t size = strlen(iconFilePath) + 1;
wchar_t* iconPath = malloc(size * sizeof(wchar_t));
mbstowcs(iconPath, iconFilePath, size);
HICON hIcon = LoadImageW(NULL, iconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
if (hIcon == NULL) {
free(iconPath);
return ICON_NOT_FOUND;
}
// Set the application icon
SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
SendMessageW(window, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
// Cleanup
free(iconPath);
DestroyIcon(hIcon);
return TRUE;
}
return OK;

#elif __linux__
bool set_icon_linux(const void *ptr, const char *iconFilePath) {

GtkWidget *window = (GtkWidget *)ptr;
if (window == NULL) {
fprintf(stderr, "Failed to find the application window!\n");
return false;
return WINDOW_NOT_FOUND;
}
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(iconFilePath, NULL);
if (pixbuf == NULL) {
fprintf(stderr, "Failed to load icon from file!\n");
return false;
return ICON_NOT_FOUND;
}
GtkWindow *gtkWindow = GTK_WINDOW(window);
gtk_window_set_icon(GTK_WINDOW(gtkWindow), pixbuf);
g_object_unref(pixbuf);
return true;
}
return OK;

#endif

return OS_UNSUPPORTED;
}
16 changes: 11 additions & 5 deletions src/icon/c/icon.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
#pragma once
#include <stdio.h>

#ifdef _WIN32
#include <tchar.h>
#include <windows.h>
BOOL set_icon_win32(const void *ptr, const wchar_t *iconFilePath);
#include <wchar.h>
#include <stdlib.h>
#elif __linux__
#include <gtk/gtk.h>
#include <stdbool.h>
bool set_icon_linux(const void *ptr, const char *iconFilePath);
#endif

enum SetIconErrorCode {
OK = 0,
WINDOW_NOT_FOUND,
ICON_NOT_FOUND,
OS_UNSUPPORTED,
};

enum SetIconErrorCode set_icon(const void *ptr, const char *iconFilePath);
35 changes: 17 additions & 18 deletions src/icon/icon.v
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
module icon

import builtin.wchar

#flag -I@VMODROOT/src/icon/c
#flag @VMODROOT/src/icon/c/icon.o
#include "icon.h"

$if linux {
#pkgconfig gtk+-3.0
#pkgconfig webkit2gtk-4.0
}
#flag -I@VMODROOT/src/icon/c
#flag @VMODROOT/src/icon/c/icon.o
#include "@VMODROOT/src/icon/c/icon.h"

fn C.set_icon_win32(w voidptr, ico_file_path &wchar.Character) bool
enum SetIconResult {
ok = C.OK
window_not_found = C.WINDOW_NOT_FOUND
icon_not_found = C.ICON_NOT_FOUND
os_unsupported = C.OS_UNSUPPORTED
}

fn C.set_icon_linux(w voidptr, ico_file_path &char) bool
fn C.set_icon(w voidptr, ico_file_path &char) SetIconResult

// set_icon updates the icon of the native window. It supports Windows HWND windows and Linux GTK
// windows under X11 - under Wayland, window application mapping is based on the desktop file entry name.
// TODO: add macOS support
pub fn set_icon(window voidptr, icon_file_path string) ! {
$if windows {
if !C.set_icon_win32(window, wchar.from_string(icon_file_path)) {
return error('Failed to set icon.')
}
} $else $if linux {
if !C.set_icon_linux(window, &char(icon_file_path.str)) {
return error('Failed to set icon.')
}
} $else {
return error('Failed to set icon. Unsupported OS.')
result := SetIconResult(C.set_icon(window, &char(icon_file_path.str)))
match result {
.ok { return }
.icon_not_found { return error('Failed finding icon.') }
.window_not_found { return error('Failed to set icon. Window not found.') }
// .os_unsupported { return error('Failed to set icon. Unsupported OS.') }
.os_unsupported { return }
}
}