Skip to content

Commit bac869e

Browse files
authored
Merge branch 'master' into feat/layers-panel-alt-drag-duplicate
2 parents a906c46 + 00718c5 commit bac869e

74 files changed

Lines changed: 1975 additions & 1994 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.nix/pkgs/graphite.nix

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,15 @@ let
4444
// {
4545
cargoArtifacts = deps.crane.lib.buildDepsOnly resourcesCommon;
4646

47-
# TODO: Remove the need for this hash by using individual package resolutions and hashes from package-lock.json
48-
npmDeps = pkgs.fetchNpmDeps {
49-
inherit (info) pname version;
50-
src = "${info.src}/frontend";
51-
hash = "sha256-D8VCNK+Ca3gxO+5wriBn8FszG8/x8n/zM6/MPo9E2j4=";
47+
npmDeps = pkgs.importNpmLock {
48+
npmRoot = "${info.src}/frontend";
5249
};
5350

5451
npmRoot = "frontend";
5552
npmConfigScript = "setup";
5653
makeCacheWritable = true;
5754

58-
nativeBuildInputs = tools.frontend ++ [ pkgs.npmHooks.npmConfigHook ];
55+
nativeBuildInputs = tools.frontend ++ [ pkgs.importNpmLock.npmConfigHook ];
5956

6057
prePatch = ''
6158
mkdir branding
@@ -109,13 +106,20 @@ deps.crane.lib.buildPackage (
109106
}
110107
else
111108
{ }
112-
);
109+
) // {
110+
GRAPHITE_GIT_COMMIT_HASH = inputs.self.rev or "unknown";
111+
GRAPHITE_GIT_COMMIT_DATE = inputs.self.lastModified or "unknown";
112+
};
113113

114114
postUnpack = ''
115115
mkdir ./branding
116116
cp -r ${branding}/* ./branding
117117
'';
118118

119+
preBuild = if inputs.self ? rev then ''
120+
export GRAPHITE_GIT_COMMIT_DATE="$(date -u -d "@$GRAPHITE_GIT_COMMIT_DATE" +"%Y-%m-%dT%H:%M:%SZ")"
121+
'' else "";
122+
119123
installPhase = ''
120124
mkdir -p $out/bin
121125
cp target/${if dev then "debug" else "release"}/graphite $out/bin/graphite
@@ -125,6 +129,12 @@ deps.crane.lib.buildPackage (
125129
126130
mkdir -p $out/share/icons/hicolor/scalable/apps
127131
cp ${branding}/app-icons/graphite.svg $out/share/icons/hicolor/scalable/apps/art.graphite.Graphite.svg
132+
mkdir -p $out/share/icons/hicolor/512x512/apps
133+
cp ${branding}/app-icons/graphite-512.png $out/share/icons/hicolor/512x512/apps/art.graphite.Graphite.png
134+
mkdir -p $out/share/icons/hicolor/256x256/apps
135+
cp ${branding}/app-icons/graphite-256.png $out/share/icons/hicolor/256x256/apps/art.graphite.Graphite.png
136+
mkdir -p $out/share/icons/hicolor/128x128/apps
137+
cp ${branding}/app-icons/graphite-128.png $out/share/icons/hicolor/128x128/apps/art.graphite.Graphite.png
128138
'';
129139

130140
postFixup = ''

.vscode/extensions.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
// Code quality
1212
"wayou.vscode-todo-highlight",
1313
"streetsidesoftware.code-spell-checker",
14-
// Helpful
14+
// Git
1515
"mhutchie.git-graph",
1616
"qezhu.gitlink",
17+
// Helpful
1718
"wmaurer.change-case"
1819
]
1920
}

.vscode/settings.json

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"editor.formatOnSave": false
3333
},
3434
// Rust Analyzer config
35+
"rust-analyzer.check.command": "clippy",
3536
"rust-analyzer.cargo.allTargets": false,
3637
"rust-analyzer.procMacro.ignored": {
3738
"serde_derive": ["Serialize", "Deserialize"],
@@ -47,13 +48,35 @@
4748
"vite-plugin-svelte-css-no-scopable-elements": "ignore", // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
4849
"a11y-no-static-element-interactions": "ignore", // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
4950
"a11y-no-noninteractive-element-interactions": "ignore", // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
50-
"a11y-click-events-have-key-events": "ignore" // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
51+
"a11y-click-events-have-key-events": "ignore", // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
52+
"a11y_consider_explicit_label": "ignore", // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
53+
"a11y_click_events_have_key_events": "ignore", // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
54+
"a11y_no_noninteractive_element_interactions": "ignore" // NOTICE: Keep this list in sync with the list in `frontend/vite.config.ts`
5155
},
56+
// Git Graph config
57+
"git-graph.repository.fetchAndPrune": true,
58+
"git-graph.repository.showRemoteHeads": false,
59+
"git-graph.repository.commits.fetchAvatars": true,
60+
// VS Code Git config
61+
"git.autofetch": true,
62+
"git.enableStatusBarSync": false,
63+
"git.showActionButton": {
64+
"sync": false
65+
},
66+
// CSpell config
67+
"cSpell.language": "en-US",
68+
"cSpell.logLevel": "Information",
69+
"cSpell.allowCompoundWords": true,
70+
// Other extensions config
71+
"evenBetterToml.formatter.alignComments": false,
72+
"package-json-upgrade.ignorePatterns": ["source-sans-pro"],
5273
// VS Code config
5374
"html.format.wrapLineLength": 200,
5475
"files.eol": "\n",
5576
"files.insertFinalNewline": true,
5677
"files.associations": {
5778
"*.graphite": "json"
58-
}
79+
},
80+
"editor.renderWhitespace": "boundary",
81+
"editor.minimap.markSectionHeaderRegex": "// ===+\\n\\s*//\\s*(?<label>[^\\n]{1,18})[^\\n]*(\\n\\s*//[^\\n]*)*\\n\\s*// ===+"
5982
}

