Merge lp:~3v1n0/unity/panelmenu-fixes into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merged at revision: 1617
Proposed branch: lp:~3v1n0/unity/panelmenu-fixes
Merge into: lp:unity
Diff against target: 1499 lines (+470/-231)
12 files modified
plugins/unityshell/src/PanelIndicatorsView.cpp (+55/-41)
plugins/unityshell/src/PanelIndicatorsView.h (+13/-1)
plugins/unityshell/src/PanelMenuView.cpp (+146/-86)
plugins/unityshell/src/PanelMenuView.h (+9/-7)
plugins/unityshell/src/PanelTitlebarGrabAreaView.cpp (+35/-33)
plugins/unityshell/src/PanelTitlebarGrabAreaView.h (+11/-10)
plugins/unityshell/src/PanelView.cpp (+20/-9)
plugins/unityshell/src/PanelView.h (+3/-0)
plugins/unityshell/src/PluginAdapter.cpp (+33/-1)
plugins/unityshell/src/WindowButtons.cpp (+14/-2)
plugins/unityshell/src/WindowManager.cpp (+5/-1)
services/panel-service.c (+126/-40)
To merge this branch: bzr merge lp:~3v1n0/unity/panelmenu-fixes
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Jason Smith (community) Approve
Gord Allott (community) Approve
Review via email: mp+76133@code.launchpad.net

Description of the change

Fixed lots of other PanelMenuView related bugs (see the linked list of "In Progress bugs" for reference).

