Skip to content

Commit

Permalink
refactor: improve icon, fix incompatible hwnd ptr type warning (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
ttytm authored Oct 5, 2023
1 parent 3c8e16d commit f139c81
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 49 deletions.
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 @@ -72,9 +72,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 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 }
}
}

0 comments on commit f139c81

Please sign in to comment.