summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnon Gilboa <agilboa@redhat.com>2009-12-30 13:41:58 +0200
committerYaniv Kamay <ykamay@redhat.com>2010-01-03 17:55:32 +0200
commit4202ee3945bdcbe78326562b49817c086dc67e18 (patch)
tree3243083507043f72924a7651c71d0a5af94167b6
parent8ce343daa08d2807428f71f552e22ab5319f8aea (diff)
downloadspice-4202ee3945bdcbe78326562b49817c086dc67e18.tar.gz
spice-4202ee3945bdcbe78326562b49817c086dc67e18.tar.xz
spice-4202ee3945bdcbe78326562b49817c086dc67e18.zip
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()
-rw-r--r--client/monitor.cpp11
-rw-r--r--client/monitor.h6
-rw-r--r--client/platform.h2
-rw-r--r--client/red_window.h2
-rw-r--r--client/windows/platform.cpp33
-rw-r--r--client/windows/red_window.cpp4
-rw-r--r--client/windows/red_window_p.h2
-rw-r--r--client/x11/platform.cpp57
-rw-r--r--client/x11/red_window.cpp75
-rw-r--r--client/x11/red_window_p.h4
10 files changed, 123 insertions, 73 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 c32b8634..ff89181b 100644
--- a/client/platform.h
+++ b/client/platform.h
@@ -100,6 +100,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 6f51f70e..65d5efd5 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 6d5deba5..2988827d 100644
--- a/client/windows/platform.cpp
+++ b/client/windows/platform.cpp
@@ -222,8 +222,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;}
@@ -232,6 +230,8 @@ public:
protected:
virtual ~WinMonitor();
+ virtual void do_set_mode(int width, int height);
+ virtual void do_restore();
private:
void update_position();
@@ -261,7 +261,7 @@ WinMonitor::WinMonitor(int id, const wchar_t* name, const wchar_t* string)
WinMonitor::~WinMonitor()
{
- restore();
+ do_restore();
}
void WinMonitor::update_position()
@@ -357,7 +357,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) {
@@ -375,31 +375,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++;
}
@@ -408,6 +414,7 @@ const MonitorsList& Platform::init_monitors()
void Platform::destroy_monitors()
{
+ primary_monitor = NULL;
while (!monitors.empty()) {
Monitor* monitor = monitors.front();
monitors.pop_front();
@@ -502,6 +509,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 554c1770..0d4c4a56 100644
--- a/client/windows/red_window.cpp
+++ b/client/windows/red_window.cpp
@@ -265,6 +265,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)
@@ -344,8 +346,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 d00092be..a1c08ca8 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -491,18 +491,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;
};
@@ -513,14 +515,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);
@@ -573,7 +577,7 @@ public:
}
};
-void DynamicScreen::set_mode(int width, int height)
+void DynamicScreen::do_set_mode(int width, int height)
{
int num_sizes;
@@ -595,7 +599,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)) {
@@ -689,8 +693,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;
@@ -719,6 +721,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);
@@ -1657,7 +1663,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;
@@ -1743,12 +1749,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()
@@ -1831,6 +1837,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;
@@ -1861,11 +1868,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();
@@ -2257,6 +2273,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 1647cd4d..7e25c608 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -844,6 +844,10 @@ void RedWindow_p::win_proc(XEvent& event)
case EnterNotify:
if (!red_window->_ignore_pointer) {
red_window->on_pointer_enter();
+ Point origin = red_window->get_origin();
+ red_window->get_listener().on_mouse_motion(event.xcrossing.x - origin.x,
+ event.xcrossing.y - origin.y,
+ to_red_buttons_state(event.xcrossing.state));
} else {
red_window->_shadow_pointer_state = true;
memcpy(&red_window->_shadow_pointer_event, &event, sizeof(XEvent));
@@ -860,13 +864,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()
@@ -977,7 +1003,9 @@ RedWindow_p::RedWindow_p()
: _win (None)
, _glcont_copy (NULL)
, _icon (NULL)
+ , _focused (false)
, _ignore_foucs (false)
+ , _pointer_in_window (false)
, _ignore_pointer (false)
{
}
@@ -1147,8 +1175,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)
@@ -1554,55 +1580,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()
@@ -1659,7 +1648,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 8b98b4a6..ab9ce048 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;}
@@ -60,9 +60,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;