In particular, I've also changed these things:
 - Moving to nux::GetGraphicsDisplay()->GetMouseScreenCoord() (instead of gdk functions,
   warning this needs nux bzr-453 or newer not to crash, thanks to Jay for fixing!)
 - Checking for mouse position after closing menus to hide/show them (bug bug #843670)
 - Checking for mouse position after dragging a window to to hide/show menus
 - Fix for PluginAdapter not to consider unmapped windows as maximized (bug #781215)
 - Panel-service: correctly close menus when releasing mouse outside a menu title (bug #844309)
 - Panel-service: cache the indicator entries geometry and use the values for checking mouse position
 - Don't redecorate windows on maximization drag (bug #838923)
 - panel-service: Remove id2entry_hash and use sscanf to parse the entries IDs
 - PanelView: track mouse position only when it has been changed (fix bug #834065)
 - PanelMenuView / PanelIndicatorsView: remove code duplication for adding an entry
 - Better mouse grab management using only PanelTitleGrabArea
 - PanelMenuView: even more checks to avoid to show/hide menus when we shouldn't
 - PanelView: sync geometries for real

See the related commit logs for more informations.

This branch, to work properly, needs the updated UnityCore code that I've pushed in my lp:~3v1n0/unity/menus-switching-hacks branch (for the entries geometry things), so in the case that the other branch isn't accepted, we need to port its UnityCore changes here.

PS: for the record, this is the previous merge request for this branch: https://code.launchpad.net/~3v1n0/unity/panelmenu-fixes/+merge/73622

To post a comment you must log in.
Revision history for this message
Jason Smith (jassmith) wrote :

Has a merge conflict if you merge your other branch in first. Conflicts are non-trivial (at least for me to fix)

review: Needs Fixing
Revision history for this message
Gord Allott (gordallott) wrote :

looks okay from here +1

review: Approve
Revision history for this message
Jason Smith (jassmith) wrote :

Switching to approved

review: Approve
Revision history for this message
Neil J. Patel (njpatel) wrote :

Excellent work Marco, approved.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/PanelIndicatorsView.cpp'
2--- plugins/unityshell/src/PanelIndicatorsView.cpp 2011-09-20 17:25:06 +0000
3+++ plugins/unityshell/src/PanelIndicatorsView.cpp 2011-09-25 12:09:24 +0000
4@@ -21,14 +21,9 @@
5 #include <Nux/Nux.h>
6 #include <Nux/Area.h>
7 #include <Nux/HLayout.h>
8-#include <Nux/VLayout.h>
9
10 #include <NuxCore/Logger.h>
11
12-#include <NuxGraphics/GLThread.h>
13-#include <Nux/BaseWindow.h>
14-#include <Nux/WindowCompositor.h>
15-
16 #include "PanelIndicatorsView.h"
17
18 #include <UnityCore/Variant.h>
19@@ -55,9 +50,9 @@
20
21 PanelIndicatorsView::~PanelIndicatorsView()
22 {
23- for (auto it = indicators_connections_.begin(); it != indicators_connections_.end(); it++)
24+ for (auto ind : indicators_connections_)
25 {
26- for (auto conn : it->second)
27+ for (auto conn : ind.second)
28 conn.disconnect();
29 }
30 }
31@@ -130,11 +125,9 @@
32 PanelIndicatorsView::QueueDraw()
33 {
34 nux::View::QueueDraw();
35- for (auto i = entries_.begin(), end = entries_.end(); i != end; ++i)
36- {
37- if (i->second)
38- i->second->QueueDraw();
39- }
40+
41+ for (auto entry : entries_)
42+ entry.second->QueueDraw();
43 }
44
45 bool
46@@ -155,9 +148,9 @@
47 bool
48 PanelIndicatorsView::ActivateIfSensitive()
49 {
50- for (auto i = entries_.begin(), end = entries_.end(); i != end; ++i)
51+ for (auto entry : entries_)
52 {
53- PanelIndicatorEntryView* view = i->second;
54+ PanelIndicatorEntryView* view = entry.second;
55 if (view->IsSensitive())
56 {
57 view->Activate();
58@@ -170,11 +163,8 @@
59 void
60 PanelIndicatorsView::GetGeometryForSync(indicator::EntryLocationMap& locations)
61 {
62- for (auto i = entries_.begin(), end = entries_.end(); i != end; ++i)
63- {
64- if (i->second)
65- i->second->GetGeometryForSync(locations);
66- }
67+ for (auto entry : entries_)
68+ entry.second->GetGeometryForSync(locations);
69 }
70
71 bool
72@@ -228,37 +218,45 @@
73 PanelIndicatorsView::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
74 {
75 GfxContext.PushClippingRectangle(GetGeometry());
76- if (layout_)
77- layout_->ProcessDraw(GfxContext, force_draw);
78+ layout_->ProcessDraw(GfxContext, force_draw);
79 GfxContext.PopClippingRectangle();
80 }
81
82-void
83-PanelIndicatorsView::OnEntryAdded(indicator::Entry::Ptr const& entry)
84+PanelIndicatorEntryView *
85+PanelIndicatorsView::AddEntry(indicator::Entry::Ptr const& entry, int padding, IndicatorEntryPosition pos)
86 {
87- auto view = new PanelIndicatorEntryView(entry);
88+ PanelIndicatorEntryView *view;
89+ int entry_pos = pos;
90+
91+ if (padding > -1)
92+ view = new PanelIndicatorEntryView(entry, padding);
93+ else
94+ view = new PanelIndicatorEntryView(entry);
95+
96 view->refreshed.connect(sigc::mem_fun(this, &PanelIndicatorsView::OnEntryRefreshed));
97
98- int indicator_pos = nux::NUX_LAYOUT_BEGIN;
99-
100- if (entry->priority() > -1)
101+ if (entry_pos == IndicatorEntryPosition::AUTO)
102 {
103- for (nux::Area* &area : layout_->GetChildren())
104+ entry_pos = nux::NUX_LAYOUT_BEGIN;
105+
106+ if (entry->priority() > -1)
107 {
108- auto en = dynamic_cast<PanelIndicatorEntryView*>(area);
109-
110- if (en)
111+ for (auto area : layout_->GetChildren())
112 {
113- if (en && entry->priority() <= en->GetEntryPriority())
114- break;
115-
116- indicator_pos++;
117+ auto en = dynamic_cast<PanelIndicatorEntryView*>(area);
118+
119+ if (en)
120+ {
121+ if (en && entry->priority() <= en->GetEntryPriority())
122+ break;
123+
124+ entry_pos++;
125+ }
126 }
127 }
128 }
129
130- nux::LayoutPosition pos = (nux::LayoutPosition) indicator_pos;
131- layout_->AddView(view, 0, nux::eCenter, nux::eFull, 1.0, pos);
132+ layout_->AddView(view, 0, nux::eCenter, nux::eFull, 1.0, (nux::LayoutPosition) entry_pos);
133 layout_->SetContentDistribution(nux::eStackRight);
134 entries_[entry->id()] = view;
135
136@@ -267,6 +265,14 @@
137 QueueDraw();
138
139 on_indicator_updated.emit(view);
140+
141+ return view;
142+}
143+
144+void
145+PanelIndicatorsView::OnEntryAdded(indicator::Entry::Ptr const& entry)
146+{
147+ AddEntry(entry);
148 }
149
150 void
151@@ -279,28 +285,36 @@
152 }
153
154 void
155-PanelIndicatorsView::OnEntryRemoved(std::string const& entry_id)
156+PanelIndicatorsView::RemoveEntry(std::string const& entry_id)
157 {
158 PanelIndicatorEntryView* view = entries_[entry_id];
159
160 if (view)
161 {
162- on_indicator_updated.emit(view);
163 layout_->RemoveChildObject(view);
164 entries_.erase(entry_id);
165+ on_indicator_updated.emit(view);
166
167 QueueRelayout();
168 QueueDraw();
169 }
170 }
171
172-void PanelIndicatorsView::DashShown()
173+void
174+PanelIndicatorsView::OnEntryRemoved(std::string const& entry_id)
175+{
176+ RemoveEntry(entry_id);
177+}
178+
179+void
180+PanelIndicatorsView::DashShown()
181 {
182 for (auto entry: entries_)
183 entry.second->DashShown();
184 }
185
186-void PanelIndicatorsView::DashHidden()
187+void
188+PanelIndicatorsView::DashHidden()
189 {
190 for (auto entry: entries_)
191 entry.second->DashHidden();
192
193=== modified file 'plugins/unityshell/src/PanelIndicatorsView.h'
194--- plugins/unityshell/src/PanelIndicatorsView.h 2011-09-15 11:33:58 +0000
195+++ plugins/unityshell/src/PanelIndicatorsView.h 2011-09-25 12:09:24 +0000
196@@ -22,6 +22,7 @@
197 #define PANEL_INDICATORS_VIEW_H
198
199 #include <Nux/View.h>
200+#include <Nux/Layout.h>
201
202 #include <UnityCore/Indicator.h>
203
204@@ -41,6 +42,17 @@
205 void AddIndicator(indicator::Indicator::Ptr const& indicator);
206 void RemoveIndicator(indicator::Indicator::Ptr const& indicator);
207
208+ typedef enum {
209+ AUTO = -1,
210+ START = nux::NUX_LAYOUT_BEGIN,
211+ END = nux::NUX_LAYOUT_END,
212+ } IndicatorEntryPosition;
213+
214+ PanelIndicatorEntryView* AddEntry(indicator::Entry::Ptr const& entry,
215+ int padding = -1,
216+ IndicatorEntryPosition pos = AUTO);
217+ void RemoveEntry(std::string const& entry_id);
218+
219 bool OnPointerMoved(int x, int y);
220 bool ActivateEntry(std::string const& entry_id);
221 bool ActivateIfSensitive();
222@@ -51,7 +63,7 @@
223 virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
224 virtual void QueueDraw();
225
226- virtual void OnEntryAdded(indicator::Entry::Ptr const& proxy);
227+ virtual void OnEntryAdded(indicator::Entry::Ptr const& entry);
228 virtual void OnEntryRefreshed(PanelIndicatorEntryView* view);
229 virtual void OnEntryRemoved(std::string const& entry_id);
230
231
232=== modified file 'plugins/unityshell/src/PanelMenuView.cpp'
233--- plugins/unityshell/src/PanelMenuView.cpp 2011-09-19 03:03:53 +0000
234+++ plugins/unityshell/src/PanelMenuView.cpp 2011-09-25 12:09:24 +0000
235@@ -15,11 +15,11 @@
236 * along with this program. If not, see <http://www.gnu.org/licenses/>.
237 *
238 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
239+ * Marco Trevisan <mail@3v1n0.net>
240 */
241 #include <glib.h>
242 #include <pango/pangocairo.h>
243 #include <gtk/gtk.h>
244-#include <X11/cursorfont.h>
245
246 #include <Nux/Nux.h>
247 #include <Nux/HLayout.h>
248@@ -64,7 +64,6 @@
249 _title_layer(NULL),
250 _util_cg(CAIRO_FORMAT_ARGB32, 1, 1),
251 _gradient_texture(NULL),
252- _title_tex(NULL),
253 _is_inside(false),
254 _is_maximized(false),
255 _is_own_window(false),
256@@ -77,15 +76,12 @@
257 _monitor(0),
258 _active_xid(0),
259 _active_moved_id(0),
260+ _update_show_now_id(0),
261 _place_shown_interest(0),
262 _place_hidden_interest(0)
263 {
264 WindowManager* win_manager;
265
266- _matcher = bamf_matcher_get_default();
267- _activate_window_changed_id = g_signal_connect(_matcher, "active-window-changed",
268- G_CALLBACK(on_active_window_changed), this);
269-
270 // TODO: kill _menu_layout - should just use the _layout defined
271 // in the base class.
272 _menu_layout = new nux::HLayout("", NUX_TRACKER_LOCATION);
273@@ -96,6 +92,10 @@
274 */
275 layout_ = _menu_layout;
276
277+ _matcher = bamf_matcher_get_default();
278+ _activate_window_changed_id = g_signal_connect(_matcher, "active-window-changed",
279+ G_CALLBACK(on_active_window_changed), this);
280+
281 _padding = padding;
282 _name_changed_callback_instance = NULL;
283 _name_changed_callback_id = 0;
284@@ -109,23 +109,23 @@
285 _window_buttons->restore_clicked.connect(sigc::mem_fun(this, &PanelMenuView::OnRestoreClicked));
286 _window_buttons->mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter));
287 _window_buttons->mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave));
288- _window_buttons->mouse_move.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseMove));
289+ //_window_buttons->mouse_move.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseMove));
290
291 _panel_titlebar_grab_area = new PanelTitlebarGrabArea();
292 _panel_titlebar_grab_area->SetParentObject(this);
293 _panel_titlebar_grab_area->SinkReference();
294+ _panel_titlebar_grab_area->mouse_down.connect(sigc::mem_fun(this, &PanelMenuView::OnMouseMiddleClicked));
295 _panel_titlebar_grab_area->mouse_down.connect(sigc::mem_fun(this, &PanelMenuView::OnMaximizedGrabStart));
296 _panel_titlebar_grab_area->mouse_drag.connect(sigc::mem_fun(this, &PanelMenuView::OnMaximizedGrabMove));
297 _panel_titlebar_grab_area->mouse_up.connect(sigc::mem_fun(this, &PanelMenuView::OnMaximizedGrabEnd));
298- _panel_titlebar_grab_area->mouse_doubleleftclick.connect(sigc::mem_fun(this, &PanelMenuView::OnMouseDoubleClicked));
299- _panel_titlebar_grab_area->mouse_middleclick.connect(sigc::mem_fun(this, &PanelMenuView::OnMouseMiddleClicked));
300+ _panel_titlebar_grab_area->mouse_double_click.connect(sigc::mem_fun(this, &PanelMenuView::OnMouseDoubleClicked));
301
302 win_manager = WindowManager::Default();
303
304 win_manager->window_minimized.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowMinimized));
305 win_manager->window_unminimized.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowUnminimized));
306- win_manager->initiate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadInitiate));
307- win_manager->terminate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadTerminate));
308+ //win_manager->initiate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadInitiate));
309+ //win_manager->terminate_spread.connect(sigc::mem_fun(this, &PanelMenuView::OnSpreadTerminate));
310
311 win_manager->window_maximized.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowMaximized));
312 win_manager->window_restored.connect(sigc::mem_fun(this, &PanelMenuView::OnWindowRestored));
313@@ -136,7 +136,7 @@
314
315 mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter));
316 mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave));
317- mouse_move.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseMove));
318+ //mouse_move.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseMove));
319
320 _panel_titlebar_grab_area->mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter));
321 _panel_titlebar_grab_area->mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave));
322@@ -166,8 +166,6 @@
323
324 if (_title_layer)
325 delete _title_layer;
326- if (_title_tex)
327- _title_tex->UnReference();
328
329 _menu_layout->UnReference();
330 _window_buttons->UnReference();
331@@ -345,11 +343,9 @@
332 else
333 {
334 bool have_valid_entries = false;
335- Entries::iterator it, eit = entries_.end();
336-
337- for (it = entries_.begin(); it != eit; ++it)
338+ for (auto entry : entries_)
339 {
340- if (it->second->IsEntryValid())
341+ if (entry.second->IsEntryValid())
342 {
343 have_valid_entries = true;
344 break;
345@@ -408,12 +404,12 @@
346 nux::TexCoordXForm texxform1;
347
348 // Modulate the checkboard and the gradient texture
349- if (_title_tex)
350+ if (_title_layer)
351 GfxContext.QRP_2TexMod(geo.x, geo.y,
352 geo.width, geo.height,
353 _gradient_texture, texxform0,
354 nux::color::White,
355- _title_tex->GetDeviceTexture(),
356+ _title_layer->GetDeviceTexture(),
357 texxform1,
358 nux::color::White);
359
360@@ -449,14 +445,16 @@
361 if (!_is_own_window && !_places_showing && _we_control_active)
362 {
363 if (_is_inside || _last_active_view || _show_now_activated)
364- layout_->ProcessDraw(GfxContext, force_draw);
365- }
366-
367- if ((!_is_own_window && _we_control_active && _is_maximized && (_is_inside || _show_now_activated)) ||
368- _places_showing)
369 {
370- _window_buttons->ProcessDraw(GfxContext, true);
371+ _menu_layout->ProcessDraw(GfxContext, force_draw);
372 }
373+ }
374+
375+ if ((!_is_own_window && _we_control_active && _is_maximized &&
376+ (_is_inside || _show_now_activated)) || _places_showing)
377+ {
378+ _window_buttons->ProcessDraw(GfxContext, true);
379+ }
380
381 GfxContext.PopClippingRectangle();
382 }
383@@ -682,12 +680,7 @@
384 nux::color::White,
385 true,
386 rop);
387-
388- if (_title_tex)
389- _title_tex->UnReference();
390-
391- _title_tex = texture2D;
392-
393+ texture2D->UnReference();
394 g_free(label);
395 }
396
397@@ -709,26 +702,26 @@
398 FullRedraw();
399 }
400
401-void PanelMenuView::OnEntryAdded(unity::indicator::Entry::Ptr const& proxy)
402+void
403+PanelMenuView::OnEntryAdded(unity::indicator::Entry::Ptr const& entry)
404 {
405- PanelIndicatorEntryView* view = new PanelIndicatorEntryView(proxy, 6);
406+ auto view = AddEntry(entry, 6, IndicatorEntryPosition::END);
407+
408+ entry->show_now_changed.connect(sigc::mem_fun(this, &PanelMenuView::UpdateShowNow));
409+
410 view->active_changed.connect(sigc::mem_fun(this, &PanelMenuView::OnActiveChanged));
411- view->refreshed.connect(sigc::mem_fun(this, &PanelIndicatorsView::OnEntryRefreshed));
412- proxy->show_now_changed.connect(sigc::mem_fun(this, &PanelMenuView::UpdateShowNow));
413-
414- _menu_layout->AddView(view, 0, nux::eCenter, nux::eFull, 1.0, nux::NUX_LAYOUT_END);
415- _menu_layout->SetContentDistribution(nux::eStackLeft);
416-
417- entries_[proxy->id()] = view;
418- AddChild(view);
419-
420 view->mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter));
421 view->mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave));
422-
423- QueueRelayout();
424- QueueDraw();
425-
426- on_indicator_updated.emit(view);
427+}
428+
429+void
430+PanelMenuView::AllMenusClosed()
431+{
432+ auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
433+ _is_inside = GetAbsoluteGeometry().IsPointInside(mouse.x, mouse.y);
434+ _last_active_view = NULL;
435+
436+ FullRedraw();
437 }
438
439 void
440@@ -815,7 +808,6 @@
441 void
442 PanelMenuView::OnWindowMinimized(guint32 xid)
443 {
444-
445 if (WindowManager::Default()->IsWindowMaximized(xid))
446 {
447 WindowManager::Default()->Decorate(xid);
448@@ -844,25 +836,32 @@
449 PanelMenuView::OnWindowMaximized(guint xid)
450 {
451 BamfWindow* window;
452+ bool updated = false;
453
454 window = bamf_matcher_get_active_window(_matcher);
455 if (BAMF_IS_WINDOW(window) && bamf_window_get_xid(window) == xid)
456 {
457 _is_maximized = true;
458+
459+ // We need to update the _is_inside state in the case of maximization by grab
460+ auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
461+ _is_inside = GetAbsoluteGeometry().IsPointInside(mouse.x, mouse.y);
462+ updated = true;
463 }
464
465 // update the state of the window in the _decor_map
466 _decor_map[xid] = WindowManager::Default()->IsWindowDecorated(xid);
467
468 if (_decor_map[xid])
469- {
470 WindowManager::Default()->Undecorate(xid);
471- }
472
473 _maximized_set.insert(xid);
474
475- Refresh();
476- FullRedraw();
477+ if (updated)
478+ {
479+ Refresh();
480+ FullRedraw();
481+ }
482 }
483
484 void
485@@ -870,6 +869,9 @@
486 {
487 BamfWindow* window;
488
489+ if (_maximized_set.find(xid) == _maximized_set.end())
490+ return;
491+
492 window = bamf_matcher_get_active_window(_matcher);
493 if (BAMF_IS_WINDOW(window) && bamf_window_get_xid(window) == xid)
494 {
495@@ -878,9 +880,7 @@
496 }
497
498 if (_decor_map[xid])
499- {
500 WindowManager::Default()->Decorate(xid);
501- }
502
503 _maximized_set.erase(xid);
504
505@@ -976,7 +976,7 @@
506 nux::Geometry monitor = UScreen::GetDefault()->GetMonitorGeometry(_monitor);
507
508 // Find the front-most of the maximized windows we are controlling
509- foreach(guint32 xid, _maximized_set)
510+ for (auto xid : _maximized_set)
511 {
512 // We can safely assume only the front-most is visible
513 if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid)
514@@ -994,37 +994,48 @@
515 }
516
517 void
518-PanelMenuView::OnMaximizedGrabStart(int x, int y)
519+PanelMenuView::OnMaximizedGrabStart(int x, int y, unsigned long button_flags, unsigned long)
520 {
521+ if (nux::GetEventButton(button_flags) != 1 || _places_showing)
522+ return;
523+
524 // When Start dragging the panelmenu of a maximized window, change cursor
525 // to simulate the dragging, waiting to go out of the panel area.
526 //
527 // This is a workaround to avoid that the grid plugin would be fired
528 // showing the window shape preview effect. See bug #838923
529 if (GetMaximizedWindow() != 0)
530- {
531- Display* d = nux::GetGraphicsDisplay()->GetX11Display();
532- nux::BaseWindow *bw = static_cast<nux::BaseWindow*>(GetTopLevelViewWindow());
533- Cursor c = XCreateFontCursor(d, XC_fleur);
534- XDefineCursor(d, bw->GetInputWindowId(), c);
535- XFreeCursor(d, c);
536- }
537+ _panel_titlebar_grab_area->SetGrabbed(true);
538 }
539
540 void
541-PanelMenuView::OnMaximizedGrabMove(int x, int y, int, int, unsigned long, unsigned long)
542+PanelMenuView::OnMaximizedGrabMove(int x, int y, int, int, unsigned long button_flags, unsigned long)
543 {
544+// FIXME nux doesn't export it with drag event.
545+// if (nux::GetEventButton(button_flags) != 1)
546+// return;
547+
548+ // We use this, due to the problem above
549+ if (!_panel_titlebar_grab_area->IsGrabbed())
550+ return;
551+
552+ auto panel = static_cast<nux::BaseWindow*>(GetTopLevelViewWindow());
553+
554+ if (!panel)
555+ return;
556+
557+ x += _panel_titlebar_grab_area->GetAbsoluteX();
558+ y += _panel_titlebar_grab_area->GetAbsoluteY();
559+
560 guint32 window_xid = GetMaximizedWindow();
561
562 // When the drag goes out from the Panel, start the real movement.
563 //
564 // This is a workaround to avoid that the grid plugin would be fired
565 // showing the window shape preview effect. See bug #838923
566- if (window_xid != 0 && !GetAbsoluteGeometry().IsPointInside(x, y))
567+ if (window_xid != 0 && panel && !panel->GetAbsoluteGeometry().IsPointInside(x, y))
568 {
569- Display* d = nux::GetGraphicsDisplay()->GetX11Display();
570- nux::BaseWindow *bw = static_cast<nux::BaseWindow*>(GetTopLevelViewWindow());
571- XUndefineCursor(d, bw->GetInputWindowId());
572+ _panel_titlebar_grab_area->SetGrabbed(false);
573
574 WindowManager::Default()->Activate(window_xid);
575 _is_inside = true;
576@@ -1038,15 +1049,25 @@
577 void
578 PanelMenuView::OnMaximizedGrabEnd(int x, int y, unsigned long, unsigned long)
579 {
580- // Restore the window cursor to default.
581- Display* d = nux::GetGraphicsDisplay()->GetX11Display();
582- nux::BaseWindow *bw = static_cast<nux::BaseWindow*>(GetTopLevelViewWindow());
583- XUndefineCursor(d, bw->GetInputWindowId());
584+ _panel_titlebar_grab_area->SetGrabbed(false);
585+
586+ x += _panel_titlebar_grab_area->GetAbsoluteX();
587+ y += _panel_titlebar_grab_area->GetAbsoluteY();
588+ _is_inside = GetAbsoluteGeometry().IsPointInside(x, y);
589+
590+ if (!_is_inside)
591+ _is_grabbed = false;
592+
593+ Refresh();
594+ FullRedraw();
595 }
596
597 void
598-PanelMenuView::OnMouseDoubleClicked()
599+PanelMenuView::OnMouseDoubleClicked(int x, int y, unsigned long button_flags, unsigned long)
600 {
601+ if (nux::GetEventButton(button_flags) != 1)
602+ return;
603+
604 guint32 window_xid = GetMaximizedWindow();
605
606 if (window_xid != 0)
607@@ -1057,8 +1078,11 @@
608 }
609
610 void
611-PanelMenuView::OnMouseMiddleClicked()
612+PanelMenuView::OnMouseMiddleClicked(int x, int y, unsigned long button_flags, unsigned long)
613 {
614+ if (nux::GetEventButton(button_flags) != 2)
615+ return;
616+
617 guint32 window_xid = GetMaximizedWindow();
618
619 if (window_xid != 0)
620@@ -1120,23 +1144,58 @@
621 self->QueueDraw();
622 }
623
624-void PanelMenuView::UpdateShowNow(bool ignore)
625+gboolean
626+PanelMenuView::UpdateShowNowWithDelay(PanelMenuView *self)
627 {
628- // NOTE: This is sub-optimal. We are getting a dbus event for every menu,
629- // and every time that is setting the show now status of an indicator entry,
630- // we are getting the event raised, and we are ignoring the status, and
631- // looking through all the entries to see if any are shown.
632- _show_now_activated = false;
633+ bool active = false;
634
635- for (Entries::iterator it = entries_.begin(); it != entries_.end(); ++it)
636+ for (auto entry : self->entries_)
637 {
638- PanelIndicatorEntryView* view = it->second;
639- if (view->GetShowNow()) {
640- _show_now_activated = true;
641+ if (entry.second->GetShowNow())
642+ {
643+ active = true;
644 break;
645 }
646 }
647- QueueDraw();
648+
649+ self->_update_show_now_id = 0;
650+
651+ if (active)
652+ {
653+ self->_show_now_activated = true;
654+ self->QueueDraw();
655+ }
656+
657+ return FALSE;
658+}
659+
660+void
661+PanelMenuView::UpdateShowNow(bool status)
662+{
663+ /* When we get a show now event, if we are requested to show the menus,
664+ * we take the last incoming event and we wait for small delay (to avoid the
665+ * Alt+Tab conflict) then we check if any menuitem has requested to show.
666+ * If the status is false, we just check that the menus entries are hidden
667+ * and we remove any eventual delayed request */
668+
669+ if (!status && _show_now_activated)
670+ {
671+ _show_now_activated = false;
672+ QueueDraw();
673+ }
674+
675+ if (_update_show_now_id != 0)
676+ {
677+ g_source_remove(_update_show_now_id);
678+ _update_show_now_id = 0;
679+ }
680+
681+ if (status && !_show_now_activated)
682+ {
683+ _update_show_now_id = g_timeout_add(180, (GSourceFunc)
684+ &PanelMenuView::UpdateShowNowWithDelay,
685+ this);
686+ }
687 }
688
689 void
690@@ -1167,6 +1226,7 @@
691 _is_grabbed = false;
692 else
693 _is_inside = true;
694+
695 FullRedraw();
696 }
697 }
698
699=== modified file 'plugins/unityshell/src/PanelMenuView.h'
700--- plugins/unityshell/src/PanelMenuView.h 2011-09-03 02:47:41 +0000
701+++ plugins/unityshell/src/PanelMenuView.h 2011-09-25 12:09:24 +0000
702@@ -76,13 +76,14 @@
703
704 guint32 GetMaximizedWindow();
705
706- void OnMaximizedGrabStart(int x, int y);
707+ void OnMaximizedGrabStart(int, int, unsigned long, unsigned long);
708 void OnMaximizedGrabMove(int, int, int, int, unsigned long, unsigned long);
709- void OnMaximizedGrabEnd(int x, int y, unsigned long, unsigned long);
710- void OnMouseDoubleClicked();
711- void OnMouseMiddleClicked();
712+ void OnMaximizedGrabEnd(int, int, unsigned long, unsigned long);
713+ void OnMouseDoubleClicked(int, int, unsigned long, unsigned long);
714+ void OnMouseMiddleClicked(int, int, unsigned long, unsigned long);
715
716 void Refresh();
717+ void AllMenusClosed();
718
719 void OnCloseClicked();
720 void OnMinimizeClicked();
721@@ -101,7 +102,7 @@
722 void OnPanelViewMouseEnter(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state);
723 void OnPanelViewMouseLeave(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state);
724 void OnPanelViewMouseMove(int x, int y, int dx, int dy, unsigned long mouse_button_state, unsigned long special_keys_state);
725- virtual void OnEntryAdded(unity::indicator::Entry::Ptr const& proxy);
726+ virtual void OnEntryAdded(unity::indicator::Entry::Ptr const& entry);
727
728 private:
729 gchar* GetActiveViewName();
730@@ -109,15 +110,15 @@
731 static void OnPlaceViewHidden(GVariant* data, PanelMenuView* self);
732 void UpdateShowNow(bool ignore);
733 static gboolean UpdateActiveWindowPosition(PanelMenuView* self);
734+ static gboolean UpdateShowNowWithDelay(PanelMenuView* self);
735
736 private:
737 BamfMatcher* _matcher;
738
739- nux::AbstractPaintLayer* _title_layer;
740+ nux::TextureLayer* _title_layer;
741 nux::HLayout* _menu_layout;
742 nux::CairoGraphics _util_cg;
743 nux::ObjectPtr<nux::IOpenGLBaseTexture> _gradient_texture;
744- nux::BaseTexture* _title_tex;
745
746 bool _is_inside;
747 bool _is_grabbed;
748@@ -144,6 +145,7 @@
749 int _monitor;
750 guint32 _active_xid;
751 guint32 _active_moved_id;
752+ guint32 _update_show_now_id;
753 nux::Geometry _monitor_geo;
754
755 gulong _activate_window_changed_id;
756
757=== modified file 'plugins/unityshell/src/PanelTitlebarGrabAreaView.cpp'
758--- plugins/unityshell/src/PanelTitlebarGrabAreaView.cpp 2011-09-06 18:30:26 +0000
759+++ plugins/unityshell/src/PanelTitlebarGrabAreaView.cpp 2011-09-25 12:09:24 +0000
760@@ -1,3 +1,4 @@
761+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
762 /*
763 * Copyright (C) 2010 Canonical Ltd
764 *
765@@ -14,8 +15,9 @@
766 * along with this program. If not, see <http://www.gnu.org/licenses/>.
767 *
768 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
769- * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
770- * Authored by: Didier Roche <didier.roche@canonical.com>
771+ * Sam Spilsbury <sam.spilsbury@canonical.com>
772+ * Didier Roche <didier.roche@canonical.com>
773+ * Marco Trevisan (Treviño) <mail@3v1n0.net>
774 */
775
776 #include <Nux/Nux.h>
777@@ -31,19 +33,13 @@
778 #include <UnityCore/Variant.h>
779
780 #include <glib.h>
781+#include <X11/cursorfont.h>
782
783 #define DELTA_MOUSE_DOUBLE_CLICK 500000000
784
785-enum
786-{
787- BUTTON_CLOSE = 0,
788- BUTTON_MINIMISE,
789- BUTTON_UNMAXIMISE
790-};
791-
792-
793 PanelTitlebarGrabArea::PanelTitlebarGrabArea()
794 : InputArea(NUX_TRACKER_LOCATION)
795+ , _grab_cursor(None)
796 {
797 // FIXME: the two following functions should be used instead of the insane trick with fixed value. But nux is broken
798 // right now and we need jay to focus on other things
799@@ -52,38 +48,44 @@
800 InputArea::mouse_up.connect(sigc::mem_fun(this, &PanelTitlebarGrabArea::RecvMouseUp));
801 _last_click_time.tv_sec = 0;
802 _last_click_time.tv_nsec = 0;
803-
804- // connect the *Click events before the *Down ones otherwise, weird race happens
805- InputArea::mouse_down.connect(sigc::mem_fun(this, &PanelTitlebarGrabArea::RecvMouseDown));
806 }
807
808
809 PanelTitlebarGrabArea::~PanelTitlebarGrabArea()
810 {
811-}
812-
813-void PanelTitlebarGrabArea::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
814-{
815- int button = nux::GetEventButton(button_flags);
816- if (button == 1)
817- {
818- mouse_down.emit(x, y);
819- }
820- else if (button == 2)
821- {
822- mouse_middleclick.emit();
823- }
824+ if (_grab_cursor)
825+ XFreeCursor(nux::GetGraphicsDisplay()->GetX11Display(), _grab_cursor);
826+}
827+
828+void PanelTitlebarGrabArea::SetGrabbed(bool enabled)
829+{
830+ auto display = nux::GetGraphicsDisplay()->GetX11Display();
831+ auto panel_window = static_cast<nux::BaseWindow*>(GetTopLevelViewWindow());
832+
833+ if (!panel_window || !display)
834+ return;
835+
836+ if (enabled && !_grab_cursor)
837+ {
838+ _grab_cursor = XCreateFontCursor(display, XC_fleur);
839+ XDefineCursor(display, panel_window->GetInputWindowId(), _grab_cursor);
840+ }
841+ else if (!enabled && _grab_cursor)
842+ {
843+ XUndefineCursor(display, panel_window->GetInputWindowId());
844+ XFreeCursor(display, _grab_cursor);
845+ _grab_cursor = None;
846+ }
847+}
848+
849+bool PanelTitlebarGrabArea::IsGrabbed()
850+{
851+ return _grab_cursor != None;
852 }
853
854 void PanelTitlebarGrabArea::RecvMouseDoubleClick(int x, int y, unsigned long button_flags, unsigned long key_flags)
855 {
856- int button = nux::GetEventButton(button_flags);
857- if (button == 1)
858- {
859- mouse_doubleleftclick.emit();
860- return;
861- }
862- mouse_doubleclick.emit();
863+ mouse_double_click.emit(x, y, button_flags, key_flags);
864 }
865
866 // TODO: can be safely removed once OnMouseDoubleClick is fixed in nux
867
868=== modified file 'plugins/unityshell/src/PanelTitlebarGrabAreaView.h'
869--- plugins/unityshell/src/PanelTitlebarGrabAreaView.h 2011-07-21 14:59:25 +0000
870+++ plugins/unityshell/src/PanelTitlebarGrabAreaView.h 2011-09-25 12:09:24 +0000
871@@ -1,3 +1,4 @@
872+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
873 /*
874 * Copyright (C) 2010 Canonical Ltd
875 *
876@@ -14,8 +15,9 @@
877 * along with this program. If not, see <http://www.gnu.org/licenses/>.
878 *
879 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
880- * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
881- * Authored by: Didier Roche <didier.roche@canonical.com>
882+ * Sam Spilsbury <sam.spilsbury@canonical.com>
883+ * Didier Roche <didier.roche@canonical.com>
884+ * Marco Trevisan (Treviño) <mail@3v1n0.net>
885 */
886
887 #ifndef PANEL_TITLEBAR_GRAB_AREA_H
888@@ -38,23 +40,22 @@
889 PanelTitlebarGrabArea();
890 ~PanelTitlebarGrabArea();
891
892- sigc::signal <void, int, int> mouse_down;
893- sigc::signal <void> mouse_middleclick;
894- sigc::signal <void> mouse_doubleclick;
895- sigc::signal <void> mouse_doubleleftclick;
896+ void SetGrabbed(bool enabled);
897+ bool IsGrabbed();
898
899-protected:
900+private:
901 void RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags);
902 void RecvMouseDoubleClick(int x, int y, unsigned long button_flags, unsigned long key_flags);
903 // TODO: can be safely removed once OnMouseDoubleClick is fixed in nux
904 void RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags);
905 struct timespec time_diff(struct timespec start, struct timespec end);
906
907- struct timespec _last_click_time;
908-
909 const gchar* GetName();
910 const gchar* GetChildsName();
911- void AddProperties(GVariantBuilder* builder);
912+ void AddProperties(GVariantBuilder* builder);
913+
914+ struct timespec _last_click_time;
915+ Cursor _grab_cursor;
916 };
917
918 #endif
919
920=== modified file 'plugins/unityshell/src/PanelView.cpp'
921--- plugins/unityshell/src/PanelView.cpp 2011-09-20 16:23:55 +0000
922+++ plugins/unityshell/src/PanelView.cpp 2011-09-25 12:09:24 +0000
923@@ -190,7 +190,7 @@
924
925 const gchar* PanelView::GetName()
926 {
927- return "Panel";
928+ return "UnityPanel";
929 }
930
931 const gchar*
932@@ -459,6 +459,7 @@
933
934 void PanelView::OnIndicatorViewUpdated(PanelIndicatorEntryView* view)
935 {
936+ _needs_geo_sync = true;
937 ComputeChildLayout();
938 }
939
940@@ -488,12 +489,19 @@
941 if (!ret) _indicators->ActivateEntry(entry_id);
942 }
943
944-static gboolean track_menu_pointer(gpointer data)
945-{
946- PanelView *self = (PanelView*)data;
947- gint x, y;
948- gdk_display_get_pointer(gdk_display_get_default(), NULL, &x, &y, NULL);
949- self->OnMenuPointerMoved(x, y);
950+void PanelView::TrackMenuPointer()
951+{
952+ auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
953+ if (_tracked_pointer_pos != mouse)
954+ {
955+ OnMenuPointerMoved(mouse.x, mouse.y);
956+ _tracked_pointer_pos = mouse;
957+ }
958+}
959+
960+static gboolean track_menu_pointer(PanelView *self)
961+{
962+ self->TrackMenuPointer();
963 return TRUE;
964 }
965
966@@ -512,7 +520,7 @@
967 // process. All the motion events will go to unity-panel-service while
968 // scrubbing because the active panel menu has (needs) the pointer grab.
969 //
970- _track_menu_pointer_id = g_timeout_add(16, track_menu_pointer, this);
971+ _track_menu_pointer_id = g_timeout_add(16, (GSourceFunc) track_menu_pointer, this);
972 }
973 else if (!active)
974 {
975@@ -521,6 +529,8 @@
976 g_source_remove(_track_menu_pointer_id);
977 _track_menu_pointer_id = 0;
978 }
979+ _menu_view->AllMenusClosed();
980+ _tracked_pointer_pos = {-1, -1};
981 }
982 }
983
984@@ -603,7 +613,8 @@
985 _is_primary = primary;
986 }
987
988-void PanelView::SyncGeometries()
989+void
990+PanelView::SyncGeometries()
991 {
992 indicator::EntryLocationMap locations;
993 _menu_view->GetGeometryForSync(locations);
994
995=== modified file 'plugins/unityshell/src/PanelView.h'
996--- plugins/unityshell/src/PanelView.h 2011-09-15 09:58:21 +0000
997+++ plugins/unityshell/src/PanelView.h 2011-09-25 12:09:24 +0000
998@@ -72,6 +72,8 @@
999 void EndFirstMenuShow();
1000
1001 void SetOpacity(float opacity);
1002+
1003+ void TrackMenuPointer();
1004
1005 unsigned int GetTrayXid ();
1006
1007@@ -120,6 +122,7 @@
1008 guint _handle_dash_shown;
1009 guint _handle_bg_color_update;
1010 guint _track_menu_pointer_id;
1011+ nux::Point _tracked_pointer_pos;
1012
1013 std::vector<sigc::connection> _on_indicator_updated_connections;
1014 BackgroundEffectHelper bg_effect_helper_;
1015
1016=== modified file 'plugins/unityshell/src/PluginAdapter.cpp'
1017--- plugins/unityshell/src/PluginAdapter.cpp 2011-09-21 03:40:33 +0000
1018+++ plugins/unityshell/src/PluginAdapter.cpp 2011-09-25 12:09:24 +0000
1019@@ -375,7 +375,36 @@
1020 bool
1021 PluginAdapter::IsWindowDecorated(guint32 xid)
1022 {
1023- Window win = (Window)xid;
1024+ Display* display = m_Screen->dpy();
1025+ Window win = xid;
1026+ Atom hints_atom = None;
1027+ MotifWmHints* hints = NULL;
1028+ Atom type = None;
1029+ gint format;
1030+ gulong nitems;
1031+ gulong bytes_after;
1032+ bool ret = true;
1033+
1034+ hints_atom = XInternAtom(display, _XA_MOTIF_WM_HINTS, false);
1035+
1036+ XGetWindowProperty(display, win, hints_atom, 0,
1037+ sizeof(MotifWmHints) / sizeof(long), False,
1038+ hints_atom, &type, &format, &nitems, &bytes_after,
1039+ (guchar**)&hints);
1040+
1041+ if (!hints)
1042+ return ret;
1043+
1044+ if (type == hints_atom && format != 0 && hints->flags & MWM_HINTS_DECORATIONS)
1045+ {
1046+ ret = hints->decorations & (MwmDecorAll | MwmDecorTitle);
1047+ }
1048+
1049+ XFree(hints);
1050+ return ret;
1051+
1052+/* FIXME compiz is too slow to update this value, and this could lead to
1053+ * issues like the bug #838923, since the read value isn't valid anymore
1054 CompWindow* window;
1055
1056 window = m_Screen->findWindow(win);
1057@@ -386,6 +415,7 @@
1058 return decor & (MwmDecorAll | MwmDecorTitle);
1059 }
1060 return true;
1061+*/
1062 }
1063
1064 bool
1065@@ -419,6 +449,8 @@
1066 {
1067 if (sibling->defaultViewport() == window_vp
1068 && !sibling->minimized()
1069+ && sibling->isMapped()
1070+ && sibling->isViewable()
1071 && (sibling->state() & MAXIMIZE_STATE) == MAXIMIZE_STATE)
1072 return true;
1073 }
1074
1075=== modified file 'plugins/unityshell/src/WindowButtons.cpp'
1076--- plugins/unityshell/src/WindowButtons.cpp 2011-09-06 18:30:26 +0000
1077+++ plugins/unityshell/src/WindowButtons.cpp 2011-09-25 12:09:24 +0000
1078@@ -55,6 +55,7 @@
1079 _prelight_dash_tex(NULL),
1080 _pressed_dash_tex(NULL),
1081 _dash_is_open(false),
1082+ _mouse_is_down(false),
1083 _place_shown_interest(0),
1084 _place_hidden_interest(0)
1085 {
1086@@ -69,6 +70,14 @@
1087 _place_hidden_interest = ubus_server_register_interest(ubus, UBUS_PLACE_VIEW_HIDDEN,
1088 (UBusCallback)&WindowButton::OnPlaceViewHidden,
1089 this);
1090+
1091+ /* FIXME HasMouseFocus() doesn't seem to work correctly, so we use this workaround */
1092+ mouse_down.connect([&_mouse_is_down](int, int, unsigned long, unsigned long) {
1093+ _mouse_is_down = true;
1094+ });
1095+ mouse_up.connect([&_mouse_is_down](int, int, unsigned long, unsigned long) {
1096+ _mouse_is_down = false;
1097+ });
1098 }
1099
1100 ~WindowButton()
1101@@ -98,7 +107,8 @@
1102
1103 if (_dash_is_open)
1104 {
1105- if (HasMouseFocus() && IsMouseInside())
1106+ //FIXME should use HasMouseFocus()
1107+ if (_mouse_is_down && IsMouseInside())
1108 tex = _pressed_dash_tex;
1109 else if (IsMouseInside())
1110 tex = _prelight_dash_tex;
1111@@ -107,7 +117,8 @@
1112 }
1113 else
1114 {
1115- if (HasMouseFocus() && IsMouseInside())
1116+ //FIXME should use HasMouseFocus()
1117+ if (_mouse_is_down && IsMouseInside())
1118 tex = _pressed_tex;
1119 else if (IsMouseInside())
1120 tex = _prelight_tex;
1121@@ -217,6 +228,7 @@
1122 nux::BaseTexture* _prelight_dash_tex;
1123 nux::BaseTexture* _pressed_dash_tex;
1124 bool _dash_is_open;
1125+ bool _mouse_is_down;
1126 guint32 _place_shown_interest;
1127 guint32 _place_hidden_interest;
1128
1129
1130=== modified file 'plugins/unityshell/src/WindowManager.cpp'
1131--- plugins/unityshell/src/WindowManager.cpp 2011-09-19 16:36:21 +0000
1132+++ plugins/unityshell/src/WindowManager.cpp 2011-09-25 12:09:24 +0000
1133@@ -1,3 +1,4 @@
1134+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1135 /*
1136 * Copyright (C) 2010 Canonical Ltd
1137 *
1138@@ -26,7 +27,7 @@
1139 {
1140 return 0;
1141 }
1142-
1143+
1144 bool IsScreenGrabbed()
1145 {
1146 return false;
1147@@ -181,6 +182,9 @@
1148 void
1149 WindowManager::StartMove(guint32 xid, int x, int y)
1150 {
1151+ if (x < 0 || y < 0)
1152+ return;
1153+
1154 XEvent ev;
1155 Display* d = nux::GetGraphicsDisplay()->GetX11Display();
1156
1157
1158=== modified file 'services/panel-service.c'
1159--- services/panel-service.c 2011-09-08 11:53:46 +0000
1160+++ services/panel-service.c 2011-09-25 12:09:24 +0000
1161@@ -16,6 +16,7 @@
1162 *
1163 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
1164 * Rodrigo Moya <rodrigo.moya@canonical.com>
1165+ * Marco Trevisan (Treviño) <mail@3v1n0.net>
1166 */
1167
1168 #if HAVE_CONFIG_H
1169@@ -47,8 +48,8 @@
1170 struct _PanelServicePrivate
1171 {
1172 GSList *indicators;
1173- GHashTable *id2entry_hash;
1174 GHashTable *entry2indicator_hash;
1175+ GHashTable *entry2geometry_hash;
1176
1177 guint initial_sync_id;
1178 gint32 timeouts[N_TIMEOUT_SLOTS];
1179@@ -64,6 +65,9 @@
1180 gint last_right;
1181 gint last_bottom;
1182 guint32 last_menu_button;
1183+
1184+ IndicatorObjectEntry *pressed_entry;
1185+ gboolean use_event;
1186 };
1187
1188 /* Globals */
1189@@ -113,6 +117,7 @@
1190 static void sort_indicators (PanelService *self);
1191
1192 static void notify_object (IndicatorObject *object);
1193+static IndicatorObjectEntry *get_entry_at (PanelService *self, gint x, gint y);
1194
1195 static GdkFilterReturn event_filter (GdkXEvent *ev,
1196 GdkEvent *gev,
1197@@ -128,8 +133,8 @@
1198 PanelServicePrivate *priv = PANEL_SERVICE (object)->priv;
1199 gint i;
1200
1201- g_hash_table_destroy (priv->id2entry_hash);
1202 g_hash_table_destroy (priv->entry2indicator_hash);
1203+ g_hash_table_destroy (priv->entry2geometry_hash);
1204
1205 gdk_window_remove_filter (NULL, (GdkFilterFunc)event_filter, object);
1206
1207@@ -239,25 +244,83 @@
1208 if (cookie->type == GenericEvent)
1209 {
1210 XIDeviceEvent *event = cookie->data;
1211-
1212- if (event && event->evtype == XI_ButtonRelease &&
1213- priv->last_menu_button != 0) //FocusChange
1214- {
1215- if (event->root_x < priv->last_left ||
1216- event->root_x > priv->last_right ||
1217- event->root_y < priv->last_top ||
1218- event->root_y > priv->last_bottom)
1219- {
1220- ret = GDK_FILTER_REMOVE;
1221- }
1222-
1223- priv->last_menu_button = 0;
1224+ if (!event)
1225+ return ret;
1226+
1227+ if (event->evtype == XI_ButtonPress)
1228+ {
1229+ priv->pressed_entry = get_entry_at (self, event->root_x, event->root_y);
1230+ priv->use_event = (priv->pressed_entry == NULL);
1231+ }
1232+
1233+ if (event->evtype == XI_ButtonRelease)
1234+ {
1235+ if (priv->use_event)
1236+ {
1237+ priv->use_event = FALSE;
1238+ }
1239+ else
1240+ {
1241+ IndicatorObjectEntry *entry;
1242+ entry = get_entry_at (self, event->root_x, event->root_y);
1243+
1244+ if (entry)
1245+ {
1246+ if (entry != priv->pressed_entry)
1247+ {
1248+ ret = GDK_FILTER_REMOVE;
1249+ priv->use_event = TRUE;
1250+ }
1251+ else if (priv->last_entry && entry != priv->last_entry)
1252+ {
1253+ /* If we were navigating over indicators using the keyboard
1254+ * and now we click over the indicator under the mouse, we
1255+ * must force it to show back again, not make it close */
1256+ gchar *entry_id = g_strdup_printf ("%p", entry);
1257+ g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id);
1258+ g_free (entry_id);
1259+ }
1260+ }
1261+ }
1262 }
1263 }
1264
1265 return ret;
1266 }
1267
1268+static IndicatorObjectEntry *
1269+get_entry_at (PanelService *self, gint x, gint y)
1270+{
1271+ GHashTableIter iter;
1272+ gpointer key, value;
1273+
1274+ g_hash_table_iter_init (&iter, self->priv->entry2geometry_hash);
1275+ while (g_hash_table_iter_next (&iter, &key, &value))
1276+ {
1277+ IndicatorObjectEntry *entry = key;
1278+ GdkRectangle *geo = value;
1279+
1280+ if (x >= geo->x && x <= (geo->x + geo->width) &&
1281+ y >= geo->y && y <= (geo->y + geo->height))
1282+ {
1283+ return entry;
1284+ }
1285+ }
1286+
1287+ return NULL;
1288+}
1289+
1290+static IndicatorObjectEntry *
1291+get_entry_by_id (const gchar *entry_id)
1292+{
1293+ IndicatorObjectEntry *entry;
1294+
1295+ if (sscanf (entry_id, "%p", &entry) == 1)
1296+ return entry;
1297+
1298+ return NULL;
1299+}
1300+
1301 static gboolean
1302 initial_resync (PanelService *self)
1303 {
1304@@ -277,9 +340,9 @@
1305
1306 gdk_window_add_filter (NULL, (GdkFilterFunc)event_filter, self);
1307
1308- priv->id2entry_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
1309- g_free, NULL);
1310 priv->entry2indicator_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
1311+ priv->entry2geometry_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
1312+ NULL, g_free);
1313
1314 suppress_signals = TRUE;
1315 load_indicators (self);
1316@@ -315,10 +378,8 @@
1317 {
1318 for (l = entries; l; l = l->next)
1319 {
1320- gchar *id = g_strdup_printf ("%p", l->data);
1321- g_hash_table_remove (self->priv->id2entry_hash, id);
1322 g_hash_table_remove (self->priv->entry2indicator_hash, l->data);
1323- g_free (id);
1324+ g_hash_table_remove (self->priv->entry2geometry_hash, l->data);
1325 }
1326
1327 g_list_free (entries);
1328@@ -520,14 +581,11 @@
1329 PanelService *self)
1330 {
1331 PanelServicePrivate *priv;
1332- gchar *id;
1333
1334 g_return_if_fail (PANEL_IS_SERVICE (self));
1335 g_return_if_fail (entry != NULL);
1336 priv = self->priv;
1337
1338- id = g_strdup_printf ("%p", entry);
1339- g_hash_table_insert (priv->id2entry_hash, id, entry);
1340 g_hash_table_insert (priv->entry2indicator_hash, entry, object);
1341
1342 if (GTK_IS_LABEL (entry->label))
1343@@ -576,17 +634,16 @@
1344 PanelService *self)
1345 {
1346 PanelServicePrivate *priv;
1347- gchar *id;
1348-
1349 g_return_if_fail (PANEL_IS_SERVICE (self));
1350 g_return_if_fail (entry != NULL);
1351
1352 priv = self->priv;
1353
1354- id = g_strdup_printf ("%p", entry);
1355 g_hash_table_remove (priv->entry2indicator_hash, entry);
1356- g_hash_table_remove (priv->id2entry_hash, id);
1357- g_free (id);
1358+ /* Don't remove here the value from priv->entry2geometry_hash, this should
1359+ * be done in during the sync, to avoid false positive.
1360+ * FIXME this in libappmenu.so to avoid to send an "entry-removed" signal
1361+ * when switching the focus from a window to one of its dialog children */
1362
1363 notify_object (object);
1364 }
1365@@ -628,7 +685,7 @@
1366 PanelService *self)
1367 {
1368 gchar *entry_id;
1369-
1370+
1371 g_return_if_fail (PANEL_IS_SERVICE (self));
1372 if (entry == NULL)
1373 {
1374@@ -637,7 +694,7 @@
1375 }
1376
1377 entry_id = g_strdup_printf ("%p", entry);
1378-
1379+
1380 g_signal_emit (self, _service_signals[ENTRY_SHOW_NOW_CHANGED], 0, entry_id, show_now_changed);
1381
1382 g_free (entry_id);
1383@@ -967,6 +1024,8 @@
1384 priv->last_top = 0;
1385 priv->last_bottom = 0;
1386
1387+ priv->pressed_entry = NULL;
1388+
1389 g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, "");
1390 }
1391
1392@@ -1045,9 +1104,32 @@
1393 gint height)
1394 {
1395 PanelServicePrivate *priv = self->priv;
1396- IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);
1397+ IndicatorObjectEntry *entry = get_entry_by_id (entry_id);
1398 IndicatorObject *object = g_hash_table_lookup (priv->entry2indicator_hash, entry);
1399
1400+ if (entry)
1401+ {
1402+ if (width < 0 || height < 0)
1403+ {
1404+ g_hash_table_remove (priv->entry2geometry_hash, entry);
1405+ }
1406+ else
1407+ {
1408+ GdkRectangle *geo = g_hash_table_lookup (priv->entry2geometry_hash, entry);
1409+
1410+ if (geo == NULL)
1411+ {
1412+ geo = g_new (GdkRectangle, 1);
1413+ g_hash_table_insert (priv->entry2geometry_hash, entry, geo);
1414+ }
1415+
1416+ geo->x = x;
1417+ geo->y = y;
1418+ geo->width = width;
1419+ geo->height = height;
1420+ }
1421+ }
1422+
1423 g_signal_emit (self, _service_signals[GEOMETRIES_CHANGED], 0, object, entry, x, y, width, height);
1424 }
1425
1426@@ -1176,8 +1258,7 @@
1427 priv = self->priv;
1428
1429 /* Not interested in up or down */
1430- if (direction == GTK_MENU_DIR_NEXT
1431- || direction == GTK_MENU_DIR_PREV)
1432+ if (direction == GTK_MENU_DIR_NEXT || direction == GTK_MENU_DIR_PREV)
1433 return;
1434
1435 /* We don't want to distrupt going into submenus */
1436@@ -1221,15 +1302,17 @@
1437 gint32 button)
1438 {
1439 PanelServicePrivate *priv = self->priv;
1440- IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);
1441+ IndicatorObjectEntry *entry = get_entry_by_id (entry_id);
1442 IndicatorObject *object = g_hash_table_lookup (priv->entry2indicator_hash, entry);
1443 GtkWidget *last_menu;
1444
1445+ g_return_if_fail (entry);
1446+
1447 if (priv->last_entry == entry)
1448 return;
1449
1450 last_menu = GTK_WIDGET (priv->last_menu);
1451-
1452+
1453 if (GTK_IS_MENU (priv->last_menu))
1454 {
1455 priv->last_x = 0;
1456@@ -1247,6 +1330,8 @@
1457
1458 if (entry != NULL)
1459 {
1460+ g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, entry_id);
1461+
1462 if (GTK_IS_MENU (entry->menu))
1463 {
1464 priv->last_menu = entry->menu;
1465@@ -1294,8 +1379,6 @@
1466 priv->last_top = 0;
1467 priv->last_bottom = 0;
1468 }
1469-
1470- g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, entry_id);
1471 }
1472
1473 /* We popdown the old one last so we don't accidently send key focus back to the
1474@@ -1312,7 +1395,9 @@
1475 guint32 timestamp)
1476 {
1477 PanelServicePrivate *priv = self->priv;
1478- IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);
1479+ IndicatorObjectEntry *entry = get_entry_by_id (entry_id);
1480+ g_return_if_fail (entry);
1481+
1482 IndicatorObject *object = g_hash_table_lookup (priv->entry2indicator_hash, entry);
1483
1484 g_signal_emit_by_name(object, INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, entry,
1485@@ -1325,11 +1410,12 @@
1486 gint32 delta)
1487 {
1488 PanelServicePrivate *priv = self->priv;
1489- IndicatorObjectEntry *entry = g_hash_table_lookup (priv->id2entry_hash, entry_id);
1490+ IndicatorObjectEntry *entry = get_entry_by_id (entry_id);
1491+ g_return_if_fail (entry);
1492+
1493 IndicatorObject *object = g_hash_table_lookup (priv->entry2indicator_hash, entry);
1494 GdkScrollDirection direction = delta < 0 ? GDK_SCROLL_DOWN : GDK_SCROLL_UP;
1495
1496 g_signal_emit_by_name(object, INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, entry,
1497 abs(delta/120), direction);
1498 }
1499-