source: eviacam/trunk/fuentes/wxutil/wxappbar.cpp @ 29

Last change on this file since 29 was 29, checked in by mabarracus, 4 years ago

added eviacam content

File size: 28.9 KB
Line 
1/////////////////////////////////////////////////////////////////////////////
2// Name:        wxappbar.cpp
3// Purpose: 
4// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
5// Modified by:
6// Created:     18/10/2008
7// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
8//
9//  This program is free software: you can redistribute it and/or modify
10//  it under the terms of the GNU General Public License as published by
11//  the Free Software Foundation, either version 3 of the License, or
12//  (at your option) any later version.
13//
14//  This program is distributed in the hope that it will be useful,
15//  but WITHOUT ANY WARRANTY; without even the implied warranty of
16//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17//  GNU General Public License for more details.
18//
19//  You should have received a copy of the GNU General Public License
20//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21/////////////////////////////////////////////////////////////////////////////
22
23// For compilers that support precompilation, includes "wx/wx.h".
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
27#pragma hdrstop
28#endif
29
30#include "wxappbar.h"
31#include "warnbaroverlap.h"
32#ifndef WX_PRECOMP
33#include "wx/wx.h"
34#endif
35
36#ifdef __WXMSW__
37//#include <shellapi.h>
38#endif
39
40// X11 includes
41#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
42#include <X11/Xlib.h>
43#include <X11/Xproto.h>
44#include <X11/Xutil.h>
45#include <X11/Xatom.h>
46
47#include <gdk/gdkx.h>
48#include <gtk/gtkwidget.h>
49#include <gtk/gtk.h>
50
51#endif
52
53#include <wx/timer.h>
54
55#define AUTOHIDE_FLANGE 10
56#define TIMER_ID 1234
57
58// X11 definitions and structs
59#define WIN_STATE_STICKY          (1<<0)        /* everyone knows sticky */
60#define WIN_STATE_MINIMIZED       (1<<1)        /* ??? */
61#define WIN_STATE_MAXIMIZED_VERT  (1<<2)        /* window in maximized V state */
62#define WIN_STATE_MAXIMIZED_HORIZ (1<<3)        /* window in maximized H state */
63#define WIN_STATE_HIDDEN          (1<<4)        /* not on taskbar but window visible */
64#define WIN_STATE_SHADED          (1<<5)        /* shaded (NeXT style) */
65#define WIN_STATE_HID_WORKSPACE   (1<<6)        /* not on current desktop */
66#define WIN_STATE_HID_TRANSIENT   (1<<7)        /* owner of transient is hidden */
67#define WIN_STATE_FIXED_POSITION  (1<<8)        /* window is fixed in position even */
68#define WIN_STATE_ARRANGE_IGNORE  (1<<9)        /* ignore for auto arranging */
69
70#define WIN_HINTS_SKIP_FOCUS      (1<<0)        /* "alt-tab" skips this win */
71#define WIN_HINTS_SKIP_WINLIST    (1<<1)        /* not in win list */
72#define WIN_HINTS_SKIP_TASKBAR    (1<<2)        /* not on taskbar */
73#define WIN_HINTS_GROUP_TRANSIENT (1<<3)        /* ??????? */
74#define WIN_HINTS_FOCUS_ON_CLICK  (1<<4)        /* app only accepts focus when clicked */
75#define WIN_HINTS_DO_NOT_COVER    (1<<5)        /* attempt to not cover this window */
76
77#define MWM_HINTS_DECORATIONS         (1L << 1)
78
79// Old KDE hints
80//_NET_WM_LAYER
81
82#define _NET_WIN_LAYER_DESKTOP                0
83#define _NET_WIN_LAYER_BELOW                  2
84#define _NET_WIN_LAYER_NORMAL                 4
85#define _NET_WIN_LAYER_ONTOP                  6
86#define _NET_WIN_LAYER_DOCK                   8
87#define _NET_WIN_LAYER_ABOVE_DOCK             10
88#define _NET_WIN_LAYER_MENU                   12
89
90// _NET_WM_HINTS
91// Additional hints for the window manager or tools like panels or taskbars. Possible values:
92
93#define _NET_WM_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
94#define _NET_WM_HINTS_SKIP_WINLIST (1<<1)  /* do not show in window list */
95#define _NET_WM_HINTS_SKIP_TASKBAR (1<<2) /* do not show on taskbar */
96#define _NET_WM_HINTS_NO_AUTO_FOCUS (1<<3) /* do not automatically put focus on this window when it pops up */
97#define _NET_WM_HINTS_STANDALONE_MENUBAR  (1<<4) /* this window is a standalone menubar */
98#define _NET_WM_HINTS_FIXED_POSITION  (1<<5) /* this window has a fixed position (should be excluded from desktop uncluttering etc.) */
99#define _NET_WM_HINTS_DO_NOT_COVER (1<<6) /* attempt to never cover up this window if possible (placement policy priority hint)*/
100
101#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
102#define _NET_WM_STATE_ADD           1    /* add/set property */
103#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */
104
105// Declare/define an event type for the appbar callback
106// used only under MSW
107BEGIN_DECLARE_EVENT_TYPES()
108        DECLARE_EVENT_TYPE(WX_APPBAR_CALLBACK, -1)
109END_DECLARE_EVENT_TYPES()
110
111DEFINE_EVENT_TYPE(WX_APPBAR_CALLBACK)
112
113
114/*!
115 * WXAppBar type definition
116 */
117
118IMPLEMENT_DYNAMIC_CLASS( WXAppBar, wxDialog )
119
120
121/*!
122 * WXAppBar event table definition
123 */
124
125BEGIN_EVENT_TABLE( WXAppBar, wxDialog )
126        EVT_SIZE( WXAppBar::OnSize )
127        EVT_MOVE( WXAppBar::OnMove )
128        EVT_ENTER_WINDOW( WXAppBar::OnEnterWindow )
129        EVT_LEAVE_WINDOW( WXAppBar::OnLeaveWindow )
130        EVT_TIMER( TIMER_ID, WXAppBar::OnTimer )
131END_EVENT_TABLE()
132
133/*
134typedef struct _mwmhints
135{
136        unsigned long flags;
137        unsigned long functions;
138        unsigned long decorations;
139        long inputMode;
140        unsigned long status;
141}
142MWMHints;
143*/
144#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
145static 
146bool IsMappedWindow(Display *dd, Window w)
147{
148        XWindowAttributes attr;
149
150        XGetWindowAttributes(dd, w, &attr);
151       
152        return (attr.map_state != IsUnmapped);
153}
154
155#if 0
156static
157void wxWMspecSetState(Display *dd, Window w, int operation, Atom state)
158{
159        Atom atom= XInternAtom (dd, "_NET_WM_STATE", False);
160        assert (atom!= BadAlloc);
161        assert (atom!= BadAtom);
162        assert (atom!= BadValue);
163       
164        int screen = DefaultScreen (dd);
165        Window rootWin= RootWindow (dd, screen);
166        XEvent xev;
167
168        assert(IsMappedWindow(dd, w));
169
170        xev.type = ClientMessage;
171        xev.xclient.type = ClientMessage;
172        xev.xclient.serial = 0;
173        xev.xclient.send_event = True;
174        xev.xclient.display = dd;
175        xev.xclient.window = w;
176        xev.xclient.message_type = atom;
177        xev.xclient.format = 32;
178        xev.xclient.data.l[0] = operation;
179        xev.xclient.data.l[1] = state;
180        xev.xclient.data.l[2] = None;
181       
182        XSendEvent(dd, rootWin, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
183}
184#endif
185#endif
186
187
188
189/*!
190 * WXAppBar constructors
191 */
192
193WXAppBar::WXAppBar() : m_timer(this, TIMER_ID)
194{
195        Init();
196}
197
198WXAppBar::WXAppBar( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) : m_timer(this, TIMER_ID)
199{
200        Init();
201        Create(parent, id, caption, pos, size, style); 
202}
203
204
205/*!
206 * WXAppBar creator
207 */
208
209bool WXAppBar::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
210{
211        bool retval= wxDialog::Create( parent, id, caption, pos, size, style );
212        // Sticky window by default
213        SetSticky(true);
214        return retval;
215}
216
217
218/*!
219 * WXAppBar destructor
220 */
221
222WXAppBar::~WXAppBar()
223{
224        delete m_pMouseControl;
225        delete m_pDialog;
226}
227
228
229/*!
230 * Member initialisation
231 */
232
233void WXAppBar::Init()
234{
235        m_X= 0;
236        m_Y= 0;
237        m_Width= -1;
238        m_Height= -1;
239        m_currentDockingMode= NON_DOCKED;
240        m_dialogHadBorderDecorations= GetBorderDecorations();
241        m_firstTime= true;
242        m_autohide=  false;
243        m_isAutohideWindowShown= false;
244        m_warnBarOverlap= true;
245        m_pDialog = new WarnBarOverlap(NULL);
246#if defined(__WXGTK__)
247        m_pMouseControl = new CMouseControl ((void *) wxGetDisplay());
248#else
249        m_pMouseControl= new CMouseControl ();
250#endif
251}
252
253
254// Allows to know and change whether the dialog has borders or not
255bool WXAppBar::GetBorderDecorations () const
256{
257        // Honours the wxNO_BORDER flag
258        return (GetWindowStyleFlag() & wxNO_BORDER? false : true);     
259}
260
261void WXAppBar::SetBorderDecorations (bool enable, bool apply)
262{
263        if (enable == GetBorderDecorations()) return;
264       
265        // Changes the flag
266        long style= GetWindowStyleFlag();
267        if (enable) {
268                // Enable decorations
269                style= style & ~wxNO_BORDER;
270//              style= style | wxCAPTION;
271        }
272        else {
273                // Disable decorations
274                style= style | wxNO_BORDER;
275//              style= style & ~wxCAPTION;
276        }
277        SetWindowStyleFlag(style);
278        // According to the manual, after changing flags a Refresh is needed
279        Refresh();
280
281#if defined(__WXMSW__)
282        // TODO
283        (void)(apply); // Remove warning
284        assert (false);
285#elif defined(__WXGTK__)
286        //
287        // On WXGTK the above code is not enough, so we change this property
288        // using gtk+ directly
289        //
290       
291        // Get X11 handle for our window
292        GtkWindow *gtkWindow= (GtkWindow *) GetHandle();
293        assert (gtkWindow);
294        if (!gtkWindow) return;
295
296        bool isShown= IsShown();
297        if (apply && isShown) wxDialog::Show(false);
298       
299        gtk_window_set_decorated ((GtkWindow *) GetHandle(), (enable? TRUE : FALSE));
300        if (apply && isShown) {
301                wxDialog::Show(true);
302                Refresh();
303                Update();
304        }
305#else
306        assert (false);
307#endif
308}
309
310void WXAppBar::SetSticky (bool stick)
311{
312#if defined(__WXMSW__)
313        // TODO
314        (void)(stick); // Remove warning
315        //assert (false);
316#elif defined(__WXGTK__)       
317        // Get X11 handle for our window
318        GtkWindow *gtkWindow= (GtkWindow *) GetHandle();
319        assert (gtkWindow);
320        if (!gtkWindow) return;
321
322        if (stick) 
323                gtk_window_stick (gtkWindow);
324        else 
325                gtk_window_unstick (gtkWindow); 
326#else
327        assert (false);
328#endif
329}
330
331void WXAppBar::SetEntryInTaskBar (bool v)
332{
333#if defined(__WXMSW__)
334        // TODO
335        (void)(v); // Remove warning
336        //assert (false);
337#elif defined(__WXGTK__)       
338        // Get X11 handle for our window
339        GtkWindow *gtkWindow= (GtkWindow *) GetHandle();
340        assert (gtkWindow);
341        if (!gtkWindow) return;
342
343        gtk_window_set_skip_taskbar_hint (gtkWindow, (v? FALSE : TRUE));
344#else
345        assert (false);
346#endif
347}
348       
349void WXAppBar::SetEntryInPager (bool v)
350{
351#if defined(__WXMSW__)
352        // TODO
353        (void)(v);      // Remove warning
354        //assert (false);
355#elif defined(__WXGTK__)       
356        // Get X11 handle for our window
357        GtkWindow *gtkWindow= (GtkWindow *) GetHandle();
358        assert (gtkWindow);
359        if (!gtkWindow) return;
360       
361        gtk_window_set_skip_pager_hint (gtkWindow, (v? FALSE : TRUE));
362#else
363        assert (false);
364#endif
365}
366
367void WXAppBar::SetAcceptFocus (bool accept)
368{
369#if defined(__WXMSW__)
370        // TODO
371        (void)(accept); // Remove warning
372        //assert (false);
373#elif defined(__WXGTK__)       
374        // Get X11 handle for our window
375        GtkWindow *gtkWindow= (GtkWindow *) GetHandle();
376        assert (gtkWindow);
377        if (!gtkWindow) return;
378       
379        gtk_window_set_accept_focus (gtkWindow, (accept? TRUE : FALSE));
380#else
381        assert (false);
382#endif
383}
384
385#if defined(__WXMSW__)
386//void WXAppBar::AppBarCallback (UINT uMsg, WPARAM wParam, LPARAM lParam)
387//{
388        /*
389    APPBARDATA abd;
390        static HWND hwndZOrder = NULL;
391        POPTIONS pOpt = GetAppbarData ();
392   
393    abd.cbSize = sizeof(abd);
394    abd.hWnd = m_hWnd;
395   
396    switch (wParam)
397    {
398        // Notifies the appbar that the taskbar's autohide or always-on-top
399        // state has changed.  The appbar can use this to conform to the settings
400        // of the system taskbar.
401            case ABN_STATECHANGE:
402                break;
403
404        // Notifies the appbar when a full screen application is opening or
405        // closing.  When a full screen app is opening, the appbar must drop
406        // to the bottom of the Z-Order.  When the app is closing, we should
407        // restore our Z-order position.
408            case ABN_FULLSCREENAPP:
409                if (lParam)
410                {
411                // A full screen app is opening.  Move us to the bottom of the
412                // Z-Order. 
413
414                                // First get the window that we're underneath so we can correctly
415                                // restore our position
416                                hwndZOrder = GetWindow (m_hWnd, GW_HWNDPREV);
417                               
418                                // Now move ourselves to the bottom of the Z-Order
419                    SetWindowPos(m_hWnd, HWND_BOTTOM, 0, 0, 0, 0,
420                                         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);           
421                }
422                else
423                {
424                // The app is closing.  Restore the Z-order                       
425                SetWindowPos(m_hWnd, pOpt->fOnTop ? HWND_TOPMOST : hwndZOrder,
426                                 0, 0, 0, 0,
427                                 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
428                               
429                                hwndZOrder = NULL;
430                }
431                        break;
432       
433        // Notifies the appbar when an event has occured that may effect the
434        // appbar's size and position.  These events include changes in the
435        // taskbar's size, position, and visiblity as well as adding, removing,
436        // or resizing another appbar on the same side of the screen.
437        case ABN_POSCHANGED:
438            // Update our position in response to the system change
439                PosChanged (&abd);
440                break;
441    }
442        */
443//}
444
445#endif
446
447
448void WXAppBar::OnSize( wxSizeEvent& event )
449{
450        // TODO: delete
451//      event.Skip(false);
452       
453#if defined(__WXMSW__)
454//      SetSize(m_X, m_Y, m_Width, m_Height, 0);
455//      Raise ();       
456#else
457        //wxSize s= event.GetSize();
458        //printf ("onSize: %d, %d, orig: %d, %d\n", s.GetWidth(), s.GetHeight(), m_Width, m_Height);
459        /*
460        if (s.GetWidth()!= m_Width || s.GetHeight()!= m_Height) {
461                SetSize (m_Width, m_Height);
462                event.Skip(false);
463        }
464        else
465                wxDialog::OnSize (event);
466        */
467#endif
468        wxDialog::OnSize (event);
469}
470
471void WXAppBar::OnMove( wxMoveEvent& event )
472{
473#if defined(__WXMSW__)
474        SetSize(m_X, m_Y, m_Width, m_Height, 0);
475        Raise ();
476#endif
477        //wxPoint p= event.GetPosition();
478       
479//      printf ("onMove: %d, %d, orig: %d, %d\n", p.x, p.y, m_X, m_Y);
480//      wxDialog::OnMove (event);
481        event.Skip();
482}
483
484bool WXAppBar::ProcessEvent(wxEvent& event)
485{
486        return wxDialog::ProcessEvent (event);
487}
488
489void WXAppBar::SetDockingMode (EDocking dockingMode)
490{
491        if (m_currentDockingMode== dockingMode) return;
492
493        // If is shown, hide
494        bool isShown= IsShown();
495
496        if (isShown) Show(false);
497
498        m_currentDockingMode= dockingMode;
499       
500        if (isShown) Show(true);
501}
502
503void WXAppBar::SetAutohideMode (bool autohide)
504{
505        if (m_autohide == autohide) return;
506
507        // TODO: check this
508       
509        // If is shown, hide
510        bool isShown= IsShown();
511        if (isShown) Show(false);
512       
513        m_autohide= autohide;
514
515        if (isShown) Show(true);
516}
517
518void WXAppBar::CheckCreateWindow()
519{
520#if defined(__WXGTK__)
521        //
522        // Show & update the window to make sure that is actually created the first time
523        //
524        if (m_firstTime) {
525                wxDialog::Show(true);
526                Refresh();
527                Update();
528               
529                wxDialog::Show(false);
530                Refresh();
531                Update();
532                m_firstTime= false;
533        }
534#endif
535        // TODO: check if it is needed for Windows
536}
537
538#if defined(__WXGTK__)
539static
540void GetDesktopDimensions (Display* d, int& x, int& y, int& width, int& height, int& screenWidth, int& screenHeight)
541{
542        // Try to get real work area to set metrics
543        Atom atomTmp = XInternAtom(d, "_NET_WORKAREA", False);
544        Atom actual_type;
545        int actual_format;
546        unsigned long nitems;
547        unsigned long bytes_after;
548        unsigned long *prop;
549        int screen = DefaultScreen (d);
550               
551        // Get desktop size
552        XGetWindowProperty (d, DefaultRootWindow(d), atomTmp, 0, 4, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, (unsigned char **) &prop);
553
554        screenWidth= DisplayWidth (d, screen);
555        screenHeight= DisplayHeight (d, screen);
556       
557        if (prop!= NULL) {
558                x= (int) prop[0];
559                y= (int) prop[1];
560                width= (int)prop[2];
561                height= (int)prop[3];
562                XFree (prop);
563        }
564        else {
565                // Fallback, just in case. Assert in debug mode
566                assert (false);
567               
568                x= 0;
569                y= 0;
570                width = screenWidth;
571                height = screenHeight;
572        }
573}
574
575// Reserves an area for the X11 window 'w' in one of the sides of the desktop depending
576// on the value of 'where'. If 'where== NON_DOCKED' or area== 0 then the area is freed.
577static
578void SetStrutArea (Window w, WXAppBar::EDocking where, int area)
579{
580        Display* dd= (Display *) wxGetDisplay();
581       
582        //
583        // Get desktop working area dimensions
584        //
585        int xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight;
586        GetDesktopDimensions (dd, xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight);
587       
588        //
589        // Reserves an area in the desktop.
590        //
591        // It seems that for older GNOME version (ex: 2.22.3 on Debian, using a partial strut
592        // doesn't work properly,  more TESTING NEEDED)
593        //
594        unsigned long strut[4] = {0, 0, 0, 0};
595        //unsigned long strut_p[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
596        /* left, right, top, bottom, left_start_y, left_end_y, right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x*/
597        if (area) {
598                switch (where) {
599                case WXAppBar::TOP_DOCKED:
600                        strut[2]=  area + yDesktop;
601                        //strut_p[2]= strut[2];
602                        break;
603                case WXAppBar::BOTTOM_DOCKED:   
604                        strut[3]= screenHeight - heightDesktop - yDesktop + area;
605                        //strut_p[3]= strut[3];
606                        break;
607                case WXAppBar::LEFT_DOCKED:
608                        strut[0]= area + xDesktop;
609                        //strut_p[0]= strut[0];
610                        break; 
611                case WXAppBar::RIGHT_DOCKED:
612                        strut[1]= screenWidth - widthDesktop - xDesktop + area;
613                        //strut_p[1]= strut[1];
614                        break;
615                case WXAppBar::NON_DOCKED:
616                        break;
617                default:
618                        assert (false);
619                }
620        }
621       
622        //atomTmp = XInternAtom (dd, "_NET_WM_STRUT_PARTIAL", False);   
623        //XChangeProperty (dd, w, atomTmp, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &strut_p, 12);
624       
625        Atom atomTmp = XInternAtom (dd, "_NET_WM_STRUT", False);
626        XChangeProperty (dd, w, atomTmp, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &strut, 4);
627        XSync(dd, False);
628       
629        // If window mapped, then wait until strut applied
630        // TODO: is there a better way to do this?     
631        if (IsMappedWindow(dd, w)) {
632                int new_xDesktop, new_yDesktop, new_widthDesktop, new_heightDesktop, count= 0;
633                for (;;) {
634                        GetDesktopDimensions (dd, new_xDesktop, new_yDesktop, new_widthDesktop, 
635                                new_heightDesktop, screenWidth, screenHeight);
636                        ++count;
637                        if (!(count< 20 && new_xDesktop== xDesktop && new_yDesktop== yDesktop &&
638                        new_widthDesktop== widthDesktop && new_heightDesktop == heightDesktop)) break;
639                        usleep (100000);
640                }
641        }       
642}
643
644
645
646void WXAppBar::SetDockedModeStep1()
647{
648        //CheckCreateWindow();
649
650        //
651        // Get X11 display
652        //
653        Display* dd= (Display *) wxGetDisplay(); assert (dd);
654       
655        //
656        // Get desktop working area dimensions
657        //
658        int xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight;
659        GetDesktopDimensions (dd, xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight);
660       
661        //
662        // As we need to dock the window disable decorations
663        //
664        m_dialogHadBorderDecorations= GetBorderDecorations();
665        SetBorderDecorations(false);
666       
667        //
668        // Get X11 handle for our window
669        //
670        GtkWidget *gtkWidget= (GtkWidget *) this->GetHandle();
671        Window w= GDK_WINDOW_XWINDOW (gtkWidget->window);
672       
673        // Get original dimensions of the bar
674        wxSize proposedSize= GetBestSize();
675
676        // Compute bar position and size depending on docking mode
677        switch (m_currentDockingMode) {
678        case TOP_DOCKED:
679                m_X= xDesktop;
680                m_Y= yDesktop;
681                m_Width= widthDesktop;
682                m_Height= proposedSize.GetHeight();
683                break;
684        case BOTTOM_DOCKED:
685                m_X= xDesktop;
686                m_Y= yDesktop + heightDesktop - proposedSize.GetHeight();
687                m_Width= widthDesktop;
688                m_Height= proposedSize.GetHeight();
689                break;
690        case LEFT_DOCKED:
691                m_X= xDesktop;
692                m_Y= yDesktop;
693                m_Width= proposedSize.GetWidth();
694                m_Height= heightDesktop;
695                break; 
696        case RIGHT_DOCKED:
697                m_X= xDesktop + widthDesktop - proposedSize.GetWidth();
698                m_Y= yDesktop;
699                m_Width= proposedSize.GetWidth();
700                m_Height= heightDesktop;
701                break;
702        case NON_DOCKED:
703        default:
704                assert (false);
705        }
706       
707        //
708        // Reserves an area in the desktop.
709        //
710        switch (m_currentDockingMode) {
711        case TOP_DOCKED:        SetStrutArea (w, TOP_DOCKED, m_Height); break;
712        case BOTTOM_DOCKED:     SetStrutArea (w, BOTTOM_DOCKED, m_Height); break;
713        case LEFT_DOCKED:       SetStrutArea (w, LEFT_DOCKED, m_Width); break; 
714        case RIGHT_DOCKED:      SetStrutArea (w, RIGHT_DOCKED, m_Width); break;
715        case NON_DOCKED:
716        default:
717                assert (false);
718        }
719
720        //
721        // Functional type of the window (_NET_WM_WINDOW_TYPE)
722        //
723        Atom atomTmp= XInternAtom (dd, "_NET_WM_WINDOW_TYPE", False);
724        Atom atom_NET_WM_WINDOW_TYPE_DOCK= XInternAtom (dd, "_NET_WM_WINDOW_TYPE_DOCK", False);
725        Atom atom_NET_WM_WINDOW_TYPE_NORMAL= XInternAtom (dd, "_NET_WM_WINDOW_TYPE_NORMAL", False);
726        unsigned long propInfo[2];
727        propInfo[0]= atom_NET_WM_WINDOW_TYPE_DOCK;
728        propInfo[1]= atom_NET_WM_WINDOW_TYPE_NORMAL;           
729        XChangeProperty (dd, w, atomTmp, XA_ATOM, 32, PropModeReplace, (unsigned char *) &propInfo[0], 2);
730        SetSticky(true);
731        XSync(dd, False);
732
733        // Set desired location and dimensions
734        SetSize(m_X, m_Y, m_Width, m_Height);
735}
736
737void WXAppBar::SetDockedModeStep2()
738{
739        // Do nothing
740}
741
742void WXAppBar::UnSetDockedModeStep1()
743{
744        // Disable all special features
745        //Display *dd= (Display *) wxGetDisplay();
746
747        // Window X11 handle
748        GtkWidget *gtkWidget= (GtkWidget *) this->GetHandle();
749        Window w= GDK_WINDOW_XWINDOW (gtkWidget->window);
750       
751        // Disables struts
752        SetStrutArea (w, NON_DOCKED, 0);
753}
754
755void WXAppBar::UnSetDockedModeStep2()
756{
757        Display *dd= (Display *) wxGetDisplay();
758
759        // Window X11 handle
760        GtkWidget *gtkWidget= (GtkWidget *) this->GetHandle();
761        Window w= GDK_WINDOW_XWINDOW (gtkWidget->window);
762       
763        Refresh();
764        Update();
765       
766        //
767        // Set window style back to normal again
768        //
769        Atom atomTmp= XInternAtom (dd, "_NET_WM_WINDOW_TYPE", False);
770        Atom atom_NET_WM_WINDOW_TYPE_NORMAL= XInternAtom (dd, "_NET_WM_WINDOW_TYPE_NORMAL", False);
771        unsigned long propInfo= atom_NET_WM_WINDOW_TYPE_NORMAL;
772        XChangeProperty (dd, w, atomTmp, XA_ATOM, 32, PropModeReplace, (unsigned char *) &propInfo, 1);
773        XSync(dd, False);
774       
775        // The code above disables the sticky property, so we enable it again
776        SetSticky(true);
777       
778        // Restore decorations when needed
779        SetBorderDecorations(m_dialogHadBorderDecorations);
780       
781        // Restore original size
782        wxSize proposedSize= DoGetBestSize();
783        //SetSize (0, 0, proposedSize.GetWidth(), proposedSize.GetHeight());
784        SetSize (proposedSize.GetWidth(), proposedSize.GetHeight());
785}
786
787void WXAppBar::SetAutohideModeStep ()
788{
789        //CheckCreateWindow();
790
791        //
792        // Get X11 display
793        //
794        Display* dd= (Display *) wxGetDisplay(); assert (dd);
795       
796        //
797        // Get desktop working area dimensions
798        //
799        int xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight;
800        GetDesktopDimensions (dd, xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight);
801       
802        //
803        // As we need to dock the window disable decorations
804        //
805        m_dialogHadBorderDecorations= GetBorderDecorations();
806        SetBorderDecorations(false);
807       
808        //
809        // Get X11 handle for our window
810        //
811        GtkWidget *gtkWidget= (GtkWidget *) this->GetHandle();
812        Window w= GDK_WINDOW_XWINDOW (gtkWidget->window);
813       
814        // Get original dimensions of the bar
815        wxSize proposedSize= GetBestSize();
816
817        // Compute bar position and size depending on docking mode
818        m_Width= proposedSize.GetWidth();
819        m_Height= proposedSize.GetHeight();
820       
821        switch (m_currentDockingMode) {
822                case TOP_DOCKED:
823                        m_X= (screenWidth - proposedSize.GetWidth())/2;
824                        m_Y= 0 - proposedSize.GetHeight() + AUTOHIDE_FLANGE;
825                        break;
826                case BOTTOM_DOCKED:
827                        m_X= (screenWidth - proposedSize.GetWidth())/2;
828                        m_Y= screenHeight - AUTOHIDE_FLANGE;
829                        break;
830                case LEFT_DOCKED:
831                        m_X= 0 - proposedSize.GetWidth() + AUTOHIDE_FLANGE;
832                        m_Y= (screenHeight - proposedSize.GetHeight())/2;
833                        break; 
834                case RIGHT_DOCKED:
835                        m_X= screenWidth - AUTOHIDE_FLANGE;
836                        m_Y= (screenHeight - proposedSize.GetHeight())/2;
837                        break;
838                case NON_DOCKED:
839                default:
840                        assert (false);
841        }
842       
843       
844        //
845        // Functional type of the window (_NET_WM_WINDOW_TYPE)
846        //
847        Atom atomTmp= XInternAtom (dd, "_NET_WM_WINDOW_TYPE", False);
848        Atom atom_NET_WM_WINDOW_TYPE_DOCK= XInternAtom (dd, "_NET_WM_WINDOW_TYPE_DOCK", False);
849        Atom atom_NET_WM_WINDOW_TYPE_NORMAL= XInternAtom (dd, "_NET_WM_WINDOW_TYPE_NORMAL", False);
850        unsigned long propInfo[2];
851        propInfo[0]= atom_NET_WM_WINDOW_TYPE_DOCK;
852        propInfo[1]= atom_NET_WM_WINDOW_TYPE_NORMAL;           
853        XChangeProperty (dd, w, atomTmp, XA_ATOM, 32, PropModeReplace, (unsigned char *) &propInfo[0], 2);
854        SetSticky(true);
855        XSync(dd, False);
856
857        // Set desired location and dimensions
858        SetSize(m_X, m_Y, m_Width, m_Height);   
859}
860
861
862#elif defined(__WXMSW__)
863
864void WXAppBar::SetDockedModeStep1()
865{
866        // TODO: manage different docking locations on windows
867        APPBARDATA abd;         
868
869        // Set metrics (TOP location only)
870        wxSize proposedSize= DoGetBestSize();
871        m_X= 0;
872        m_Y= 0;
873        m_Width= GetSystemMetrics(SM_CXSCREEN);
874        m_Height= proposedSize.GetHeight();     
875
876        // Register appbar
877        abd.cbSize= sizeof(APPBARDATA);
878        abd.hWnd= (HWND) GetHandle();
879        abd.uCallbackMessage= 12345; //WX_APPBAR_CALLBACK; // TODO: respond to these callback messages
880        SHAppBarMessage (ABM_NEW, &abd);
881
882        // Set size
883        abd.uEdge= ABE_TOP;
884        abd.rc.left = m_X;
885        abd.rc.top = m_Y;
886        abd.rc.right = m_X + m_Width;
887        abd.rc.bottom = m_Y + m_Height;
888
889        SHAppBarMessage(ABM_QUERYPOS,&abd);     // Correct size if needed
890
891        m_X= abd.rc.left;
892        m_Y= abd.rc.top;               
893        m_Width= abd.rc.right - m_X;
894        // Re-calculate bottom corner
895        abd.rc.bottom = m_Y + m_Height;         
896        SHAppBarMessage(ABM_SETPOS, &abd);
897}
898
899void WXAppBar::SetDockedModeStep2()
900{
901        SetSize(m_X, m_Y, m_Width, m_Height, 0);
902        Raise();
903}
904
905void WXAppBar::UnSetDockedModeStep1()
906{
907        // Do nothing
908}
909
910void WXAppBar::UnSetDockedModeStep2()
911{
912        // Unregister app bar
913        APPBARDATA abd; 
914        abd.cbSize= sizeof(APPBARDATA);
915        abd.hWnd= (HWND) GetHandle();   
916        SHAppBarMessage (ABM_REMOVE, &abd);
917}
918
919void WXAppBar::SetAutohideModeStep ()
920{
921        //TODO
922}
923#endif
924
925bool WXAppBar::Show (bool show)
926{
927        if (show== IsShown ()) return false;
928       
929        // If no docking enabled, simply forward the call
930        if (m_currentDockingMode == NON_DOCKED) {
931                m_firstTime= false;
932                return wxDialog::Show (show);
933        }
934        else {
935                CheckCreateWindow();
936               
937                // "Docking mode" enabled
938                if (!m_autohide) {
939                        // Normal docking
940                        if (show) {
941                                SetDockedModeStep1();
942                                wxDialog::Show(true);
943                                SetDockedModeStep2();
944                        }
945                        else {
946                                UnSetDockedModeStep1();
947                                wxDialog::Show(false);
948                                UnSetDockedModeStep2();
949                        }
950                }
951                else {
952                        if (show) {
953                                if (CheckForBar() && m_warnBarOverlap)
954                                        SetWarnBarOverlap(!(m_pDialog->ShowModal() ? true : false));
955                                SetAutohideModeStep();
956                                wxDialog::Show(true);
957                        }
958                        else {
959                                UnSetDockedModeStep1();
960                                wxDialog::Show(false);
961                                UnSetDockedModeStep2();
962                        }
963                }
964        }
965       
966        return true;
967}
968
969
970void WXAppBar::OnEnterWindow( wxMouseEvent& event )
971{
972#if defined(__WXGTK__)
973        if (m_autohide && m_currentDockingMode != NON_DOCKED && !m_isAutohideWindowShown)
974        {
975                // Get X11 display
976                Display* dd= (Display *) wxGetDisplay(); assert (dd);
977               
978                // Get desktop working area dimensions
979                int xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight;
980                GetDesktopDimensions (dd, xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight);
981
982                // Get original dimensions of the bar
983                wxSize proposedSize= GetBestSize();
984
985                // Compute bar position and size depending on docking mode
986                m_Width= proposedSize.GetWidth();
987                m_Height= proposedSize.GetHeight();
988       
989                switch (m_currentDockingMode) {
990                        case TOP_DOCKED:
991                                m_X= (screenWidth - proposedSize.GetWidth())/2;
992                                m_Y= 0;
993                                break;
994                        case BOTTOM_DOCKED:
995                                m_X= (screenWidth - proposedSize.GetWidth())/2;
996                                m_Y= screenHeight - proposedSize.GetHeight();
997                                break;
998                        case LEFT_DOCKED:
999                                m_X= 0;
1000                                m_Y= (screenHeight - proposedSize.GetHeight())/2;
1001                                break; 
1002                        case RIGHT_DOCKED:
1003                                m_X= screenWidth - proposedSize.GetWidth();
1004                                m_Y= (screenHeight - proposedSize.GetHeight())/2;
1005                                break;
1006                        case NON_DOCKED:
1007                        default:
1008                                assert (false);
1009                }
1010               
1011                // Set desired location and dimensions
1012                SetSize(m_X, m_Y, m_Width, m_Height);
1013               
1014                m_isAutohideWindowShown= true;
1015        }
1016#endif
1017        event.Skip(true);
1018}
1019
1020void WXAppBar::OnLeaveWindow( wxMouseEvent& event )
1021{
1022#if defined(__WXGTK__)
1023        int x, y;
1024       
1025        m_pMouseControl->GetPointerLocation (x, y);
1026        wxRect barRect = GetRect();
1027       
1028        if (m_autohide && m_currentDockingMode != NON_DOCKED && m_isAutohideWindowShown && !barRect.Contains(x,y))
1029        {
1030                m_timer.Start(1000);
1031        }
1032#endif
1033        event.Skip(true);
1034}
1035
1036void WXAppBar::OnTimer(wxTimerEvent& event)
1037{
1038#if defined(__WXGTK__)
1039        int x, y;
1040       
1041        m_pMouseControl->GetPointerLocation (x, y);
1042        wxRect barRect = GetRect();
1043       
1044        if (m_autohide && m_currentDockingMode != NON_DOCKED && m_isAutohideWindowShown && !barRect.Contains(x,y))
1045        {
1046                // Get X11 display
1047                Display* dd= (Display *) wxGetDisplay(); assert (dd);
1048               
1049                // Get desktop working area dimensions
1050                int xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight;
1051                GetDesktopDimensions (dd, xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight);
1052
1053                // Get original dimensions of the bar
1054                wxSize proposedSize= GetBestSize();
1055
1056                // Compute bar position and size depending on docking mode
1057                m_Width= proposedSize.GetWidth();
1058                m_Height= proposedSize.GetHeight();
1059       
1060                switch (m_currentDockingMode) {
1061                        case TOP_DOCKED:
1062                                m_X= (screenWidth - proposedSize.GetWidth())/2;
1063                                m_Y= 0 - proposedSize.GetHeight() + AUTOHIDE_FLANGE;
1064                                break;
1065                        case BOTTOM_DOCKED:
1066                                m_X= (screenWidth - proposedSize.GetWidth())/2;
1067                                m_Y= screenHeight - AUTOHIDE_FLANGE;
1068                                break;
1069                        case LEFT_DOCKED:
1070                                m_X= 0 - proposedSize.GetWidth() + AUTOHIDE_FLANGE;
1071                                m_Y= (screenHeight - proposedSize.GetHeight())/2;
1072                                break; 
1073                        case RIGHT_DOCKED:
1074                                m_X= screenWidth - AUTOHIDE_FLANGE;
1075                                m_Y= (screenHeight - proposedSize.GetHeight())/2;
1076                                break;
1077                        case NON_DOCKED:
1078                        default:
1079                                assert (false);
1080                }
1081               
1082                // Set desired location and dimensions
1083                SetSize(m_X, m_Y, m_Width, m_Height);
1084               
1085                m_isAutohideWindowShown= false;
1086        }
1087#endif
1088        event.Skip(false);
1089}
1090
1091void WXAppBar::SetWarnBarOverlap(bool value)
1092{
1093        m_warnBarOverlap= value;
1094}
1095
1096bool WXAppBar::CheckForBar()
1097{
1098#if defined(__WXGTK__)
1099        // Get X11 display
1100        Display* dd= (Display *) wxGetDisplay(); assert (dd);
1101               
1102        // Get desktop working area dimensions
1103        int xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight;
1104        GetDesktopDimensions (dd, xDesktop, yDesktop, widthDesktop, heightDesktop, screenWidth, screenHeight);
1105       
1106        switch (m_currentDockingMode)
1107        {
1108                case TOP_DOCKED:
1109                        return (yDesktop > 0);
1110                        break;
1111                       
1112                case BOTTOM_DOCKED:
1113                        return ((screenHeight - yDesktop - heightDesktop) > 0);
1114                        break;
1115                       
1116                case LEFT_DOCKED:
1117                        return (xDesktop > 0);
1118                        break;
1119                       
1120                case RIGHT_DOCKED:
1121                        return ((screenWidth - xDesktop - widthDesktop) > 0);
1122                        break;
1123                       
1124                case NON_DOCKED:
1125                default:
1126                        return false;
1127                        break;
1128        }
1129#endif
1130        return false;
1131}
Note: See TracBrowser for help on using the repository browser.