desktop/src/app.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::sync::mpsc::{Receiver, Sender, SyncSender};
55
use std::thread;
66
use std::time::{Duration, Instant};
77
use winit::application::ApplicationHandler;
8-
use winit::dpi::PhysicalSize;
8+
use winit::dpi::{PhysicalPosition, PhysicalSize};
99
use winit::event::{ButtonSource, ElementState, MouseButton, WindowEvent};
1010
use winit::event_loop::{ActiveEventLoop, ControlFlow};
1111
use winit::window::WindowId;
@@ -27,6 +27,8 @@ pub(crate) struct App {
2727
window_size: PhysicalSize<u32>,
2828
window_maximized: bool,
2929
window_fullscreen: bool,
30+
pointer_position: PhysicalPosition<f64>,
31+
pointer_lock_position: Option<PhysicalPosition<f64>>,
3032
ui_scale: f64,
3133
app_event_receiver: Receiver<AppEvent>,
3234
app_event_scheduler: AppEventScheduler,
@@ -84,6 +86,8 @@ impl App {
8486
window_size: PhysicalSize { width: 0, height: 0 },
8587
window_maximized: false,
8688
window_fullscreen: false,
89+
pointer_position: Default::default(),
90+
pointer_lock_position: Default::default(),
8791
ui_scale: 1.,
8892
app_event_receiver,
8993
app_event_scheduler,
@@ -329,6 +333,12 @@ impl App {
329333
window.clipboard_write(content);
330334
}
331335
}
336+
DesktopFrontendMessage::PointerLock => {
337+
self.pointer_lock_position = Some(self.pointer_position);
338+
if let Some(window) = &self.window {
339+
window.start_pointer_lock();
340+
}
341+
}
332342
DesktopFrontendMessage::WindowClose => {
333343
self.app_event_scheduler.schedule(AppEvent::CloseWindow);
334344
}
@@ -480,6 +490,26 @@ impl ApplicationHandler for App {
480490
}
481491

482492
fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, _window_id: WindowId, event: WindowEvent) {
493+
// Handle pointer lock release
494+
if let Some(pointer_lock_position) = self.pointer_lock_position
495+
&& let WindowEvent::PointerButton {
496+
state: ElementState::Released,
497+
button: ButtonSource::Mouse(MouseButton::Left),
498+
..
499+
} = event
500+
{
501+
self.pointer_lock_position = None;
502+
if let Some(window) = &self.window {
503+
window.end_pointer_lock();
504+
}
505+
self.cef_context.handle_window_event(&WindowEvent::PointerMoved {
506+
device_id: None,
507+
position: pointer_lock_position,
508+
primary: true,
509+
source: winit::event::PointerSource::Mouse,
510+
});
511+
}
512+
483513
self.cef_context.handle_window_event(&event);
484514

485515
match event {
@@ -556,13 +586,29 @@ impl ApplicationHandler for App {
556586
self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message));
557587
}
558588
}
589+
590+
WindowEvent::PointerMoved { position, .. } | WindowEvent::PointerLeft { position: Some(position), .. } | WindowEvent::PointerEntered { position, .. }
591+
if self.pointer_lock_position.is_none() =>
592+
{
593+
self.pointer_position = position;
594+
}
595+
559596
_ => {}
560597
}
561598

