From ea9af22e62fdae7fc0bd707ef60bcf82ec3c4551 Mon Sep 17 00:00:00 2001 From: Arnon Gilboa Date: Wed, 30 Dec 2009 13:41:58 +0200 Subject: 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() --- client/monitor.cpp | 11 +++++++ client/monitor.h | 6 ++-- client/platform.h | 2 ++ client/red_window.h | 2 -- client/windows/platform.cpp | 33 ++++++++++++++----- client/windows/red_window.cpp | 4 +-- client/windows/red_window_p.h | 2 ++ client/x11/platform.cpp | 57 ++++++++++++++++++++++++--------- client/x11/red_window.cpp | 73 +++++++++++++++++-------------------------- client/x11/red_window_p.h | 4 ++- 10 files changed, 120 insertions(+), 74 deletions(-) diff --git a/client/monitor.cpp b/client/monitor.cpp index 85267693..d56cfadb 100644 --- a/client/monitor.cpp +++ b/client/monitor.cpp @@ -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(); +} diff --git a/client/monitor.h b/client/monitor.h index 59ec1e06..7a4ba3f2 100644 --- a/client/monitor.h +++ b/client/monitor.h @@ -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; diff --git a/client/platform.h b/client/platform.h index 07777c07..1b4ef435 100644 --- a/client/platform.h +++ b/client/platform.h @@ -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(); diff --git a/client/red_window.h b/client/red_window.h index 5721c53a..377d99be 100644 --- a/client/red_window.h +++ b/client/red_window.h @@ -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; diff --git a/client/windows/platform.cpp b/client/windows/platform.cpp index 11f13266..3400811f 100644 --- a/client/windows/platform.cpp +++ b/client/windows/platform.cpp @@ -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) {} diff --git a/client/windows/red_window.cpp b/client/windows/red_window.cpp index 14a7d291..47467194 100644 --- a/client/windows/red_window.cpp +++ b/client/windows/red_window.cpp @@ -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) diff --git a/client/windows/red_window_p.h b/client/windows/red_window_p.h index 4b5655ec..b35de571 100644 --- a/client/windows/red_window_p.h +++ b/client/windows/red_window_p.h @@ -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; diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp index 1a98e2ed..77025b6c 100644 --- a/client/x11/platform.cpp +++ b/client/x11/platform.cpp @@ -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 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, diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp index ee43b5a5..795a7bbd 100644 --- a/client/x11/red_window.cpp +++ b/client/x11/red_window.cpp @@ -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() diff --git a/client/x11/red_window_p.h b/client/x11/red_window_p.h index 77933f93..df306344 100644 --- a/client/x11/red_window_p.h +++ b/client/x11/red_window_p.h @@ -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; -- cgit