Skip to content

Commit

Permalink
Update Jai and add instructions for the Scoop installation.
Browse files Browse the repository at this point in the history
  • Loading branch information
LuisThiamNye committed May 1, 2024
1 parent 944672d commit 089dd77
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 39 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ This is the successor to the original [Buttery Taskbar](https://github.com/Crypt

## Installation

The program is provided as a single executable and no installer. [Download it here](https://github.com/LuisThiamNye/ButteryTaskbar2/releases/) and just run the program.
The program is provided as a single executable and no installer. [Download it here](https://github.com/LuisThiamNye/ButteryTaskbar2/releases/) (or [via scoop](#installing-via-scoop)) and just run the program.

If you want it to run at log-in, I recommend creating an entry in Task Scheduler. There are plenty of instructions online for how to make a program run at log-in with Task Scheduler.

Expand All @@ -37,6 +37,15 @@ Important: In the properties window of the Task Scheduler entry you create for B

You might notice that in Buttery Taskbar's tray menu, there is a "start at log-in" option. Keep this turned off if you followed the above steps. Unlike the Task Scheduler method, this option will not start Buttery Taskbar as administrator, and hence Buttery Taskbar will not work properly when the current focused window is running as administrator.

## Installing via Scoop

If you install the program via [scoop](https://scoop.sh/), the executable can then be found at `C:\Users\<username>\scoop\apps\buttery-taskbar\current\`

```pwsh
scoop bucket add CrypticButter https://github.com/CrypticButter/ScoopBucket
scoop install CrypticButter/buttery-taskbar
```

## Further details

- The taskbar's visibility is updated each time you switch focus between windows (including opening the Start menu).
Expand Down
18 changes: 9 additions & 9 deletions config.jai
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ is_ui_initialised: bool;

menu_loop :: () {
while loop:= 1 {
current_time = get_time();
current_time = seconds_since_init();
dt := cast(float)(current_time - last_time);
Clamp(*dt, 0, 0.1);
last_time = current_time;
Expand Down Expand Up @@ -121,7 +121,7 @@ open_menu_window :: (x_anchor: s32, y_anchor: s32) {
start_check_for_updates();

if !menu_hwnd {
class_name:= utf8_to_wide(menu_class_name);
class_name:= utf8_to_wide_new(menu_class_name,, temp);
wc: WNDCLASSEXW;
wc.cbSize = size_of(WNDCLASSEXW);
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DROPSHADOW | CS_NOCLOSE;
Expand All @@ -135,7 +135,7 @@ open_menu_window :: (x_anchor: s32, y_anchor: s32) {
terminate_program();
}

window_name:= utf8_to_wide(app_name);
window_name:= utf8_to_wide_new(app_name,, temp);
menu_hwnd = CreateWindowExW(
WS_EX_TOPMOST,
class_name,
Expand Down Expand Up @@ -166,7 +166,7 @@ set_window_frame_dark_mode :: (hwnd: HWND, dark: bool) {

is_system_app_dark_mode_enabled :: () -> bool {
// Dynamically link because this API is undocumented
hUxTheme:= LoadLibraryW(utf8_to_wide("uxtheme.dll"));
hUxTheme:= LoadLibraryW(utf8_to_wide_new("uxtheme.dll",, temp));
if hUxTheme == null {
log_error("uxtheme.dll not found.");
return false;
Expand Down Expand Up @@ -395,12 +395,12 @@ config_file_name :: "config";

save_config :: () {
programs_dir:= get_path_os_program_data();
data_dir:= join(programs_dir, "\\", app_name, allocator=temp);
data_dir:= join(programs_dir, "\\", app_name,, temp);
if !make_directory_if_it_does_not_exist(data_dir) {
log_error("Could not create data directory");
return;
}
config_path:= join(data_dir, "\\", config_file_name, allocator=temp);
config_path:= join(data_dir, "\\", config_file_name,, temp);
config:= Cold_Config.{
version = Cold_Config.VERSION,
enabled = config__enabled,
Expand All @@ -424,8 +424,8 @@ load_config :: () {
config__autohide_when_disabled = (res & ABS_AUTOHIDE) != 0;

programs_dir:= get_path_os_program_data();
data_dir:= join(programs_dir, "\\", app_name, allocator=temp);
config_path:= join(data_dir, "\\", config_file_name, allocator=temp);
data_dir:= join(programs_dir, "\\", app_name,, temp);
config_path:= join(data_dir, "\\", config_file_name,, temp);
data, ok := read_entire_file(config_path);
if !ok {
log("Failed to read config file %", config_path, flags=.WARNING);
Expand Down Expand Up @@ -459,7 +459,7 @@ load_config :: () {
}

open_url_in_browser :: (url: string) {
if xx ShellExecuteW(null, utf8_to_wide("open"), utf8_to_wide(url), null, null, SW_SHOWNORMAL) <= 32 {
if xx ShellExecuteW(null, utf8_to_wide_new("open",, temp), utf8_to_wide_new(url,, temp), null, null, SW_SHOWNORMAL) <= 32 {
log_error("Failed to open URL in browser.");
}
}
4 changes: 3 additions & 1 deletion first.jai
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ build :: () {
case "dev";
options.text_output_flags = 0;
should_execute = true;
case "norun";
should_execute = false;
case "release";
log("Building release-mode, version %", app_version);
set_optimization(*options, .VERY_OPTIMIZED);
Expand Down Expand Up @@ -158,7 +160,7 @@ build :: () {
autorun_the_exe :: (w: Workspace, use_debugger: bool) {
using options := get_build_options(w);
if output_type == .EXECUTABLE {
run_string := ifx output_path then join(output_path, "/", output_executable_name, allocator=temp) else output_executable_name;
run_string := ifx output_path then join(output_path, "/", output_executable_name,, temp) else output_executable_name;
log("Running: %\n", run_string);
result := ifx use_debugger
then Process.run_command("remedybg.exe", "-g", "-q", "Buttery_Taskbar.rdbg")
Expand Down
44 changes: 22 additions & 22 deletions main.jai
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
Basic :: #import "Basic"()(MEMORY_DEBUGGER = !RELEASE_MODE, ENABLE_ASSERT=!RELEASE_MODE, TEMP_ALLOCATOR_POISON_FREED_MEMORY=!RELEASE_MODE);
#if RELEASE_MODE { // :nullify_print_and_log_statements
using,except(log, log_error, print) Basic;
log :: (_: ..Any, flags: Log_Flags = 0) #expand {}
log_error :: (_: ..Any) #expand {}
print :: (_: ..Any) #expand {}
log :: (#discard _: ..Any, #discard flags: Log_Flags = 0) #expand {}
log_error :: (#discard _: ..Any) #expand {}
print :: (#discard _: ..Any) #expand {}
} else {
using Basic;
}
Expand Down Expand Up @@ -131,20 +131,20 @@ refresh_monitor_rect :: () {
primary_monitor_rect = info.rcWork;
}

WM_SHELLHOOKMESSAGE: u32;
wm_shellhookmessage: u32;
taskbar_restart_window_message: u32;

setup_hidden_window :: () -> bool {
WM_SHELLHOOKMESSAGE = RegisterWindowMessageW(utf8_to_wide("SHELLHOOK"));
taskbar_restart_window_message = RegisterWindowMessageW(utf8_to_wide("TaskbarCreated"));
wm_shellhookmessage = RegisterWindowMessageW(utf8_to_wide_new("SHELLHOOK",, temp));
taskbar_restart_window_message = RegisterWindowMessageW(utf8_to_wide_new("TaskbarCreated",, temp));

wc: WNDCLASSEXW;
wc.cbSize = size_of(WNDCLASSEXW);
wc.style = CS_NOCLOSE;
wc.lpfnWndProc = xx handle_window_message;
wc.hInstance = GetModuleHandleW(null);
wc.hCursor = LoadCursorW(null, IDC_ARROW);
class_name:= utf8_to_wide("BUTTERY_TASKBAR");
class_name:= utf8_to_wide_new("BUTTERY_TASKBAR",, temp);
wc.lpszClassName = class_name;

if 0 == RegisterClassExW(*wc) {
Expand All @@ -155,14 +155,14 @@ setup_hidden_window :: () -> bool {
main_hwnd = CreateWindowExW(
0,
class_name,
utf8_to_wide(app_name),
utf8_to_wide_new(app_name,, temp),
0,
0, 0, 0, 0,
null, null,
GetModuleHandleW(null),
null);

lib:= LoadLibraryW(utf8_to_wide("User32.dll"));
lib:= LoadLibraryW(utf8_to_wide_new("User32.dll",, temp));
if lib==null {
log_error("Failed to load User32.dll");
return false;
Expand Down Expand Up @@ -199,7 +199,7 @@ handle_window_message :: (hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM)
} else {
notify_icon_data.hIcon = LoadImageW(GetModuleHandleW(null), xx ICON_RESOURCE_ID, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
}
memcpy(*notify_icon_data.szTip, utf8_to_wide(app_name), app_name.count*2);
memcpy(*notify_icon_data.szTip, utf8_to_wide_new(app_name,, temp), app_name.count*2);
NOTIFYICON_VERSION_4: u32 : 4;
notify_icon_data.uVersion = NOTIFYICON_VERSION_4;

Expand Down Expand Up @@ -235,11 +235,11 @@ handle_window_message :: (hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM)
// We listen for window activation for two purposes:
// 1. Set the taskbar state.
// 2. Hide the menu popup.
if msg == WM_SHELLHOOKMESSAGE {
get_window_class_name :: (hwnd: HWND, allocator:= temp) -> string {
class_name:= NewArray(48, u16).data;
if msg == wm_shellhookmessage {
get_window_class_name :: (hwnd: HWND) -> string {
class_name:= NewArray(48, u16,, temp).data;
GetClassNameW(hwnd, class_name, 47);
return wide_to_utf8(class_name, -1, allocator);
return wide_to_utf8_new(class_name, -1);
}

if wparam == {
Expand Down Expand Up @@ -267,7 +267,7 @@ handle_window_message :: (hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM)
activated_window = GetForegroundWindow();
// class TopLevelWindowForOverflowXamlIsland is used for the tray overflow menu
// class XamlExplorerHostIslandWindow is used for task view
class_name_str:= get_window_class_name(activated_window);
class_name_str:= get_window_class_name(activated_window,, temp);
log("Activated (null): %", class_name_str);
if class_name_str == "Shell_TrayWnd"
|| class_name_str == "TopLevelWindowForOverflowXamlIsland"
Expand All @@ -281,7 +281,7 @@ handle_window_message :: (hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM)
} else {
// start menu corresponds to window class of Windows.UI.Core.CoreWindow, but is also used for things like notification and action centre
// Could be more reliably identified as the exe is SearchHost.exe
class_name_str:= get_window_class_name(activated_window);
class_name_str:= get_window_class_name(activated_window,, temp);
log("Activated: %", class_name_str);
if is_menu_active && class_name_str != menu_class_name close_menu();
if config__enabled {
Expand All @@ -308,12 +308,12 @@ handle_window_message :: (hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM)
// Taskbar stuff

refresh_taskbars :: () {
h_primary_taskbar:= FindWindowW(utf8_to_wide("Shell_TrayWnd"), null);
h_primary_taskbar:= FindWindowW(utf8_to_wide_new("Shell_TrayWnd",, temp), null);
array_reset(*taskbar_hwnds);
array_add(*taskbar_hwnds, h_primary_taskbar);
hwnd: HWND = null;
while 1 {
hwnd = FindWindowExW(null, hwnd, utf8_to_wide("Shell_SecondaryTrayWnd"), null);
hwnd = FindWindowExW(null, hwnd, utf8_to_wide_new("Shell_SecondaryTrayWnd",, temp), null);
if hwnd == null break;
array_add(*taskbar_hwnds, hwnd);
}
Expand Down Expand Up @@ -581,21 +581,21 @@ fetch_update_status :: () {
log("Checking version at: %0%", host_name, path);

user_agent:: #run join("Buttery Taskbar ", app_version);
session:= WinHttpOpen(utf8_to_wide(user_agent), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, null, null, 0);
session:= WinHttpOpen(utf8_to_wide_new(user_agent,, temp), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, null, null, 0);
if !session {
log_error("Failed to initialise WinHTTP.");
return;
}
defer WinHttpCloseHandle(session);

connection:= WinHttpConnect(session, utf8_to_wide(host_name), 443, 0);
connection:= WinHttpConnect(session, utf8_to_wide_new(host_name,, temp), 443, 0);
if !connection {
log_error("Failed to connect.");
return;
}
defer WinHttpCloseHandle(connection);

request:= WinHttpOpenRequest(connection, utf8_to_wide("GET"), utf8_to_wide(path), null, null, null, WINHTTP_FLAG_SECURE);
request:= WinHttpOpenRequest(connection, utf8_to_wide_new("GET",, temp), utf8_to_wide_new(path,, temp), null, null, null, WINHTTP_FLAG_SECURE);
if !request {
log_error("Failed to make request.");
return;
Expand Down Expand Up @@ -626,7 +626,7 @@ fetch_update_status :: () {
if n_bytes_read == 0 break;
buffer.count += n_bytes_read;
}
response:= builder_to_string(*sb, allocator=temp);
response:= builder_to_string(*sb,, temp);

found_tag:= false;
while breakable:= 1 {
Expand Down
10 changes: 5 additions & 5 deletions windows-extra.jai
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ RegSetValueExA :: (hkey: HKEY, lpValueName: *u8, Reserved: DWORD, dwType: DWORD,

#scope_file

kernel32 :: #system_library "kernel32";
user32 :: #system_library "user32";
shell32 :: #system_library "Shell32";
dwmapi :: #system_library "Dwmapi";
shcore :: #system_library "Shcore";
kernel32 :: #library,system "kernel32";
user32 :: #library,system "user32";
shell32 :: #library,system "Shell32";
dwmapi :: #library,system "Dwmapi";
shcore :: #library,system "Shcore";
2 changes: 1 addition & 1 deletion winhttp.jai
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ WinHttpSendRequest :: (hRequest: HINTERNET, lpszHeaders: *u16, dwHeadersLength:

WinHttpReceiveResponse :: (hRequest: HINTERNET, lpReserved: *void) -> BOOL #foreign winhttp;

winhttp :: #system_library "Winhttp";
winhttp :: #library,system "Winhttp";

0 comments on commit 089dd77

Please sign in to comment.