562599
// Notify cef of possible input events
563600
self.cef_context.work();
564601
}
565602

603+
fn device_event(&mut self, _event_loop: &dyn ActiveEventLoop, _device_id: Option<winit::event::DeviceId>, event: winit::event::DeviceEvent) {
604+
if self.pointer_lock_position.is_some()
605+
&& let winit::event::DeviceEvent::PointerMotion { delta: (x, y) } = event
606+
{
607+
let message = DesktopWrapperMessage::PointerLockMove { x, y };
608+
self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message));
609+
}
610+
}
611+
566612
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
567613
// Set a timeout in case we miss any cef schedule requests
568614
let timeout = Instant::now() + Duration::from_millis(10);

desktop/src/window.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ impl Window {
159159
self.winit_window.set_cursor(cursor);
160160
}
161161

162+
pub(crate) fn start_pointer_lock(&self) {
163+
let _ = self.winit_window.set_cursor_grab(winit::window::CursorGrabMode::Locked);
164+
self.winit_window.set_cursor_visible(false);
165+
}
166+
167+
pub(crate) fn end_pointer_lock(&self) {
168+
let _ = self.winit_window.set_cursor_grab(winit::window::CursorGrabMode::None);
169+
self.winit_window.set_cursor_visible(true);
170+
}
171+
162172
pub(crate) fn update_menu(&self, entries: Vec<MenuItem>) {
163173
self.native_handle.update_menu(entries);
164174
}

desktop/wrapper/src/handle_desktop_wrapper_message.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,9 @@ pub(super) fn handle_desktop_wrapper_message(dispatcher: &mut DesktopWrapperMess
172172
dispatcher.queue_editor_message(message);
173173
}
174174
}
175+
DesktopWrapperMessage::PointerLockMove { x, y } => {
176+
let message = AppWindowMessage::PointerLockMove { x, y };
177+
dispatcher.queue_editor_message(message);
178+
}
175179
}
176180
}

desktop/wrapper/src/intercept_frontend_message.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD
136136
FrontendMessage::TriggerClipboardWrite { content } => {
137137
dispatcher.respond(DesktopFrontendMessage::ClipboardWrite { content });
138138
}
139+
FrontendMessage::WindowPointerLock => {
140+
dispatcher.respond(DesktopFrontendMessage::PointerLock);
141+
}
139142
FrontendMessage::WindowClose => {
140143
dispatcher.respond(DesktopFrontendMessage::WindowClose);
141144
}

