diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index a60f0d7..bb4c272 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -1,4 +1,4 @@
-use enigo::{Direction::Click, Enigo, Key, Keyboard, Settings};
+use enigo::{Direction, Enigo, Key, Keyboard, Settings};
#[cfg(target_os = "linux")]
use std::ptr;
use tauri::Manager;
@@ -6,8 +6,8 @@ use tauri::Manager;
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
- let mut enigo = Enigo::new(&Settings::default()).unwrap();
- enigo.key(Key::Unicode('a'), Click);
+ // let mut enigo = Enigo::new(&Settings::default()).unwrap();
+ // enigo.key(Key::Unicode('a'), Click);
format!("Hello, {}! You've been greeted from Rust!", name)
}
@@ -16,17 +16,30 @@ fn send_key(key: String) -> Result<(), String> {
let mut enigo = Enigo::new(&Settings::default()).map_err(|e| format!("Enigo error: {}", e))?;
if key.len() == 1 {
- // Single letter (a-z, A-Z)
- enigo.key(Key::Unicode(key.chars().next().unwrap()), Click)
- .map_err(|e| format!("Key error: {}", e))?;
+ let ch = key.chars().next().unwrap();
+
+ // Check if uppercase letter
+ if ch.is_uppercase() && ch.is_alphabetic() {
+ // Send Shift + lowercase letter
+ enigo.key(Key::Shift, Direction::Press)
+ .map_err(|e| format!("Shift press error: {}", e))?;
+ enigo.key(Key::Unicode(ch.to_lowercase().next().unwrap()), Direction::Click)
+ .map_err(|e| format!("Key error: {}", e))?;
+ enigo.key(Key::Shift, Direction::Release)
+ .map_err(|e| format!("Shift release error: {}", e))?;
+ } else {
+ // Send character as-is (lowercase or non-letter)
+ enigo.key(Key::Unicode(ch), Direction::Click)
+ .map_err(|e| format!("Key error: {}", e))?;
+ }
} else {
// Special keys
match key.as_str() {
- "Enter" => enigo.key(Key::Return, Click)
+ "Enter" => enigo.key(Key::Return, Direction::Click)
.map_err(|e| format!("Key error: {}", e))?,
- "Space" => enigo.key(Key::Space, Click)
+ "Space" => enigo.key(Key::Space, Direction::Click)
.map_err(|e| format!("Key error: {}", e))?,
- "Backspace" => enigo.key(Key::Backspace, Click)
+ "Backspace" => enigo.key(Key::Backspace, Direction::Click)
.map_err(|e| format!("Key error: {}", e))?,
_ => return Err("Unknown key".to_string()),
}
diff --git a/src/app/app.component.html b/src/app/app.component.html
index f641c00..3585f69 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -3,65 +3,35 @@
+
{{ greetingMessage }}
-
-
-
-
+
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 9c357c2..0597add 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -2,62 +2,56 @@ import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { invoke } from "@tauri-apps/api/core";
+import { QwertyKeyboardComponent } from './keyboards/qwerty-keyboard.component';
+import { DvorakKeyboardComponent } from './keyboards/dvorak-keyboard.component';
+import { CircleKeyboardComponent } from './keyboards/circle-keyboard.component';
@Component({
selector: 'app-root',
standalone: true,
- imports: [CommonModule, RouterOutlet],
+ imports: [
+ CommonModule,
+ RouterOutlet,
+ QwertyKeyboardComponent,
+ DvorakKeyboardComponent,
+ CircleKeyboardComponent
+ ],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements AfterViewInit {
greetingMessage = "";
+ currentLayout: 'qwerty' | 'dvorak' | 'circle' = 'qwerty';
+ shiftActive = false;
@ViewChild('greetInput') inputElement!: ElementRef;
ngAfterViewInit() {
- // Beim Start fokussieren
this.inputElement.nativeElement.focus();
}
greet(event: SubmitEvent, name: string): void {
event.preventDefault();
-
- // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
invoke
("greet", { name }).then((text) => {
this.greetingMessage = text;
});
}
- // Keyboard Layout State
- currentLayout: 'qwerty' | 'dvorak' = 'qwerty';
-
- // QWERTY Layout
- qwertyRow1 = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'];
- qwertyRow2 = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'];
- qwertyRow3 = ['Z', 'X', 'C', 'V', 'B', 'N', 'M', ",", "."];
-
- // DVORAK Layout
- dvorakRow1 = [',', '.', 'P', 'Y', 'F', 'G', 'C', 'R', 'L'];
- dvorakRow2 = ['A', 'O', 'E', 'U', 'I', 'D', 'H', 'T', 'N', 'S'];
- dvorakRow3 = ['Q', 'J', 'K', 'X', 'B', 'M', 'W', 'V', 'Z'];
-
- shiftActive = false;
-
- // Getters for current layout
- get row1() { return this.currentLayout === 'qwerty' ? this.qwertyRow1 : this.dvorakRow1; }
- get row2() { return this.currentLayout === 'qwerty' ? this.qwertyRow2 : this.dvorakRow2; }
- get row3() { return this.currentLayout === 'qwerty' ? this.qwertyRow3 : this.dvorakRow3; }
-
toggleShift(): void {
this.shiftActive = !this.shiftActive;
}
switchLayout(): void {
- this.currentLayout = this.currentLayout === 'qwerty' ? 'dvorak' : 'qwerty';
+ if (this.currentLayout == 'qwerty'){
+ this.currentLayout = 'dvorak';
+ } else if (this.currentLayout == 'dvorak'){
+ this.currentLayout = 'circle';
+ } else if (this.currentLayout == 'circle'){
+ this.currentLayout = 'qwerty';
+ }
}
- async sendKey(key: string): Promise {
+ async handleKeyPress(key: string): Promise {
this.inputElement.nativeElement.focus();
let finalKey = key;
diff --git a/src/app/keyboards/circle-keyboard.component.ts b/src/app/keyboards/circle-keyboard.component.ts
new file mode 100644
index 0000000..7494420
--- /dev/null
+++ b/src/app/keyboards/circle-keyboard.component.ts
@@ -0,0 +1,190 @@
+import { Component, Output, EventEmitter, Input } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+//TODO: Second and fourth ring of keys
+
+@Component({
+ selector: 'app-circle-keyboard',
+ standalone: true,
+ imports: [CommonModule],
+ template: `
+
+
+
+
+
+ ⌫
+
+
+ ↵
+
+
+
+ ␣
+
+
+ ⇧
+
+
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+ `,
+ styles: [`
+ .circle-keyboard-container {
+ position: relative;
+ width: 400px;
+ height: 400px;
+ margin: 50px auto;
+ }
+
+ /* Center Button Container */
+ .center-button-container {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 140px;
+ height: 140px;
+ z-index: 1;
+ }
+
+ /* Center Button Sections */
+ .center-section {
+ position: absolute;
+ background: white;
+ font-size: 20px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: background 0.2s;
+ border: 2px solid #ddd;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 10;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ }
+
+ /* Top-left: Backspace (triangle) */
+ .top-left{
+ top: 0;
+ left: 0;
+ width: 70px;
+ height: 70px;
+ border-radius: 70px 0 0 0;
+ }
+
+ /* Top-right: Enter*/
+ .top-right {
+ top: 0;
+ right: 0;
+ width: 70px;
+ height: 70px;
+ border-radius: 0 70px 0 0;
+ }
+
+ /* Bottom: Space */
+ .bottom-left {
+ bottom: 0;
+ left: 0;
+ width: 70px;
+ height: 70px;
+ border-radius: 0 0 0 70px;
+ }
+
+ .bottom-left.active {
+ background: #4CAF50 !important;
+ color: white;
+ border-color: #45a049;
+ }
+
+ .bottom-right {
+ bottom: 0;
+ right: 0;
+ width: 70px;
+ height: 70px;
+ border-radius: 0 0 70px 0;
+ }
+
+ /* 8 Circle Buttons */
+ .circle-button {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 60px;
+ height: 60px;
+ margin: -30px 0 0 -30px;
+ border-radius: 50%;
+ border: 2px solid #ddd;
+ background: white;
+ font-size: 20px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: background 0.2s, border-color 0.2s;
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
+ z-index: 1;
+ }
+
+ .third-ring {
+ width: 40px;
+ height: 40px;
+ margin: -20px 0 0 -20px;
+ }
+
+ .fourth-ring {
+ width: 30px;
+ height: 30px;
+ margin: -20px 0 0 -20px;
+ }
+
+ .circle-button:hover, .center-section:hover {
+ background: #e8e8e8;
+ border-color: #999;
+ }
+
+ .circle-button:active, .center-section:active {
+ background: #d0d0d0;
+ }
+ `]
+})
+export class CircleKeyboardComponent {
+ @Input() shiftActive = false;
+ @Output() keyPressed = new EventEmitter();
+ @Output() shiftToggled = new EventEmitter();
+
+ // 8 keys arranged in circle
+ circleKeysFirst = ['E', 'T', 'A', 'O', 'N', 'I', 'H', 'S'];
+ circleKeysSecond = ['R', 'L', 'D', 'U', 'C', 'M', 'W', 'Y'];
+ circleKeysThird = ['F', 'G', 'P', 'B', 'V', 'K', 'J', 'X'];
+ circleKeysFourth = ['Q', 'Z', ',', '.'];
+
+ // Calculate position for each button in circle
+ getCirclePositionFromTop(index: number, radius: number): string {
+ const angle = (index * 45) - 90; // Start from top (0°), 45° apart
+ const angleRad = (angle * Math.PI) / 180;
+ const x = Math.cos(angleRad) * radius;
+ const y = Math.sin(angleRad) * radius;
+ return `translate(${x}px, ${y}px)`;
+ }
+}
diff --git a/src/app/keyboards/dvorak-keyboard.component.ts b/src/app/keyboards/dvorak-keyboard.component.ts
new file mode 100644
index 0000000..0c18a98
--- /dev/null
+++ b/src/app/keyboards/dvorak-keyboard.component.ts
@@ -0,0 +1,68 @@
+import { Component, Output, EventEmitter, Input } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+@Component({
+ selector: 'app-dvorak-keyboard',
+ standalone: true,
+ imports: [CommonModule],
+ template: `
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+
+
+
+ ⇧ Shift
+
+
+
+ Leertaste
+
+
+
+ ⌫ Delete
+
+
+
+ ↵ Enter
+
+
+
+ `,
+ styleUrl: '../app.component.css'
+})
+export class DvorakKeyboardComponent {
+ @Input() shiftActive = false;
+ @Output() keyPressed = new EventEmitter();
+ @Output() shiftToggled = new EventEmitter();
+
+ row1 = [',', '.', 'P', 'Y', 'F', 'G', 'C', 'R', 'L'];
+ row2 = ['A', 'O', 'E', 'U', 'I', 'D', 'H', 'T', 'N', 'S'];
+ row3 = ['Q', 'J', 'K', 'X', 'B', 'M', 'W', 'V', 'Z'];
+}
diff --git a/src/app/keyboards/qwerty-keyboard.component.ts b/src/app/keyboards/qwerty-keyboard.component.ts
new file mode 100644
index 0000000..a6e616d
--- /dev/null
+++ b/src/app/keyboards/qwerty-keyboard.component.ts
@@ -0,0 +1,68 @@
+import { Component, Output, EventEmitter, Input } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+@Component({
+ selector: 'app-qwerty-keyboard',
+ standalone: true,
+ imports: [CommonModule],
+ template: `
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+
+
+
+ {{ shiftActive ? key : key.toLowerCase() }}
+
+
+
+
+
+ ⇧ Shift
+
+
+
+ Leertaste
+
+
+
+ ⌫ Delete
+
+
+
+ ↵ Enter
+
+
+
+ `,
+ styleUrl: '../app.component.css'
+})
+export class QwertyKeyboardComponent {
+ @Input() shiftActive = false;
+ @Output() keyPressed = new EventEmitter();
+ @Output() shiftToggled = new EventEmitter();
+
+ row1 = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'];
+ row2 = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'];
+ row3 = ['Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.'];
+}