Skip to content

Commit

Permalink
Have an Android executable build
Browse files Browse the repository at this point in the history
  • Loading branch information
zenith391 committed Dec 3, 2022
1 parent 34bf939 commit 96b9f49
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 8 deletions.
4 changes: 4 additions & 0 deletions android/Sdk.zig
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,10 @@ pub fn compileAppLibrary(
exe.strip = (mode == .ReleaseSmall);
exe.export_table = true;

// XXX: temporary!
// TODO: remove and fix __emutls_get_address problem instead
exe.single_threaded = true;

exe.defineCMacro("ANDROID", null);

exe.linkLibC();
Expand Down
Binary file added android/default_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 7 additions & 3 deletions build_capy.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ pub const CapyBuildOptions = struct {
android: AndroidOptions = .{},

pub const AndroidOptions = struct {
version: AndroidSdk.AndroidVersion = .android5,
// As of 2022, 95% of Android devices use Android 8 (Oreo) or higher
version: AndroidSdk.AndroidVersion = .android8,
};
};

Expand Down Expand Up @@ -113,7 +114,7 @@ pub fn install(step: *std.build.LibExeObjStep, options: CapyBuildOptions) !void
// This is a set of resources. It should at least contain a "mipmap/icon.png" resource that
// will provide the application icon.
.resources = &[_]AndroidSdk.Resource{
.{ .path = "mipmap/icon.png", .content = .{ .path = "example/icon.png" } },
.{ .path = "mipmap/icon.png", .content = .{ .path = "android/default_icon.png" } },
},
.aaudio = false,
.opensl = false,
Expand All @@ -128,7 +129,7 @@ pub fn install(step: *std.build.LibExeObjStep, options: CapyBuildOptions) !void
};

const app = sdk.createApp(
"app-template.apk",
"zig-out/capy-app.apk",
step.root_src.?.getPath(step.builder),
config,
mode,
Expand All @@ -147,6 +148,9 @@ pub fn install(step: *std.build.LibExeObjStep, options: CapyBuildOptions) !void
}

// Make the app build when we invoke "zig build" or "zig build install"
// TODO: only invoke keystore if .build_config/android.keystore doesn't exist
// When doing take environment variables or prompt if they're unavailable
//step.step.dependOn(sdk.initKeystore(key_store, .{}));
step.step.dependOn(app.final_step);

//const b = step.builder;
Expand Down
8 changes: 7 additions & 1 deletion src/backend.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ const backend = //if (@hasDecl(@import("root"), "capyBackend"))
switch (builtin.os.tag) {
.windows => @import("backends/win32/backend.zig"),
.macos => @import("backends/macos/backend.zig"),
.linux, .freebsd => @import("backends/gtk/backend.zig"),
.linux, .freebsd => blk: {
if (builtin.target.isAndroid()) {
break :blk @import("backends/android/backend.zig");
} else {
break :blk @import("backends/gtk/backend.zig");
}
},
.freestanding => blk: {
if (builtin.cpu.arch == .wasm32 or builtin.cpu.arch == .wasm64) {
break :blk @import("backends/wasm/backend.zig");
Expand Down
111 changes: 111 additions & 0 deletions src/backends/android/backend.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
const std = @import("std");
const shared = @import("../shared.zig");
const lib = @import("../../main.zig");

const EventFunctions = shared.EventFunctions(@This());
const EventType = shared.BackendEventType;
const BackendError = shared.BackendError;
const MouseButton = shared.MouseButton;
//pub const PeerType = *c.GtkWidget;
pub const PeerType = *opaque {};

var activeWindows = std.atomic.Atomic(usize).init(0);
var hasInit: bool = false;

pub fn init() BackendError!void {
if (!hasInit) {
hasInit = true;
}
}

pub fn showNativeMessageDialog(msgType: shared.MessageType, comptime fmt: []const u8, args: anytype) void {
const msg = std.fmt.allocPrintZ(lib.internal.scratch_allocator, fmt, args) catch {
std.log.err("Could not launch message dialog, original text: " ++ fmt, args);
return;
};
defer lib.internal.scratch_allocator.free(msg);
_ = msgType;
@panic("TODO: message dialogs on Android");
}

/// user data used for handling events
pub const EventUserData = struct {
user: EventFunctions = .{},
class: EventFunctions = .{},
userdata: usize = 0,
classUserdata: usize = 0,
peer: PeerType,
focusOnClick: bool = false,
};

pub inline fn getEventUserData(peer: PeerType) *EventUserData {
_ = peer;
//return @ptrCast(*EventUserData, @alignCast(@alignOf(EventUserData), c.g_object_get_data(@ptrCast(*c.GObject, peer), "eventUserData").?));
}

pub fn Events(comptime T: type) type {
_ = T;
return struct {};
}

pub const Window = struct {
source_dpi: u32 = 96,
scale: f32 = 1.0,

pub usingnamespace Events(Window);

pub fn create() BackendError!Window {
return Window{};
}

pub fn resize(self: *Window, width: c_int, height: c_int) void {
_ = self;
_ = width;
_ = height;
}

pub fn setTitle(self: *Window, title: [*:0]const u8) void {
_ = self;
_ = title;
}

pub fn setChild(self: *Window, peer: ?PeerType) void {
_ = self;
_ = peer;
}

pub fn setSourceDpi(self: *Window, dpi: u32) void {
self.source_dpi = 96;
// TODO
const resolution = @as(f32, 96.0);
self.scale = resolution / @intToFloat(f32, dpi);
}

pub fn show(self: *Window) void {
_ = self;
_ = activeWindows.fetchAdd(1, .Release);
}

pub fn close(self: *Window) void {
_ = self;
@panic("TODO: close window");
}
};

pub fn postEmptyEvent() void {
@panic("TODO: postEmptyEvent");
}

pub fn runStep(step: shared.EventLoopStep) bool {
_ = step;
return activeWindows.load(.Acquire) != 0;
}

pub const backendExport = struct {
pub fn panic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
_ = msg;

@breakpoint();
unreachable;
}
};
2 changes: 1 addition & 1 deletion src/backends/win32/win32.zig
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ pub const SB_BOTH = 3;
pub const SW_INVALIDATE = 0x0002;

pub extern "comctl32" fn GetScrollInfo(hWnd: HWND, nBar: c_int, lpsi: *SCROLLINFO) callconv(WINAPI) BOOL;
pub extern "comctl32" fn SetScrollInfo(hWnd: HWND, nBar: c_int, lpsi: *const SCROLLINFO, redraw: BOOL) callconv(WINAPI) c_int;
pub extern "comctl32" fn SetScrollInfo(hWnd: HWND, nBar: c_int, lpsi: *const SCROLLINFO, redraw: BOOL) callconv(WINAPI) c_int;
pub extern "comctl32" fn EnableScrollBar(hWnd: HWND, wSBflags: UINT, wArrows: UINT) callconv(WINAPI) BOOL;
pub extern "comctl32" fn ScrollWindowEx(hWnd: HWND, dx: c_int, dy: c_int, prcScroll: ?*const RECT, prcClip: ?*const RECT, hrgnUpdate: ?HRGN, prcUpdate: ?LPRECT, flags: UINT) callconv(WINAPI) c_int;

Expand Down
2 changes: 1 addition & 1 deletion src/button.zig
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub const Button_Impl = struct {
if (self.peer == null) {
self.peer = try backend.Button.create();
self.peer.?.setEnabled(self.enabled.get());

self.peer.?.setLabel(self.label.get());
try self.show_events();
_ = try self.enabled.addChangeListener(.{ .function = wrapperEnabledChanged, .userdata = @ptrToInt(&self.peer) });
Expand Down
7 changes: 5 additions & 2 deletions src/flat/button.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ pub const FlatButton = struct {
const width = @intCast(u32, backend.getWidthFromPeer(events.peer));
const height = @intCast(u32, backend.getHeightFromPeer(events.peer));

if (self.enabled) { ctx.setColor(0.8, 0.8, 0.8); }
else { ctx.setColor(0.7, 0.7, 0.7); }
if (self.enabled) {
ctx.setColor(0.8, 0.8, 0.8);
} else {
ctx.setColor(0.7, 0.7, 0.7);
}
ctx.rectangle(0, 0, width, height);
ctx.fill();

Expand Down

0 comments on commit 96b9f49

Please sign in to comment.