desktop/wrapper/src/messages.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub enum DesktopFrontendMessage {
6565
ClipboardWrite {
6666
content: String,
6767
},
68+
PointerLock,
6869
WindowClose,
6970
WindowMinimize,
7071
WindowMaximize,
@@ -132,6 +133,10 @@ pub enum DesktopWrapperMessage {
132133
ClipboardReadResult {
133134
content: Option<String>,
134135
},
136+
PointerLockMove {
137+
x: f64,
138+
y: f64,
139+
},
135140
}
136141

137142
#[derive(Clone, serde::Serialize, serde::Deserialize, Debug)]

editor/build.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,18 @@ fn main() {
1818
if !gh.trim().is_empty() {
1919
gh.trim().to_string()
2020
} else {
21-
git_or_unknown(&["rev-parse", "--abbrev-ref", "HEAD"])
21+
git(&["rev-parse", "--abbrev-ref", "HEAD"]).unwrap_or_default()
2222
}
2323
});
2424

2525
// Instruct Cargo to set environment variables for compile time.
2626
// They are accessed with the `env!("GRAPHITE_*")` macro in the codebase.
27-
println!("cargo:rustc-env=GRAPHITE_GIT_COMMIT_DATE={commit_date}");
28-
println!("cargo:rustc-env=GRAPHITE_GIT_COMMIT_HASH={commit_hash}");
29-
println!("cargo:rustc-env=GRAPHITE_GIT_COMMIT_BRANCH={commit_branch}");
3027
println!("cargo:rustc-env=GRAPHITE_RELEASE_SERIES={GRAPHITE_RELEASE_SERIES}");
28+
if !commit_branch.is_empty() {
29+
println!("cargo:rustc-env=GRAPHITE_GIT_COMMIT_BRANCH={commit_branch}");
30+
}
31+
println!("cargo:rustc-env=GRAPHITE_GIT_COMMIT_HASH={commit_hash}");
32+
println!("cargo:rustc-env=GRAPHITE_GIT_COMMIT_DATE={commit_date}");
3133
}
3234

3335
/// Get an environment variable, or if it is not set or empty, use the provided fallback function. Returns a string with trimmed whitespace.

editor/src/application.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,17 @@ impl Default for Editor {
3939
}
4040

4141
pub const GRAPHITE_RELEASE_SERIES: &str = env!("GRAPHITE_RELEASE_SERIES");
42-
pub const GRAPHITE_GIT_COMMIT_DATE: &str = env!("GRAPHITE_GIT_COMMIT_DATE");
42+
pub const GRAPHITE_GIT_COMMIT_BRANCH: Option<&str> = option_env!("GRAPHITE_GIT_COMMIT_BRANCH");
4343
pub const GRAPHITE_GIT_COMMIT_HASH: &str = env!("GRAPHITE_GIT_COMMIT_HASH");
44-
pub const GRAPHITE_GIT_COMMIT_BRANCH: &str = env!("GRAPHITE_GIT_COMMIT_BRANCH");
44+
pub const GRAPHITE_GIT_COMMIT_DATE: &str = env!("GRAPHITE_GIT_COMMIT_DATE");
4545

4646
pub fn commit_info_localized(localized_commit_date: &str) -> String {
47-
format!(
48-
"Release Series: {}\n\
49-
Branch: {}\n\
50-
Commit: {}\n\
51-
{}",
52-
GRAPHITE_RELEASE_SERIES,
53-
GRAPHITE_GIT_COMMIT_BRANCH,
54-
GRAPHITE_GIT_COMMIT_HASH.get(..8).unwrap_or(GRAPHITE_GIT_COMMIT_HASH),
55-
localized_commit_date
56-
)
47+
let mut info = String::new();
48+
info.push_str(&format!("Release Series: {GRAPHITE_RELEASE_SERIES}\n"));
49+
if let Some(branch) = GRAPHITE_GIT_COMMIT_BRANCH {
50+
info.push_str(&format!("Branch: {branch}\n"));
51+
}
52+
info.push_str(&format!("Commit: {}\n", GRAPHITE_GIT_COMMIT_HASH.get(..8).unwrap_or(GRAPHITE_GIT_COMMIT_HASH)));
53+
info.push_str(localized_commit_date);
54+
info
5755
}

0 commit comments

Comments
 (0)