Merge 779edb1d9c
into 653e4badeb
This commit is contained in:
commit
46cd6270df
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(rg:*)",
|
||||||
|
"Bash(g++:*)",
|
||||||
|
"Bash(cmake:*)",
|
||||||
|
"Bash(sudo apt:*)",
|
||||||
|
"Bash(sudo apt install:*)"
|
||||||
|
],
|
||||||
|
"deny": []
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
cmake_minimum_required (VERSION 3.4)
|
cmake_minimum_required (VERSION 3.5)
|
||||||
project (barrier C CXX)
|
project (barrier C CXX)
|
||||||
|
|
||||||
option (BARRIER_BUILD_GUI "Build the GUI" ON)
|
option (BARRIER_BUILD_GUI "Build the GUI" ON)
|
||||||
|
|
|
@ -0,0 +1,265 @@
|
||||||
|
# Barrier Linux Compilation Guide
|
||||||
|
|
||||||
|
## Exact Steps Performed (What We Actually Did)
|
||||||
|
|
||||||
|
This section documents the exact sequence of commands and fixes applied to successfully build Barrier on WSL2/Ubuntu.
|
||||||
|
|
||||||
|
### 1. Fixed CMake Version Requirements
|
||||||
|
Updated minimum CMake version from 3.4 to 3.5 in three files:
|
||||||
|
|
||||||
|
**File 1:** `CMakeLists.txt` (line 18)
|
||||||
|
```cmake
|
||||||
|
# Changed from:
|
||||||
|
cmake_minimum_required (VERSION 3.4)
|
||||||
|
# To:
|
||||||
|
cmake_minimum_required (VERSION 3.5)
|
||||||
|
```
|
||||||
|
|
||||||
|
**File 2:** `cmake/Version.cmake` (line 1)
|
||||||
|
```cmake
|
||||||
|
# Changed from:
|
||||||
|
cmake_minimum_required (VERSION 3.4)
|
||||||
|
# To:
|
||||||
|
cmake_minimum_required (VERSION 3.5)
|
||||||
|
```
|
||||||
|
|
||||||
|
**File 3:** `src/gui/CMakeLists.txt` (line 1)
|
||||||
|
```cmake
|
||||||
|
# Changed from:
|
||||||
|
cmake_minimum_required (VERSION 3.4)
|
||||||
|
# To:
|
||||||
|
cmake_minimum_required (VERSION 3.5)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Installed Dependencies
|
||||||
|
```bash
|
||||||
|
sudo apt install -y libcurl4-openssl-dev qtbase5-dev qttools5-dev-tools libssl-dev libx11-dev libxtst-dev libxinerama-dev libxss-dev libxi-dev libxrandr-dev libavahi-compat-libdnssd-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Fixed Missing Headers
|
||||||
|
**File 1:** `src/lib/base/String.h`
|
||||||
|
Added missing header after line 25:
|
||||||
|
```cpp
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint> // ADDED THIS LINE
|
||||||
|
```
|
||||||
|
|
||||||
|
**File 2:** `src/lib/net/FingerprintData.h`
|
||||||
|
Added missing header after line 22:
|
||||||
|
```cpp
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint> // ADDED THIS LINE
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Build
|
||||||
|
```bash
|
||||||
|
cd "/mnt/c/D Drive/CAPTAIN/CodeProjects/barrier"
|
||||||
|
./clean_build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Verify Build Output
|
||||||
|
```bash
|
||||||
|
ls -la "/mnt/c/D Drive/CAPTAIN/CodeProjects/barrier/build/bin/"
|
||||||
|
```
|
||||||
|
**Files created:**
|
||||||
|
- `barriers` (12,709,936 bytes) - Server executable
|
||||||
|
- `barrierc` (10,165,752 bytes) - Client executable
|
||||||
|
- `integtests` (20,092,176 bytes) - Integration tests
|
||||||
|
- `unittests` (15,227,792 bytes) - Unit tests
|
||||||
|
|
||||||
|
### 6. Test Functionality
|
||||||
|
```bash
|
||||||
|
cd "/mnt/c/D Drive/CAPTAIN/CodeProjects/barrier/build/bin"
|
||||||
|
./barrierc <server-ip>
|
||||||
|
```
|
||||||
|
**Result:** ✅ Successfully connected to server
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## General Compilation Guide
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
#### System Requirements
|
||||||
|
- Ubuntu/Debian-based Linux distribution
|
||||||
|
- CMake 4.0+ (installed via snap)
|
||||||
|
- GCC 13.3.0
|
||||||
|
- Git
|
||||||
|
|
||||||
|
#### Required Dependencies
|
||||||
|
|
||||||
|
Install the following packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y \
|
||||||
|
libcurl4-openssl-dev \
|
||||||
|
qtbase5-dev \
|
||||||
|
qttools5-dev-tools \
|
||||||
|
libssl-dev \
|
||||||
|
libx11-dev \
|
||||||
|
libxtst-dev \
|
||||||
|
libxinerama-dev \
|
||||||
|
libxss-dev \
|
||||||
|
libxi-dev \
|
||||||
|
libxrandr-dev \
|
||||||
|
libavahi-compat-libdnssd-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note on Package Names:**
|
||||||
|
- Use `qtbase5-dev` instead of the deprecated `qt5-default`
|
||||||
|
- Use `libavahi-compat-libdnssd-dev` instead of `avahi-compat-libdns_sd-dev`
|
||||||
|
|
||||||
|
### Source Code Fixes Required
|
||||||
|
|
||||||
|
The original Barrier source code requires several fixes to compile with modern toolchains:
|
||||||
|
|
||||||
|
#### 1. CMake Minimum Version Updates
|
||||||
|
|
||||||
|
**Files to modify:**
|
||||||
|
- `CMakeLists.txt` (line 18)
|
||||||
|
- `cmake/Version.cmake` (line 1)
|
||||||
|
- `src/gui/CMakeLists.txt` (line 1)
|
||||||
|
|
||||||
|
**Change:**
|
||||||
|
```cmake
|
||||||
|
# FROM:
|
||||||
|
cmake_minimum_required (VERSION 3.4)
|
||||||
|
|
||||||
|
# TO:
|
||||||
|
cmake_minimum_required (VERSION 3.5)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Reason:** CMake 4.0+ no longer supports compatibility with CMake < 3.5
|
||||||
|
|
||||||
|
#### 2. Missing C++ Headers
|
||||||
|
|
||||||
|
**File:** `src/lib/base/String.h`
|
||||||
|
|
||||||
|
**Add after existing includes:**
|
||||||
|
```cpp
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint> // ADD THIS LINE
|
||||||
|
```
|
||||||
|
|
||||||
|
**File:** `src/lib/net/FingerprintData.h`
|
||||||
|
|
||||||
|
**Add after existing includes:**
|
||||||
|
```cpp
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint> // ADD THIS LINE
|
||||||
|
```
|
||||||
|
|
||||||
|
**Reason:** Modern C++ compilers require explicit inclusion of `<cstdint>` for `std::uint8_t` types
|
||||||
|
|
||||||
|
### Compilation Process
|
||||||
|
|
||||||
|
#### 1. Clone and Navigate
|
||||||
|
```bash
|
||||||
|
git clone <barrier-repo-url>
|
||||||
|
cd barrier
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Initialize Submodules
|
||||||
|
```bash
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Apply Source Code Fixes
|
||||||
|
Apply all the fixes mentioned in the "Source Code Fixes Required" section above.
|
||||||
|
|
||||||
|
#### 4. Build
|
||||||
|
```bash
|
||||||
|
./clean_build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alternative manual build:**
|
||||||
|
```bash
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Output
|
||||||
|
|
||||||
|
#### Successful Build Results
|
||||||
|
- **Location:** `build/bin/`
|
||||||
|
- **Core executables:**
|
||||||
|
- `barriers` (~12.7MB) - Server component
|
||||||
|
- `barrierc` (~10.2MB) - Client component
|
||||||
|
- `barrier` - GUI application (if Qt build completes)
|
||||||
|
- `integtests` - Integration tests
|
||||||
|
- `unittests` - Unit tests
|
||||||
|
|
||||||
|
#### Expected Warnings
|
||||||
|
- OpenSSL deprecation warnings (non-critical)
|
||||||
|
- CMake compatibility warnings (non-critical)
|
||||||
|
- Clock skew warnings in WSL (non-critical)
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
#### Server Mode
|
||||||
|
```bash
|
||||||
|
cd build/bin
|
||||||
|
./barriers
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Client Mode
|
||||||
|
```bash
|
||||||
|
cd build/bin
|
||||||
|
./barrierc <server-ip-address>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### GUI Mode (if available)
|
||||||
|
```bash
|
||||||
|
cd build/bin
|
||||||
|
./barrier
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
#### Common Issues
|
||||||
|
|
||||||
|
1. **Missing Qt5**: Install `qtbase5-dev` instead of `qt5-default`
|
||||||
|
2. **Missing Avahi**: Use `libavahi-compat-libdnssd-dev` package name
|
||||||
|
3. **uint8_t errors**: Add `#include <cstdint>` to header files
|
||||||
|
4. **CMake version errors**: Update minimum version requirements to 3.5
|
||||||
|
5. **CURL not found**: Install `libcurl4-openssl-dev`
|
||||||
|
|
||||||
|
#### Build Environment Notes
|
||||||
|
- **WSL Users**: No GUI display available by default
|
||||||
|
- **X11 Required**: For actual mouse/keyboard sharing functionality
|
||||||
|
- **Network**: Ensure firewall allows Barrier traffic (default port 24800)
|
||||||
|
|
||||||
|
### Platform-Specific Notes
|
||||||
|
|
||||||
|
#### Windows Build (Alternative)
|
||||||
|
If building on Windows instead of Linux:
|
||||||
|
- Requires Visual Studio 2019/2022
|
||||||
|
- Requires Qt 5.11.1 at `C:\Qt\5.11.1\msvc2017_64`
|
||||||
|
- Requires Bonjour SDK at `C:\Program Files\Bonjour SDK`
|
||||||
|
- Use `clean_build.bat` instead of `clean_build.sh`
|
||||||
|
|
||||||
|
#### Linux Desktop Environment
|
||||||
|
For full functionality, Barrier requires:
|
||||||
|
- X11 or Wayland display server
|
||||||
|
- Desktop environment (GNOME, KDE, etc.)
|
||||||
|
- Proper graphics drivers
|
||||||
|
|
||||||
|
### Version Information
|
||||||
|
- **Barrier Version:** 2.4.0
|
||||||
|
- **Build System:** CMake + Make
|
||||||
|
- **Compiler:** GCC 13.3.0
|
||||||
|
- **Target Platform:** Linux x86_64
|
||||||
|
|
||||||
|
### Summary of Changes Made
|
||||||
|
1. Updated CMake minimum version requirements (3 files)
|
||||||
|
2. Added missing `#include <cstdint>` headers (2 files)
|
||||||
|
3. Installed correct Linux development packages
|
||||||
|
4. Used appropriate package names for Ubuntu 24.04+
|
||||||
|
|
||||||
|
This guide should enable successful compilation of Barrier on modern Linux systems.
|
|
@ -0,0 +1,48 @@
|
||||||
|
# Grave Modifier Setup for Barrier
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This implementation adds support for using the grave key (`) as a hotkey modifier in Barrier, similar to Control, Alt, and Shift.
|
||||||
|
|
||||||
|
## Required Setup
|
||||||
|
|
||||||
|
### 1. Code Changes
|
||||||
|
The following code changes have been implemented:
|
||||||
|
|
||||||
|
- **XWindowsUtil.cpp**: Added `case XK_grave: return kKeyModifierBitGrave;` to `getModifierBitForKeySym()`
|
||||||
|
- **XWindowsKeyState.cpp**: Added fallback mapping for grave modifier to Mod4 in `updateKeysymMapXKB()`
|
||||||
|
- **key_types.cpp**: Already included grave modifier in `kModifierNameMap`
|
||||||
|
|
||||||
|
### 2. X11 Modifier Mapping (REQUIRED)
|
||||||
|
The grave key must be mapped to an X11 modifier for hotkeys to work. Run this command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
xmodmap -e "add mod4 = grave"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Make it Permanent
|
||||||
|
To make the X11 mapping persistent across reboots, add this line to `~/.xsessionrc`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo 'xmodmap -e "add mod4 = grave"' >> ~/.xsessionrc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Once setup is complete, you can use grave modifier hotkeys in your Barrier configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
keystroke(Grave+1) = switchToScreen(screen1,960,540)
|
||||||
|
keystroke(Grave+2) = switchToScreen(screen2,960,540)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
To verify the setup:
|
||||||
|
|
||||||
|
1. Check modifier mapping: `xmodmap -pm`
|
||||||
|
- Should show `grave (0x31)` in the mod4 line
|
||||||
|
2. Test hotkeys: Press and hold grave, then press a number key
|
||||||
|
3. Check Barrier logs for successful hotkey registration
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
- If hotkeys don't work, verify grave is mapped to mod4: `xmodmap -pm`
|
||||||
|
- If mapping is lost after reboot, ensure `~/.xsessionrc` contains the xmodmap command
|
||||||
|
- Restart Barrier server after making X11 mapping changes
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required (VERSION 3.4)
|
cmake_minimum_required (VERSION 3.5)
|
||||||
|
|
||||||
set (BARRIER_VERSION_MAJOR 2)
|
set (BARRIER_VERSION_MAJOR 2)
|
||||||
set (BARRIER_VERSION_MINOR 4)
|
set (BARRIER_VERSION_MINOR 4)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required (VERSION 3.4)
|
cmake_minimum_required (VERSION 3.5)
|
||||||
|
|
||||||
find_package (Qt5 REQUIRED COMPONENTS Core Widgets Network)
|
find_package (Qt5 REQUIRED COMPONENTS Core Widgets Network)
|
||||||
set (CMAKE_AUTOMOC ON)
|
set (CMAKE_AUTOMOC ON)
|
||||||
|
|
|
@ -40,7 +40,10 @@ Action::Action() :
|
||||||
m_SwitchDirection(switchLeft),
|
m_SwitchDirection(switchLeft),
|
||||||
m_LockCursorMode(lockCursorToggle),
|
m_LockCursorMode(lockCursorToggle),
|
||||||
m_ActiveOnRelease(false),
|
m_ActiveOnRelease(false),
|
||||||
m_HasScreens(false)
|
m_HasScreens(false),
|
||||||
|
m_hasCustomPosition(false),
|
||||||
|
m_customX(0),
|
||||||
|
m_customY(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +90,12 @@ QString Action::text() const
|
||||||
case switchToScreen:
|
case switchToScreen:
|
||||||
text += "(";
|
text += "(";
|
||||||
text += switchScreenName();
|
text += switchScreenName();
|
||||||
|
if (hasCustomPosition()) {
|
||||||
|
text += ",";
|
||||||
|
text += QString::number(customX());
|
||||||
|
text += ",";
|
||||||
|
text += QString::number(customY());
|
||||||
|
}
|
||||||
text += ")";
|
text += ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -133,6 +142,9 @@ void Action::loadSettings(QSettings& settings)
|
||||||
setLockCursorMode(settings.value("lockCursorToScreen", lockCursorToggle).toInt());
|
setLockCursorMode(settings.value("lockCursorToScreen", lockCursorToggle).toInt());
|
||||||
setActiveOnRelease(settings.value("activeOnRelease", false).toBool());
|
setActiveOnRelease(settings.value("activeOnRelease", false).toBool());
|
||||||
setHaveScreens(settings.value("hasScreens", false).toBool());
|
setHaveScreens(settings.value("hasScreens", false).toBool());
|
||||||
|
setHasCustomPosition(settings.value("hasCustomPosition", false).toBool());
|
||||||
|
setCustomX(settings.value("customX", 0).toInt());
|
||||||
|
setCustomY(settings.value("customY", 0).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Action::saveSettings(QSettings& settings) const
|
void Action::saveSettings(QSettings& settings) const
|
||||||
|
@ -153,6 +165,9 @@ void Action::saveSettings(QSettings& settings) const
|
||||||
settings.setValue("lockCursorToScreen", lockCursorMode());
|
settings.setValue("lockCursorToScreen", lockCursorMode());
|
||||||
settings.setValue("activeOnRelease", activeOnRelease());
|
settings.setValue("activeOnRelease", activeOnRelease());
|
||||||
settings.setValue("hasScreens", haveScreens());
|
settings.setValue("hasScreens", haveScreens());
|
||||||
|
settings.setValue("hasCustomPosition", hasCustomPosition());
|
||||||
|
settings.setValue("customX", customX());
|
||||||
|
settings.setValue("customY", customY());
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextStream& operator<<(QTextStream& outStream, const Action& action)
|
QTextStream& operator<<(QTextStream& outStream, const Action& action)
|
||||||
|
|
|
@ -72,6 +72,15 @@ class Action
|
||||||
bool haveScreens() const { return m_HasScreens; }
|
bool haveScreens() const { return m_HasScreens; }
|
||||||
void setHaveScreens(bool b) { m_HasScreens = b; }
|
void setHaveScreens(bool b) { m_HasScreens = b; }
|
||||||
|
|
||||||
|
bool hasCustomPosition() const { return m_hasCustomPosition; }
|
||||||
|
void setHasCustomPosition(bool b) { m_hasCustomPosition = b; }
|
||||||
|
|
||||||
|
int customX() const { return m_customX; }
|
||||||
|
void setCustomX(int x) { m_customX = x; }
|
||||||
|
|
||||||
|
int customY() const { return m_customY; }
|
||||||
|
void setCustomY(int y) { m_customY = y; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KeySequence m_KeySequence;
|
KeySequence m_KeySequence;
|
||||||
int m_Type;
|
int m_Type;
|
||||||
|
@ -81,6 +90,9 @@ class Action
|
||||||
int m_LockCursorMode;
|
int m_LockCursorMode;
|
||||||
bool m_ActiveOnRelease;
|
bool m_ActiveOnRelease;
|
||||||
bool m_HasScreens;
|
bool m_HasScreens;
|
||||||
|
bool m_hasCustomPosition;
|
||||||
|
int m_customX;
|
||||||
|
int m_customY;
|
||||||
|
|
||||||
static const char* m_ActionTypeNames[];
|
static const char* m_ActionTypeNames[];
|
||||||
static const char* m_SwitchDirectionNames[];
|
static const char* m_SwitchDirectionNames[];
|
||||||
|
|
|
@ -73,6 +73,11 @@ ActionDialog::ActionDialog(QWidget* parent, ServerConfig& config, Hotkey& hotkey
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize coordinate controls
|
||||||
|
m_pCheckBoxCustomPosition->setChecked(m_Action.hasCustomPosition());
|
||||||
|
m_pSpinBoxX->setValue(m_Action.customX());
|
||||||
|
m_pSpinBoxY->setValue(m_Action.customY());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionDialog::accept()
|
void ActionDialog::accept()
|
||||||
|
@ -93,6 +98,23 @@ void ActionDialog::accept()
|
||||||
m_Action.setSwitchDirection(m_pComboSwitchInDirection->currentIndex());
|
m_Action.setSwitchDirection(m_pComboSwitchInDirection->currentIndex());
|
||||||
m_Action.setLockCursorMode(m_pComboLockCursorToScreen->currentIndex());
|
m_Action.setLockCursorMode(m_pComboLockCursorToScreen->currentIndex());
|
||||||
m_Action.setActiveOnRelease(m_pRadioHotkeyReleased->isChecked());
|
m_Action.setActiveOnRelease(m_pRadioHotkeyReleased->isChecked());
|
||||||
|
|
||||||
|
// Save coordinate settings only for switchToScreen action
|
||||||
|
if (m_pButtonGroupType->checkedId() == Action::switchToScreen) {
|
||||||
|
m_Action.setHasCustomPosition(m_pCheckBoxCustomPosition->isChecked());
|
||||||
|
if (m_pCheckBoxCustomPosition->isChecked()) {
|
||||||
|
m_Action.setCustomX(m_pSpinBoxX->value());
|
||||||
|
m_Action.setCustomY(m_pSpinBoxY->value());
|
||||||
|
} else {
|
||||||
|
m_Action.setCustomX(0);
|
||||||
|
m_Action.setCustomY(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Clear custom position for other action types
|
||||||
|
m_Action.setHasCustomPosition(false);
|
||||||
|
m_Action.setCustomX(0);
|
||||||
|
m_Action.setCustomY(0);
|
||||||
|
}
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,96 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="m_pCheckBoxCustomPosition">
|
||||||
|
<property name="text">
|
||||||
|
<string>Set specific position</string>
|
||||||
|
</property>
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<spacer>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="m_pLabelX">
|
||||||
|
<property name="text">
|
||||||
|
<string>X:</string>
|
||||||
|
</property>
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="m_pSpinBoxX">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>9999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="m_pLabelY">
|
||||||
|
<property name="text">
|
||||||
|
<string>Y:</string>
|
||||||
|
</property>
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="m_pSpinBoxY">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>9999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout">
|
<layout class="QHBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -588,5 +678,85 @@
|
||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>m_pRadioSwitchToScreen</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>m_pCheckBoxCustomPosition</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>148</x>
|
||||||
|
<y>291</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>148</x>
|
||||||
|
<y>310</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>m_pCheckBoxCustomPosition</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>m_pLabelX</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>148</x>
|
||||||
|
<y>310</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>50</x>
|
||||||
|
<y>330</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>m_pCheckBoxCustomPosition</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>m_pSpinBoxX</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>148</x>
|
||||||
|
<y>310</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>100</x>
|
||||||
|
<y>330</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>m_pCheckBoxCustomPosition</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>m_pLabelY</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>148</x>
|
||||||
|
<y>310</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>150</x>
|
||||||
|
<y>330</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>m_pCheckBoxCustomPosition</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>m_pSpinBoxY</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>148</x>
|
||||||
|
<y>310</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>200</x>
|
||||||
|
<y>330</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
</connections>
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -139,6 +139,19 @@ bool KeySequence::appendKey(int key, int modifiers)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_QuoteLeft:
|
||||||
|
{
|
||||||
|
printf("GRAVE DEBUG: Qt::Key_QuoteLeft detected in GUI\n");
|
||||||
|
int mod = GraveModifier & (~m_Modifiers);
|
||||||
|
if (mod)
|
||||||
|
{
|
||||||
|
printf("GRAVE DEBUG: Adding GraveModifier to sequence: %08x\n", mod);
|
||||||
|
m_Sequence.append(mod);
|
||||||
|
m_Modifiers |= mod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// see if we can handle this key, if not, don't accept it
|
// see if we can handle this key, if not, don't accept it
|
||||||
if (keyToString(key).isEmpty())
|
if (keyToString(key).isEmpty())
|
||||||
|
@ -210,6 +223,9 @@ QString KeySequence::keyToString(int key)
|
||||||
if (key & Qt::MetaModifier)
|
if (key & Qt::MetaModifier)
|
||||||
return "Meta";
|
return "Meta";
|
||||||
|
|
||||||
|
if (key & GraveModifier)
|
||||||
|
return "Grave";
|
||||||
|
|
||||||
// treat key pad like normal keys (FIXME: we should have another lookup table for keypad keys instead)
|
// treat key pad like normal keys (FIXME: we should have another lookup table for keypad keys instead)
|
||||||
key &= ~Qt::KeypadModifier;
|
key &= ~Qt::KeypadModifier;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
class QSettings;
|
class QSettings;
|
||||||
|
|
||||||
|
// Custom modifier for grave key (not supported by Qt)
|
||||||
|
static const int GraveModifier = 0x20000000;
|
||||||
|
|
||||||
class KeySequence
|
class KeySequence
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -209,6 +209,7 @@ const KeyModifierNameMapEntry kModifierNameMap[] = {
|
||||||
{ "AltGr", KeyModifierAltGr },
|
{ "AltGr", KeyModifierAltGr },
|
||||||
// { "CapsLock", KeyModifierCapsLock },
|
// { "CapsLock", KeyModifierCapsLock },
|
||||||
{ "Control", KeyModifierControl },
|
{ "Control", KeyModifierControl },
|
||||||
|
{ "Grave", KeyModifierGrave },
|
||||||
{ "Meta", KeyModifierMeta },
|
{ "Meta", KeyModifierMeta },
|
||||||
// { "NumLock", KeyModifierNumLock },
|
// { "NumLock", KeyModifierNumLock },
|
||||||
// { "ScrollLock", KeyModifierScrollLock },
|
// { "ScrollLock", KeyModifierScrollLock },
|
||||||
|
|
|
@ -58,6 +58,7 @@ static const KeyModifierMask KeyModifierMeta = 0x0008;
|
||||||
static const KeyModifierMask KeyModifierSuper = 0x0010;
|
static const KeyModifierMask KeyModifierSuper = 0x0010;
|
||||||
static const KeyModifierMask KeyModifierAltGr = 0x0020;
|
static const KeyModifierMask KeyModifierAltGr = 0x0020;
|
||||||
static const KeyModifierMask KeyModifierLevel5Lock = 0x0040;
|
static const KeyModifierMask KeyModifierLevel5Lock = 0x0040;
|
||||||
|
static const KeyModifierMask KeyModifierGrave = 0x0080;
|
||||||
static const KeyModifierMask KeyModifierCapsLock = 0x1000;
|
static const KeyModifierMask KeyModifierCapsLock = 0x1000;
|
||||||
static const KeyModifierMask KeyModifierNumLock = 0x2000;
|
static const KeyModifierMask KeyModifierNumLock = 0x2000;
|
||||||
static const KeyModifierMask KeyModifierScrollLock = 0x4000;
|
static const KeyModifierMask KeyModifierScrollLock = 0x4000;
|
||||||
|
@ -73,6 +74,7 @@ static const UInt32 kKeyModifierBitMeta = 3;
|
||||||
static const UInt32 kKeyModifierBitSuper = 4;
|
static const UInt32 kKeyModifierBitSuper = 4;
|
||||||
static const UInt32 kKeyModifierBitAltGr = 5;
|
static const UInt32 kKeyModifierBitAltGr = 5;
|
||||||
static const UInt32 kKeyModifierBitLevel5Lock = 6;
|
static const UInt32 kKeyModifierBitLevel5Lock = 6;
|
||||||
|
static const UInt32 kKeyModifierBitGrave = 7;
|
||||||
static const UInt32 kKeyModifierBitCapsLock = 12;
|
static const UInt32 kKeyModifierBitCapsLock = 12;
|
||||||
static const UInt32 kKeyModifierBitNumLock = 13;
|
static const UInt32 kKeyModifierBitNumLock = 13;
|
||||||
static const UInt32 kKeyModifierBitScrollLock = 14;
|
static const UInt32 kKeyModifierBitScrollLock = 14;
|
||||||
|
@ -88,7 +90,8 @@ static const KeyModifierID kKeyModifierIDAlt = 3;
|
||||||
static const KeyModifierID kKeyModifierIDMeta = 4;
|
static const KeyModifierID kKeyModifierIDMeta = 4;
|
||||||
static const KeyModifierID kKeyModifierIDSuper = 5;
|
static const KeyModifierID kKeyModifierIDSuper = 5;
|
||||||
static const KeyModifierID kKeyModifierIDAltGr = 6;
|
static const KeyModifierID kKeyModifierIDAltGr = 6;
|
||||||
static const KeyModifierID kKeyModifierIDLast = 7;
|
static const KeyModifierID kKeyModifierIDGrave = 7;
|
||||||
|
static const KeyModifierID kKeyModifierIDLast = 8;
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
//! @name Key identifiers
|
//! @name Key identifiers
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
// use standard C++ string class for our string class
|
// use standard C++ string class for our string class
|
||||||
typedef std::string String;
|
typedef std::string String;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace barrier {
|
namespace barrier {
|
||||||
|
|
||||||
|
|
|
@ -317,6 +317,7 @@ XWindowsKeyState::updateKeysymMap(barrier::KeyMap& keyMap)
|
||||||
m_modifierToX[KeyModifierShift] = ShiftMask;
|
m_modifierToX[KeyModifierShift] = ShiftMask;
|
||||||
m_modifierToX[KeyModifierCapsLock] = LockMask;
|
m_modifierToX[KeyModifierCapsLock] = LockMask;
|
||||||
m_modifierToX[KeyModifierControl] = ControlMask;
|
m_modifierToX[KeyModifierControl] = ControlMask;
|
||||||
|
m_modifierToX[KeyModifierGrave] = Mod4Mask;
|
||||||
|
|
||||||
// prepare map from KeyID to KeyCode
|
// prepare map from KeyID to KeyCode
|
||||||
m_keyCodeFromKey.clear();
|
m_keyCodeFromKey.clear();
|
||||||
|
@ -779,6 +780,16 @@ XWindowsKeyState::updateKeysymMapXKB(barrier::KeyMap& keyMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add fallback for grave modifier if not found during XKB discovery
|
||||||
|
if (m_modifierToX.find(KeyModifierGrave) == m_modifierToX.end()) {
|
||||||
|
LOG((CLOG_DEBUG1 "XKB: Adding fallback mapping for grave modifier to Mod4"));
|
||||||
|
m_modifierToX[KeyModifierGrave] = Mod4Mask;
|
||||||
|
// Also update the reverse mapping for consistency
|
||||||
|
if (m_modifierFromX.size() > 3) { // Mod4 is bit 3
|
||||||
|
m_modifierFromX[3] |= KeyModifierGrave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// change all modifier masks to barrier masks from X masks
|
// change all modifier masks to barrier masks from X masks
|
||||||
keyMap.foreachKey(&XWindowsKeyState::remapKeyModifiers, this);
|
keyMap.foreachKey(&XWindowsKeyState::remapKeyModifiers, this);
|
||||||
|
|
||||||
|
|
|
@ -528,7 +528,7 @@ XWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||||
{
|
{
|
||||||
// only allow certain modifiers
|
// only allow certain modifiers
|
||||||
if ((mask & ~(KeyModifierShift | KeyModifierControl |
|
if ((mask & ~(KeyModifierShift | KeyModifierControl |
|
||||||
KeyModifierAlt | KeyModifierSuper)) != 0) {
|
KeyModifierAlt | KeyModifierSuper | KeyModifierGrave)) != 0) {
|
||||||
LOG((CLOG_DEBUG "could not map hotkey id=%04x mask=%04x", key, mask));
|
LOG((CLOG_DEBUG "could not map hotkey id=%04x mask=%04x", key, mask));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1646,6 +1646,9 @@ XWindowsUtil::getModifierBitForKeySym(KeySym keysym)
|
||||||
case XK_Scroll_Lock:
|
case XK_Scroll_Lock:
|
||||||
return kKeyModifierBitScrollLock;
|
return kKeyModifierBitScrollLock;
|
||||||
|
|
||||||
|
case XK_grave:
|
||||||
|
return kKeyModifierBitGrave;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return kKeyModifierBitNone;
|
return kKeyModifierBitNone;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1141,8 +1141,8 @@ void Config::parseAction(ConfigReadContext& s, const std::string& name,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (name == "switchToScreen") {
|
else if (name == "switchToScreen") {
|
||||||
if (args.size() != 1) {
|
if (args.size() != 1 && args.size() != 3) {
|
||||||
throw XConfigRead(s, "syntax for action: switchToScreen(name)");
|
throw XConfigRead(s, "syntax for action: switchToScreen(name[,x,y])");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string screen = args[0];
|
std::string screen = args[0];
|
||||||
|
@ -1153,7 +1153,19 @@ void Config::parseAction(ConfigReadContext& s, const std::string& name,
|
||||||
throw XConfigRead(s, "unknown screen name in switchToScreen");
|
throw XConfigRead(s, "unknown screen name in switchToScreen");
|
||||||
}
|
}
|
||||||
|
|
||||||
action = new InputFilter::SwitchToScreenAction(m_events, screen);
|
if (args.size() == 3) {
|
||||||
|
// Parse coordinates
|
||||||
|
int x, y;
|
||||||
|
try {
|
||||||
|
x = std::stoi(args[1]);
|
||||||
|
y = std::stoi(args[2]);
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
throw XConfigRead(s, "invalid coordinates in switchToScreen");
|
||||||
|
}
|
||||||
|
action = new InputFilter::SwitchToScreenAction(m_events, screen, x, y);
|
||||||
|
} else {
|
||||||
|
action = new InputFilter::SwitchToScreenAction(m_events, screen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (name == "toggleScreen") {
|
else if (name == "toggleScreen") {
|
||||||
|
|
|
@ -322,6 +322,20 @@ InputFilter::LockCursorToScreenAction::perform(const Event& event)
|
||||||
InputFilter::SwitchToScreenAction::SwitchToScreenAction(IEventQueue* events,
|
InputFilter::SwitchToScreenAction::SwitchToScreenAction(IEventQueue* events,
|
||||||
const std::string& screen) :
|
const std::string& screen) :
|
||||||
m_screen(screen),
|
m_screen(screen),
|
||||||
|
m_hasCustomPosition(false),
|
||||||
|
m_x(0),
|
||||||
|
m_y(0),
|
||||||
|
m_events(events)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
InputFilter::SwitchToScreenAction::SwitchToScreenAction(IEventQueue* events,
|
||||||
|
const std::string& screen, int x, int y) :
|
||||||
|
m_screen(screen),
|
||||||
|
m_hasCustomPosition(true),
|
||||||
|
m_x(x),
|
||||||
|
m_y(y),
|
||||||
m_events(events)
|
m_events(events)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
|
@ -332,15 +346,38 @@ std::string InputFilter::SwitchToScreenAction::getScreen() const
|
||||||
return m_screen;
|
return m_screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InputFilter::SwitchToScreenAction::hasCustomPosition() const
|
||||||
|
{
|
||||||
|
return m_hasCustomPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputFilter::SwitchToScreenAction::getX() const
|
||||||
|
{
|
||||||
|
return m_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputFilter::SwitchToScreenAction::getY() const
|
||||||
|
{
|
||||||
|
return m_y;
|
||||||
|
}
|
||||||
|
|
||||||
InputFilter::Action*
|
InputFilter::Action*
|
||||||
InputFilter::SwitchToScreenAction::clone() const
|
InputFilter::SwitchToScreenAction::clone() const
|
||||||
{
|
{
|
||||||
return new SwitchToScreenAction(*this);
|
if (m_hasCustomPosition) {
|
||||||
|
return new SwitchToScreenAction(m_events, m_screen, m_x, m_y);
|
||||||
|
} else {
|
||||||
|
return new SwitchToScreenAction(m_events, m_screen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string InputFilter::SwitchToScreenAction::format() const
|
std::string InputFilter::SwitchToScreenAction::format() const
|
||||||
{
|
{
|
||||||
return barrier::string::sprintf("switchToScreen(%s)", m_screen.c_str());
|
if (m_hasCustomPosition) {
|
||||||
|
return barrier::string::sprintf("switchToScreen(%s,%d,%d)", m_screen.c_str(), m_x, m_y);
|
||||||
|
} else {
|
||||||
|
return barrier::string::sprintf("switchToScreen(%s)", m_screen.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -356,8 +393,12 @@ InputFilter::SwitchToScreenAction::perform(const Event& event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// send event
|
// send event
|
||||||
Server::SwitchToScreenInfo* info =
|
Server::SwitchToScreenInfo* info;
|
||||||
Server::SwitchToScreenInfo::alloc(screen);
|
if (m_hasCustomPosition) {
|
||||||
|
info = Server::SwitchToScreenInfo::alloc(screen, m_x, m_y);
|
||||||
|
} else {
|
||||||
|
info = Server::SwitchToScreenInfo::alloc(screen);
|
||||||
|
}
|
||||||
m_events->addEvent(Event(m_events->forServer().switchToScreen(),
|
m_events->addEvent(Event(m_events->forServer().switchToScreen(),
|
||||||
event.getTarget(), info,
|
event.getTarget(), info,
|
||||||
Event::kDeliverImmediately));
|
Event::kDeliverImmediately));
|
||||||
|
|
|
@ -153,8 +153,12 @@ public:
|
||||||
class SwitchToScreenAction : public Action {
|
class SwitchToScreenAction : public Action {
|
||||||
public:
|
public:
|
||||||
SwitchToScreenAction(IEventQueue* events, const std::string& screen);
|
SwitchToScreenAction(IEventQueue* events, const std::string& screen);
|
||||||
|
SwitchToScreenAction(IEventQueue* events, const std::string& screen, int x, int y);
|
||||||
|
|
||||||
std::string getScreen() const;
|
std::string getScreen() const;
|
||||||
|
bool hasCustomPosition() const;
|
||||||
|
int getX() const;
|
||||||
|
int getY() const;
|
||||||
|
|
||||||
// Action overrides
|
// Action overrides
|
||||||
virtual Action* clone() const;
|
virtual Action* clone() const;
|
||||||
|
@ -163,6 +167,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_screen;
|
std::string m_screen;
|
||||||
|
bool m_hasCustomPosition;
|
||||||
|
int m_x;
|
||||||
|
int m_y;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1404,7 +1404,13 @@ Server::handleSwitchToScreenEvent(const Event& event, void*)
|
||||||
LOG((CLOG_DEBUG1 "screen \"%s\" not active", info->m_screen));
|
LOG((CLOG_DEBUG1 "screen \"%s\" not active", info->m_screen));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jumpToScreen(index->second);
|
if (info->m_hasCustomPosition) {
|
||||||
|
// Switch to specific coordinates
|
||||||
|
switchScreen(index->second, info->m_x, info->m_y, false);
|
||||||
|
} else {
|
||||||
|
// Use default behavior - jump to last cursor position
|
||||||
|
jumpToScreen(index->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2329,6 +2335,22 @@ Server::SwitchToScreenInfo::alloc(const std::string& screen)
|
||||||
SwitchToScreenInfo* info =
|
SwitchToScreenInfo* info =
|
||||||
(SwitchToScreenInfo*)malloc(sizeof(SwitchToScreenInfo) +
|
(SwitchToScreenInfo*)malloc(sizeof(SwitchToScreenInfo) +
|
||||||
screen.size());
|
screen.size());
|
||||||
|
info->m_hasCustomPosition = false;
|
||||||
|
info->m_x = 0;
|
||||||
|
info->m_y = 0;
|
||||||
|
strcpy(info->m_screen, screen.c_str());
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::SwitchToScreenInfo*
|
||||||
|
Server::SwitchToScreenInfo::alloc(const std::string& screen, SInt32 x, SInt32 y)
|
||||||
|
{
|
||||||
|
SwitchToScreenInfo* info =
|
||||||
|
(SwitchToScreenInfo*)malloc(sizeof(SwitchToScreenInfo) +
|
||||||
|
screen.size());
|
||||||
|
info->m_hasCustomPosition = true;
|
||||||
|
info->m_x = x;
|
||||||
|
info->m_y = y;
|
||||||
strcpy(info->m_screen, screen.c_str());
|
strcpy(info->m_screen, screen.c_str());
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,8 +63,12 @@ public:
|
||||||
class SwitchToScreenInfo {
|
class SwitchToScreenInfo {
|
||||||
public:
|
public:
|
||||||
static SwitchToScreenInfo* alloc(const std::string& screen);
|
static SwitchToScreenInfo* alloc(const std::string& screen);
|
||||||
|
static SwitchToScreenInfo* alloc(const std::string& screen, SInt32 x, SInt32 y);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool m_hasCustomPosition;
|
||||||
|
SInt32 m_x;
|
||||||
|
SInt32 m_y;
|
||||||
// this is a C-string; this type is a variable size structure
|
// this is a C-string; this type is a variable size structure
|
||||||
char m_screen[1];
|
char m_screen[1];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue