mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 14:41:25 +00:00
spice: position mouse in primary monitor center after full screen toggle
-move _focused & _pointer_in_window from RedWindow to RedWindow_p's -move shadow focus & cursor handling to sync() -add reset_cursor_pos() to Platform -Monitor set_mode()/restore() use virtual do_set_mode()/do_restore()
This commit is contained in:
parent
02a07b2c06
commit
ea9af22e62
@ -18,6 +18,7 @@
|
||||
#include "common.h"
|
||||
#include "monitor.h"
|
||||
#include "debug.h"
|
||||
#include "platform.h"
|
||||
|
||||
uint32_t Monitor::self_monitors_change = 0;
|
||||
|
||||
@ -33,3 +34,13 @@ bool Monitor::is_self_change()
|
||||
return self_monitors_change != 0;
|
||||
}
|
||||
|
||||
void Monitor::set_mode(int width, int height)
|
||||
{
|
||||
do_set_mode(width, height);
|
||||
Platform::reset_cursor_pos();
|
||||
}
|
||||
void Monitor::restore()
|
||||
{
|
||||
do_restore();
|
||||
Platform::reset_cursor_pos();
|
||||
}
|
||||
|
||||
@ -29,8 +29,8 @@ public:
|
||||
void set_free() {_free = true;}
|
||||
void set_used() {_free = false;}
|
||||
|
||||
virtual void set_mode(int width, int height) = 0;
|
||||
virtual void restore() = 0;
|
||||
void set_mode(int width, int height);
|
||||
void restore();
|
||||
virtual int get_depth() = 0;
|
||||
virtual Point get_position() = 0;
|
||||
virtual Point get_size() const = 0;
|
||||
@ -41,6 +41,8 @@ public:
|
||||
|
||||
protected:
|
||||
virtual ~Monitor() {}
|
||||
virtual void do_set_mode(int width, int height) = 0;
|
||||
virtual void do_restore() = 0;
|
||||
|
||||
private:
|
||||
int _id;
|
||||
|
||||
@ -101,6 +101,8 @@ public:
|
||||
|
||||
static uint32_t get_keyboard_modifiers();
|
||||
|
||||
static void reset_cursor_pos();
|
||||
|
||||
static LocalCursor* create_local_cursor(CursorData* cursor_data);
|
||||
static LocalCursor* create_inactive_cursor();
|
||||
static LocalCursor* create_default_cursor();
|
||||
|
||||
@ -105,8 +105,6 @@ private:
|
||||
Type _type;
|
||||
LocalCursor* _local_cursor;
|
||||
bool _cursor_visible;
|
||||
bool _focused;
|
||||
bool _pointer_in_window;
|
||||
bool _trace_key_interception;
|
||||
bool _key_interception_on;
|
||||
Menu* _menu;
|
||||
|
||||
@ -227,8 +227,6 @@ class WinMonitor: public Monitor {
|
||||
public:
|
||||
WinMonitor(int id, const wchar_t* name, const wchar_t* string);
|
||||
|
||||
virtual void set_mode(int width, int height);
|
||||
virtual void restore();
|
||||
virtual int get_depth() { return _depth;}
|
||||
virtual Point get_position();
|
||||
virtual Point get_size() const { Point size = {_width, _height}; return size;}
|
||||
@ -237,6 +235,8 @@ public:
|
||||
|
||||
protected:
|
||||
virtual ~WinMonitor();
|
||||
virtual void do_set_mode(int width, int height);
|
||||
virtual void do_restore();
|
||||
|
||||
private:
|
||||
void update_position();
|
||||
@ -266,7 +266,7 @@ WinMonitor::WinMonitor(int id, const wchar_t* name, const wchar_t* string)
|
||||
|
||||
WinMonitor::~WinMonitor()
|
||||
{
|
||||
restore();
|
||||
do_restore();
|
||||
}
|
||||
|
||||
void WinMonitor::update_position()
|
||||
@ -362,7 +362,7 @@ bool WinMonitor::best_display_setting(uint32_t width, uint32_t height, uint32_t
|
||||
== DISP_CHANGE_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void WinMonitor::set_mode(int width, int height)
|
||||
void WinMonitor::do_set_mode(int width, int height)
|
||||
{
|
||||
update_position();
|
||||
if (width == _width && height == _height) {
|
||||
@ -380,31 +380,37 @@ void WinMonitor::set_mode(int width, int height)
|
||||
update_position();
|
||||
}
|
||||
|
||||
void WinMonitor::restore()
|
||||
void WinMonitor::do_restore()
|
||||
{
|
||||
if (_active) {
|
||||
_active = false;
|
||||
self_monitors_change++;
|
||||
ChangeDisplaySettingsEx(_dev_name.c_str(), NULL, NULL, 0, NULL);
|
||||
self_monitors_change--;
|
||||
update_position();
|
||||
}
|
||||
}
|
||||
|
||||
static MonitorsList monitors;
|
||||
static Monitor* primary_monitor = NULL;
|
||||
|
||||
const MonitorsList& Platform::init_monitors()
|
||||
{
|
||||
ASSERT(monitors.empty());
|
||||
|
||||
int id = 0;
|
||||
Monitor* mon;
|
||||
DISPLAY_DEVICE device_info;
|
||||
DWORD device_id = 0;
|
||||
device_info.cb = sizeof(device_info);
|
||||
while (EnumDisplayDevices(NULL, device_id, &device_info, 0)) {
|
||||
if ((device_info.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) &&
|
||||
!(device_info.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) {
|
||||
monitors.push_back(new WinMonitor(id++, device_info.DeviceName,
|
||||
device_info.DeviceString));
|
||||
!(device_info.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) {
|
||||
mon = new WinMonitor(id++, device_info.DeviceName, device_info.DeviceString);
|
||||
monitors.push_back(mon);
|
||||
if (device_info.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
|
||||
primary_monitor = mon;
|
||||
}
|
||||
}
|
||||
device_id++;
|
||||
}
|
||||
@ -413,6 +419,7 @@ const MonitorsList& Platform::init_monitors()
|
||||
|
||||
void Platform::destroy_monitors()
|
||||
{
|
||||
primary_monitor = NULL;
|
||||
while (!monitors.empty()) {
|
||||
Monitor* monitor = monitors.front();
|
||||
monitors.pop_front();
|
||||
@ -507,6 +514,16 @@ uint32_t Platform::get_keyboard_modifiers()
|
||||
KEY_BIT(keymap, VK_RMENU, R_ALT_MODIFIER);
|
||||
}
|
||||
|
||||
void Platform::reset_cursor_pos()
|
||||
{
|
||||
if (!primary_monitor) {
|
||||
return;
|
||||
}
|
||||
Point pos = primary_monitor->get_position();
|
||||
Point size = primary_monitor->get_size();
|
||||
SetCursorPos(pos.x + size.x / 2, pos.y + size.y / 2);
|
||||
}
|
||||
|
||||
class WinBaseLocalCursor: public LocalCursor {
|
||||
public:
|
||||
WinBaseLocalCursor() : _handle (0) {}
|
||||
|
||||
@ -327,6 +327,8 @@ RedWindow_p::RedWindow_p()
|
||||
, _modal_refs (0)
|
||||
, _no_taskmgr_dll (NULL)
|
||||
, _no_taskmgr_hook (NULL)
|
||||
, _focused (false)
|
||||
, _pointer_in_window (false)
|
||||
, _minimized (false)
|
||||
, _valid_pos (false)
|
||||
, _sys_menu (NULL)
|
||||
@ -406,8 +408,6 @@ RedWindow::RedWindow(RedWindow::Listener& listener, int screen_id)
|
||||
, _type (TYPE_NORMAL)
|
||||
, _local_cursor (NULL)
|
||||
, _cursor_visible (true)
|
||||
, _focused (false)
|
||||
, _pointer_in_window (false)
|
||||
, _trace_key_interception (false)
|
||||
, _key_interception_on (false)
|
||||
, _menu (NULL)
|
||||
|
||||
@ -56,6 +56,8 @@ protected:
|
||||
uint32_t _modal_refs;
|
||||
HMODULE _no_taskmgr_dll;
|
||||
HHOOK _no_taskmgr_hook;
|
||||
bool _focused;
|
||||
bool _pointer_in_window;
|
||||
bool _minimized;
|
||||
bool _valid_pos;
|
||||
int _x;
|
||||
|
||||
@ -507,18 +507,20 @@ public:
|
||||
monitors.push_back(this);
|
||||
}
|
||||
|
||||
virtual void set_mode(int width, int height)
|
||||
{
|
||||
_out_of_sync = width > get_width() || height > get_height();
|
||||
}
|
||||
|
||||
virtual void restore() {}
|
||||
virtual int get_depth() { return XPlatform::get_vinfo()[0]->depth;}
|
||||
virtual Point get_position() { return XScreen::get_position();}
|
||||
virtual Point get_size() const { Point pt = {get_width(), get_height()}; return pt;}
|
||||
virtual bool is_out_of_sync() { return _out_of_sync;}
|
||||
virtual int get_screen_id() { return get_screen();}
|
||||
|
||||
protected:
|
||||
virtual void do_set_mode(int width, int height)
|
||||
{
|
||||
_out_of_sync = width > get_width() || height > get_height();
|
||||
}
|
||||
|
||||
virtual void do_restore() {}
|
||||
|
||||
private:
|
||||
bool _out_of_sync;
|
||||
};
|
||||
@ -529,14 +531,16 @@ public:
|
||||
virtual ~DynamicScreen();
|
||||
|
||||
void publish_monitors(MonitorsList& monitors);
|
||||
virtual void set_mode(int width, int height);
|
||||
virtual void restore();
|
||||
virtual int get_depth() { return XPlatform::get_vinfo()[0]->depth;}
|
||||
virtual Point get_position() { return XScreen::get_position();}
|
||||
virtual Point get_size() const { Point pt = {get_width(), get_height()}; return pt;}
|
||||
virtual bool is_out_of_sync() { return _out_of_sync;}
|
||||
virtual int get_screen_id() { return get_screen();}
|
||||
|
||||
protected:
|
||||
virtual void do_set_mode(int width, int height);
|
||||
virtual void do_restore();
|
||||
|
||||
private:
|
||||
bool set_screen_size(int size_index);
|
||||
|
||||
@ -589,7 +593,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void DynamicScreen::set_mode(int width, int height)
|
||||
void DynamicScreen::do_set_mode(int width, int height)
|
||||
{
|
||||
int num_sizes;
|
||||
|
||||
@ -611,7 +615,7 @@ void DynamicScreen::set_mode(int width, int height)
|
||||
X_DEBUG_SYNC(get_display());
|
||||
}
|
||||
|
||||
void DynamicScreen::restore()
|
||||
void DynamicScreen::do_restore()
|
||||
{
|
||||
X_DEBUG_SYNC(get_display());
|
||||
if (is_broken() || (get_width() == _saved_width && get_height() == _saved_height)) {
|
||||
@ -705,8 +709,6 @@ public:
|
||||
XMonitor(MultyMonScreen& container, int id, RRCrtc crtc);
|
||||
virtual ~XMonitor();
|
||||
|
||||
virtual void set_mode(int width, int height);
|
||||
virtual void restore();
|
||||
virtual int get_depth();
|
||||
virtual Point get_position();
|
||||
virtual Point get_size() const;
|
||||
@ -735,6 +737,10 @@ public:
|
||||
static void inc_change_ref() { Monitor::self_monitors_change++;}
|
||||
static void dec_change_ref() { Monitor::self_monitors_change--;}
|
||||
|
||||
protected:
|
||||
virtual void do_set_mode(int width, int height);
|
||||
virtual void do_restore();
|
||||
|
||||
private:
|
||||
void update_position();
|
||||
bool finde_mode_in_outputs(RRMode mode, int start_index, XRRScreenResources* res);
|
||||
@ -1673,7 +1679,7 @@ XRRModeInfo* XMonitor::find_mode(int width, int height, XRRScreenResources* res)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void XMonitor::set_mode(int width, int height)
|
||||
void XMonitor::do_set_mode(int width, int height)
|
||||
{
|
||||
if (width == _size.x && height == _size.y) {
|
||||
_out_of_sync = false;
|
||||
@ -1759,12 +1765,12 @@ bool XMonitor::position_changed()
|
||||
return _position.x != _saved_position.x || _position.y != _saved_position.y;
|
||||
}
|
||||
|
||||
void XMonitor::restore()
|
||||
void XMonitor::do_restore()
|
||||
{
|
||||
if (!mode_changed()) {
|
||||
return;
|
||||
}
|
||||
set_mode(_saved_size.x, _saved_size.y);
|
||||
do_set_mode(_saved_size.x, _saved_size.y);
|
||||
}
|
||||
|
||||
int XMonitor::get_depth()
|
||||
@ -1847,6 +1853,7 @@ void XMonitor::set_mode(const XRRModeInfo& mode)
|
||||
#endif
|
||||
|
||||
static MonitorsList monitors;
|
||||
static Monitor* primary_monitor = NULL;
|
||||
|
||||
typedef std::list<XScreen*> ScreenList;
|
||||
static ScreenList screens;
|
||||
@ -1877,11 +1884,20 @@ const MonitorsList& Platform::init_monitors()
|
||||
for (; iter != screens.end(); iter++) {
|
||||
(*iter)->publish_monitors(monitors);
|
||||
}
|
||||
MonitorsList::iterator mon_iter = monitors.begin();
|
||||
for (; mon_iter != monitors.end(); mon_iter++) {
|
||||
Monitor *mon = *mon_iter;
|
||||
if (mon->get_id() == 0) {
|
||||
primary_monitor = mon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return monitors;
|
||||
}
|
||||
|
||||
void Platform::destroy_monitors()
|
||||
{
|
||||
primary_monitor = NULL;
|
||||
monitors.clear();
|
||||
while (!screens.empty()) {
|
||||
XScreen* screen = screens.front();
|
||||
@ -2295,6 +2311,17 @@ uint32_t Platform::get_keyboard_modifiers()
|
||||
key_bit(keymap, XK_Alt_R, R_ALT_MODIFIER);
|
||||
}
|
||||
|
||||
void Platform::reset_cursor_pos()
|
||||
{
|
||||
if (!primary_monitor) {
|
||||
return;
|
||||
}
|
||||
Point pos = primary_monitor->get_position();
|
||||
Point size = primary_monitor->get_size();
|
||||
Window root_window = RootWindow(x_display, DefaultScreen(x_display));
|
||||
XWarpPointer(x_display, None, root_window, 0, 0, 0, 0, pos.x + size.x / 2, pos.y + size.y / 2);
|
||||
}
|
||||
|
||||
WaveRecordAbstract* Platform::create_recorder(RecordClient& client,
|
||||
uint32_t sampels_per_sec,
|
||||
uint32_t bits_per_sample,
|
||||
|
||||
@ -889,7 +889,7 @@ void RedWindow_p::win_proc(XEvent& event)
|
||||
if (!red_window->_ignore_pointer) {
|
||||
Point origin = red_window->get_origin();
|
||||
red_window->on_pointer_enter(event.xcrossing.x - origin.x, event.xcrossing.y - origin.y,
|
||||
to_red_buttons_state(event.xmotion.state));
|
||||
to_red_buttons_state(event.xcrossing.state));
|
||||
} else {
|
||||
red_window->_shadow_pointer_state = true;
|
||||
memcpy(&red_window->_shadow_pointer_event, &event, sizeof(XEvent));
|
||||
@ -906,13 +906,35 @@ void RedWindow_p::win_proc(XEvent& event)
|
||||
}
|
||||
}
|
||||
|
||||
void RedWindow_p::sync()
|
||||
void RedWindow_p::sync(bool shadowed)
|
||||
{
|
||||
if (shadowed) {
|
||||
_ignore_foucs = true;
|
||||
_ignore_pointer = true;
|
||||
_shadow_foucs_state = _focused;
|
||||
_shadow_pointer_state = _pointer_in_window;
|
||||
_shadow_focus_event.xany.serial = 0;
|
||||
}
|
||||
XSync(x_display, False);
|
||||
XEvent event;
|
||||
while (XCheckWindowEvent(x_display, _win, ~long(0), &event)) {
|
||||
win_proc(event);
|
||||
}
|
||||
if (!shadowed) {
|
||||
return;
|
||||
}
|
||||
_ignore_foucs = false;
|
||||
_ignore_pointer = false;
|
||||
if (_shadow_foucs_state != _focused) {
|
||||
DBG(0, "put back shadowed focus event");
|
||||
XPutBackEvent(x_display, &_shadow_focus_event);
|
||||
} else if (_shadow_focus_event.xany.serial > 0) {
|
||||
focus_serial = _shadow_focus_event.xany.serial;
|
||||
}
|
||||
if (_shadow_pointer_state != _pointer_in_window) {
|
||||
DBG(0, "put back shadowed pointer event");
|
||||
XPutBackEvent(x_display, &_shadow_pointer_event);
|
||||
}
|
||||
}
|
||||
|
||||
void RedWindow_p::wait_for_reparent()
|
||||
@ -1023,7 +1045,9 @@ RedWindow_p::RedWindow_p()
|
||||
: _win (None)
|
||||
, _glcont_copy (NULL)
|
||||
, _icon (NULL)
|
||||
, _focused (false)
|
||||
, _ignore_foucs (false)
|
||||
, _pointer_in_window (false)
|
||||
, _ignore_pointer (false)
|
||||
{
|
||||
}
|
||||
@ -1193,8 +1217,6 @@ RedWindow::RedWindow(RedWindow::Listener& listener, int screen)
|
||||
, _type (TYPE_NORMAL)
|
||||
, _local_cursor (NULL)
|
||||
, _cursor_visible (true)
|
||||
, _focused (false)
|
||||
, _pointer_in_window (false)
|
||||
, _trace_key_interception (false)
|
||||
, _key_interception_on (false)
|
||||
, _menu (NULL)
|
||||
@ -1600,55 +1622,18 @@ void RedWindow::do_start_key_interception()
|
||||
// LeaveNotify and EnterNotify.
|
||||
|
||||
ASSERT(_focused);
|
||||
_ignore_foucs = true;
|
||||
_ignore_pointer = true;
|
||||
_shadow_foucs_state = true;
|
||||
_shadow_pointer_state = true;
|
||||
_shadow_focus_event.xany.serial = 0;
|
||||
XGrabKeyboard(x_display, _win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
sync();
|
||||
sync(true);
|
||||
_listener.on_start_key_interception();
|
||||
_ignore_foucs = false;
|
||||
_ignore_pointer = false;
|
||||
_key_interception_on = true;
|
||||
if (!_shadow_foucs_state) {
|
||||
DBG(0, "put back shadowed focus out");
|
||||
XPutBackEvent(x_display, &_shadow_focus_event);
|
||||
} else if (_shadow_focus_event.xany.serial > 0) {
|
||||
ASSERT(focus_window == this);
|
||||
focus_serial = _shadow_focus_event.xany.serial;
|
||||
}
|
||||
|
||||
if (!_shadow_pointer_state) {
|
||||
DBG(0, "put back shadowed pointer leave");
|
||||
XPutBackEvent(x_display, &_shadow_pointer_event);
|
||||
}
|
||||
}
|
||||
|
||||
void RedWindow::do_stop_key_interception()
|
||||
{
|
||||
_ignore_foucs = true;
|
||||
_ignore_pointer = true;
|
||||
_shadow_foucs_state = _focused;
|
||||
_shadow_pointer_state = _pointer_in_window;
|
||||
_shadow_focus_event.xany.serial = 0;
|
||||
XUngrabKeyboard(x_display, CurrentTime);
|
||||
sync();
|
||||
sync(true);
|
||||
_key_interception_on = false;
|
||||
_listener.on_stop_key_interception();
|
||||
_ignore_foucs = false;
|
||||
_ignore_pointer = false;
|
||||
if (_shadow_foucs_state != _focused) {
|
||||
DBG(0, "put back shadowed focus event");
|
||||
XPutBackEvent(x_display, &_shadow_focus_event);
|
||||
} else if (_shadow_focus_event.xany.serial > 0) {
|
||||
focus_serial = _shadow_focus_event.xany.serial;
|
||||
}
|
||||
|
||||
if (_shadow_pointer_state != _pointer_in_window) {
|
||||
DBG(0, "put back shadowed pointer event");
|
||||
XPutBackEvent(x_display, &_shadow_pointer_event);
|
||||
}
|
||||
}
|
||||
|
||||
void RedWindow::start_key_interception()
|
||||
@ -1705,7 +1690,7 @@ void RedWindow::hide_cursor()
|
||||
void RedWindow::release_mouse()
|
||||
{
|
||||
XUngrabPointer(x_display, CurrentTime);
|
||||
sync();
|
||||
sync(true);
|
||||
}
|
||||
|
||||
void RedWindow::cupture_mouse()
|
||||
|
||||
@ -41,7 +41,7 @@ public:
|
||||
void wait_for_reparent();
|
||||
void wait_for_map();
|
||||
void wait_for_unmap();
|
||||
void sync();
|
||||
void sync(bool shadowed = false);
|
||||
void set_visibale(bool vis) { _visibale = vis;}
|
||||
void move_to_current_desktop();
|
||||
Window get_window() {return _win;}
|
||||
@ -61,9 +61,11 @@ protected:
|
||||
Point _show_pos;
|
||||
GLXContext _glcont_copy;
|
||||
Icon* _icon;
|
||||
bool _focused;
|
||||
bool _ignore_foucs;
|
||||
bool _shadow_foucs_state;
|
||||
XEvent _shadow_focus_event;
|
||||
bool _pointer_in_window;
|
||||
bool _ignore_pointer;
|
||||
bool _shadow_pointer_state;
|
||||
XEvent _shadow_pointer_event;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user