LCOV - code coverage report
Current view: top level - vcl/unx/gtk/window - gtksalframe.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 2078 0.0 %
Date: 2014-11-03 Functions: 0 138 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <unx/gtk/gtkframe.hxx>
      21             : #include <unx/gtk/gtkdata.hxx>
      22             : #include <unx/gtk/gtkinst.hxx>
      23             : #include <unx/gtk/gtkgdi.hxx>
      24             : #include <vcl/help.hxx>
      25             : #include <vcl/keycodes.hxx>
      26             : #include <vcl/layout.hxx>
      27             : #include <unx/wmadaptor.hxx>
      28             : #include <unx/sm.hxx>
      29             : #include <unx/salbmp.h>
      30             : #include <generic/genprn.h>
      31             : #include <generic/geninst.h>
      32             : #include <headless/svpgdi.hxx>
      33             : #include <osl/file.hxx>
      34             : #include <rtl/bootstrap.hxx>
      35             : #include <rtl/process.h>
      36             : #include <vcl/floatwin.hxx>
      37             : #include <vcl/svapp.hxx>
      38             : #include <vcl/window.hxx>
      39             : #include <vcl/settings.hxx>
      40             : 
      41             : #if !GTK_CHECK_VERSION(3,0,0)
      42             : #  include <unx/x11/xlimits.hxx>
      43             : #endif
      44             : #if defined(ENABLE_DBUS) && defined(ENABLE_GIO)
      45             : #  include <unx/gtk/gtksalmenu.hxx>
      46             : #endif
      47             : #if defined ENABLE_GMENU_INTEGRATION // defined in gtksalmenu.hxx above
      48             : #  include <unx/gtk/hudawareness.h>
      49             : #endif
      50             : 
      51             : #include <gtk/gtk.h>
      52             : #include <prex.h>
      53             : #include <X11/Xatom.h>
      54             : #include <gdk/gdkx.h>
      55             : #include <postx.h>
      56             : 
      57             : #include <dlfcn.h>
      58             : #include <vcl/salbtype.hxx>
      59             : #include <vcl/bitmapex.hxx>
      60             : #include <impbmp.hxx>
      61             : #include <svids.hrc>
      62             : #include <sal/macros.h>
      63             : 
      64             : #include <basegfx/range/b2ibox.hxx>
      65             : #include <basegfx/vector/b2ivector.hxx>
      66             : 
      67             : #include <algorithm>
      68             : #include <glib/gprintf.h>
      69             : 
      70             : #if OSL_DEBUG_LEVEL > 1
      71             : #  include <cstdio>
      72             : #endif
      73             : 
      74             : #include <comphelper/processfactory.hxx>
      75             : #include <comphelper/sequenceashashmap.hxx>
      76             : #include <com/sun/star/accessibility/XAccessibleContext.hpp>
      77             : #include <com/sun/star/accessibility/AccessibleRole.hpp>
      78             : #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
      79             : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
      80             : #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
      81             : #include <com/sun/star/frame/Desktop.hpp>
      82             : #include <com/sun/star/frame/ModuleManager.hpp>
      83             : #include <com/sun/star/frame/XFrame.hpp>
      84             : #include <com/sun/star/util/URLTransformer.hpp>
      85             : 
      86             : #if GTK_CHECK_VERSION(3,0,0)
      87             : #  include <gdk/gdkkeysyms-compat.h>
      88             : #endif
      89             : 
      90             : #ifdef ENABLE_DBUS
      91             : #include <dbus/dbus-glib.h>
      92             : 
      93             : #define GSM_DBUS_SERVICE        "org.gnome.SessionManager"
      94             : #define GSM_DBUS_PATH           "/org/gnome/SessionManager"
      95             : #define GSM_DBUS_INTERFACE      "org.gnome.SessionManager"
      96             : #endif
      97             : 
      98             : #include <config_folders.h>
      99             : 
     100             : // make compile on gtk older than 2.10
     101             : #if GTK_MINOR_VERSION < 10
     102             : #define GDK_SUPER_MASK      (1 << 26)
     103             : #define GDK_HYPER_MASK      (1 << 27)
     104             : #define GDK_META_MASK       (1 << 28)
     105             : #endif
     106             : 
     107             : #if GTK_CHECK_VERSION(3,0,0)
     108             : #define IS_WIDGET_REALIZED gtk_widget_get_realized
     109             : #define IS_WIDGET_MAPPED   gtk_widget_get_mapped
     110             : #else
     111             : #define IS_WIDGET_REALIZED GTK_WIDGET_REALIZED
     112             : #define IS_WIDGET_MAPPED   GTK_WIDGET_MAPPED
     113             : #endif
     114             : 
     115             : using namespace com::sun::star;
     116             : 
     117             : int GtkSalFrame::m_nFloats = 0;
     118             : 
     119             : #if defined ENABLE_GMENU_INTEGRATION
     120             : static GDBusConnection* pSessionBus = NULL;
     121             : #endif
     122             : 
     123           0 : static sal_uInt16 GetKeyModCode( guint state )
     124             : {
     125           0 :     sal_uInt16 nCode = 0;
     126           0 :     if( (state & GDK_SHIFT_MASK) )
     127           0 :         nCode |= KEY_SHIFT;
     128           0 :     if( (state & GDK_CONTROL_MASK) )
     129           0 :         nCode |= KEY_MOD1;
     130           0 :     if( (state & GDK_MOD1_MASK) )
     131           0 :         nCode |= KEY_MOD2;
     132             : 
     133             :     // Map Meta/Super keys to MOD3 modifier on all Unix systems
     134             :     // except Mac OS X
     135           0 :     if ( (state & GDK_META_MASK ) || ( state & GDK_SUPER_MASK ) )
     136           0 :         nCode |= KEY_MOD3;
     137           0 :     return nCode;
     138             : }
     139             : 
     140           0 : static sal_uInt16 GetMouseModCode( guint state )
     141             : {
     142           0 :     sal_uInt16 nCode = GetKeyModCode( state );
     143           0 :     if( (state & GDK_BUTTON1_MASK) )
     144           0 :         nCode |= MOUSE_LEFT;
     145           0 :     if( (state & GDK_BUTTON2_MASK) )
     146           0 :         nCode |= MOUSE_MIDDLE;
     147           0 :     if( (state & GDK_BUTTON3_MASK) )
     148           0 :         nCode |= MOUSE_RIGHT;
     149             : 
     150           0 :     return nCode;
     151             : }
     152             : 
     153           0 : static sal_uInt16 GetKeyCode( guint keyval )
     154             : {
     155           0 :     sal_uInt16 nCode = 0;
     156           0 :     if( keyval >= GDK_0 && keyval <= GDK_9 )
     157           0 :         nCode = KEY_0 + (keyval-GDK_0);
     158           0 :     else if( keyval >= GDK_KP_0 && keyval <= GDK_KP_9 )
     159           0 :         nCode = KEY_0 + (keyval-GDK_KP_0);
     160           0 :     else if( keyval >= GDK_A && keyval <= GDK_Z )
     161           0 :         nCode = KEY_A + (keyval-GDK_A );
     162           0 :     else if( keyval >= GDK_a && keyval <= GDK_z )
     163           0 :         nCode = KEY_A + (keyval-GDK_a );
     164           0 :     else if( keyval >= GDK_F1 && keyval <= GDK_F26 )
     165             :     {
     166             : #if !GTK_CHECK_VERSION(3,0,0)
     167           0 :         if( GetGtkSalData()->GetGtkDisplay()->IsNumLockFromXS() )
     168             :         {
     169           0 :             nCode = KEY_F1 + (keyval-GDK_F1);
     170             :         }
     171             :         else
     172             : #endif
     173             :         {
     174           0 :             switch( keyval )
     175             :             {
     176             :                 // - - - - - Sun keyboard, see vcl/unx/source/app/saldisp.cxx
     177             :                 case GDK_L2:
     178             : #if !GTK_CHECK_VERSION(3,0,0)
     179           0 :                     if( GetGtkSalData()->GetGtkDisplay()->GetServerVendor() == vendor_sun )
     180           0 :                         nCode = KEY_REPEAT;
     181             :                     else
     182             : #endif
     183           0 :                         nCode = KEY_F12;
     184           0 :                     break;
     185           0 :                 case GDK_L3:            nCode = KEY_PROPERTIES; break;
     186           0 :                 case GDK_L4:            nCode = KEY_UNDO;       break;
     187           0 :                 case GDK_L6:            nCode = KEY_COPY;       break; // KEY_F16
     188           0 :                 case GDK_L8:            nCode = KEY_PASTE;      break; // KEY_F18
     189           0 :                 case GDK_L10:           nCode = KEY_CUT;        break; // KEY_F20
     190             :                 default:
     191           0 :                     nCode = KEY_F1 + (keyval-GDK_F1);           break;
     192             :             }
     193             :         }
     194             :     }
     195             :     else
     196             :     {
     197           0 :         switch( keyval )
     198             :         {
     199             :             case GDK_KP_Down:
     200           0 :             case GDK_Down:          nCode = KEY_DOWN;       break;
     201             :             case GDK_KP_Up:
     202           0 :             case GDK_Up:            nCode = KEY_UP;         break;
     203             :             case GDK_KP_Left:
     204           0 :             case GDK_Left:          nCode = KEY_LEFT;       break;
     205             :             case GDK_KP_Right:
     206           0 :             case GDK_Right:         nCode = KEY_RIGHT;      break;
     207             :             case GDK_KP_Begin:
     208             :             case GDK_KP_Home:
     209             :             case GDK_Begin:
     210           0 :             case GDK_Home:          nCode = KEY_HOME;       break;
     211             :             case GDK_KP_End:
     212           0 :             case GDK_End:           nCode = KEY_END;        break;
     213             :             case GDK_KP_Page_Up:
     214           0 :             case GDK_Page_Up:       nCode = KEY_PAGEUP;     break;
     215             :             case GDK_KP_Page_Down:
     216           0 :             case GDK_Page_Down:     nCode = KEY_PAGEDOWN;   break;
     217             :             case GDK_KP_Enter:
     218           0 :             case GDK_Return:        nCode = KEY_RETURN;     break;
     219           0 :             case GDK_Escape:        nCode = KEY_ESCAPE;     break;
     220             :             case GDK_ISO_Left_Tab:
     221             :             case GDK_KP_Tab:
     222           0 :             case GDK_Tab:           nCode = KEY_TAB;        break;
     223           0 :             case GDK_BackSpace:     nCode = KEY_BACKSPACE;  break;
     224             :             case GDK_KP_Space:
     225           0 :             case GDK_space:         nCode = KEY_SPACE;      break;
     226             :             case GDK_KP_Insert:
     227           0 :             case GDK_Insert:        nCode = KEY_INSERT;     break;
     228             :             case GDK_KP_Delete:
     229           0 :             case GDK_Delete:        nCode = KEY_DELETE;     break;
     230             :             case GDK_plus:
     231           0 :             case GDK_KP_Add:        nCode = KEY_ADD;        break;
     232             :             case GDK_minus:
     233           0 :             case GDK_KP_Subtract:   nCode = KEY_SUBTRACT;   break;
     234             :             case GDK_asterisk:
     235           0 :             case GDK_KP_Multiply:   nCode = KEY_MULTIPLY;   break;
     236             :             case GDK_slash:
     237           0 :             case GDK_KP_Divide:     nCode = KEY_DIVIDE;     break;
     238           0 :             case GDK_period:        nCode = KEY_POINT;      break;
     239           0 :             case GDK_decimalpoint:  nCode = KEY_POINT;      break;
     240           0 :             case GDK_comma:         nCode = KEY_COMMA;      break;
     241           0 :             case GDK_less:          nCode = KEY_LESS;       break;
     242           0 :             case GDK_greater:       nCode = KEY_GREATER;    break;
     243             :             case GDK_KP_Equal:
     244           0 :             case GDK_equal:         nCode = KEY_EQUAL;      break;
     245           0 :             case GDK_Find:          nCode = KEY_FIND;       break;
     246           0 :             case GDK_Menu:          nCode = KEY_CONTEXTMENU;break;
     247           0 :             case GDK_Help:          nCode = KEY_HELP;       break;
     248           0 :             case GDK_Undo:          nCode = KEY_UNDO;       break;
     249           0 :             case GDK_Redo:          nCode = KEY_REPEAT;     break;
     250             :             case GDK_KP_Decimal:
     251           0 :             case GDK_KP_Separator:  nCode = KEY_DECIMAL;    break;
     252           0 :             case GDK_asciitilde:    nCode = KEY_TILDE;      break;
     253             :             case GDK_leftsinglequotemark:
     254           0 :             case GDK_quoteleft: nCode = KEY_QUOTELEFT;      break;
     255           0 :             case GDK_bracketleft:  nCode = KEY_BRACKETLEFT;  break;
     256           0 :             case GDK_bracketright: nCode = KEY_BRACKETRIGHT; break;
     257           0 :             case GDK_semicolon:    nCode = KEY_SEMICOLON;   break;
     258           0 :             case GDK_quoteright:   nCode = KEY_QUOTERIGHT;  break;
     259             :             // some special cases, also see saldisp.cxx
     260             :             // - - - - - - - - - - - - -  Apollo - - - - - - - - - - - - - 0x1000
     261             :             case 0x1000FF02: // apXK_Copy
     262           0 :                 nCode = KEY_COPY;
     263           0 :                 break;
     264             :             case 0x1000FF03: // apXK_Cut
     265           0 :                 nCode = KEY_CUT;
     266           0 :                 break;
     267             :             case 0x1000FF04: // apXK_Paste
     268           0 :                 nCode = KEY_PASTE;
     269           0 :                 break;
     270             :             case 0x1000FF14: // apXK_Repeat
     271           0 :                 nCode = KEY_REPEAT;
     272           0 :                 break;
     273             :             // Exit, Save
     274             :             // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
     275             :             case 0x1000FF00:
     276           0 :                 nCode = KEY_DELETE;
     277           0 :                 break;
     278             :             // - - - - - - - - - - - - - -  H P  - - - - - - - - - - - - - 0x1000
     279             :             case 0x1000FF73: // hpXK_DeleteChar
     280           0 :                 nCode = KEY_DELETE;
     281           0 :                 break;
     282             :             case 0x1000FF74: // hpXK_BackTab
     283             :             case 0x1000FF75: // hpXK_KP_BackTab
     284           0 :                 nCode = KEY_TAB;
     285           0 :                 break;
     286             :             // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
     287             :             // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
     288             :             case 0x1004FF02: // osfXK_Copy
     289           0 :                 nCode = KEY_COPY;
     290           0 :                 break;
     291             :             case 0x1004FF03: // osfXK_Cut
     292           0 :                 nCode = KEY_CUT;
     293           0 :                 break;
     294             :             case 0x1004FF04: // osfXK_Paste
     295           0 :                 nCode = KEY_PASTE;
     296           0 :                 break;
     297             :             case 0x1004FF07: // osfXK_BackTab
     298           0 :                 nCode = KEY_TAB;
     299           0 :                 break;
     300             :             case 0x1004FF08: // osfXK_BackSpace
     301           0 :                 nCode = KEY_BACKSPACE;
     302           0 :                 break;
     303             :             case 0x1004FF1B: // osfXK_Escape
     304           0 :                 nCode = KEY_ESCAPE;
     305           0 :                 break;
     306             :             // Up, Down, Left, Right, PageUp, PageDown
     307             :             // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
     308             :             // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
     309             :             // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
     310             :             // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
     311             :             case 0x1005FF10: // SunXK_F36
     312           0 :                 nCode = KEY_F11;
     313           0 :                 break;
     314             :             case 0x1005FF11: // SunXK_F37
     315           0 :                 nCode = KEY_F12;
     316           0 :                 break;
     317             :             case 0x1005FF70: // SunXK_Props
     318           0 :                 nCode = KEY_PROPERTIES;
     319           0 :                 break;
     320             :             case 0x1005FF71: // SunXK_Front
     321           0 :                 nCode = KEY_FRONT;
     322           0 :                 break;
     323             :             case 0x1005FF72: // SunXK_Copy
     324           0 :                 nCode = KEY_COPY;
     325           0 :                 break;
     326             :             case 0x1005FF73: // SunXK_Open
     327           0 :                 nCode = KEY_OPEN;
     328           0 :                 break;
     329             :             case 0x1005FF74: // SunXK_Paste
     330           0 :                 nCode = KEY_PASTE;
     331           0 :                 break;
     332             :             case 0x1005FF75: // SunXK_Cut
     333           0 :                 nCode = KEY_CUT;
     334           0 :                 break;
     335             :         }
     336             :     }
     337             : 
     338           0 :     return nCode;
     339             : }
     340             : 
     341           0 : static guint GetKeyValFor(GdkKeymap* pKeyMap, guint16 hardware_keycode, guint8 group)
     342             : {
     343           0 :     guint updated_keyval = 0;
     344             :     gdk_keymap_translate_keyboard_state(pKeyMap, hardware_keycode,
     345           0 :         (GdkModifierType)0, group, &updated_keyval, NULL, NULL, NULL);
     346           0 :     return updated_keyval;
     347             : }
     348             : 
     349             : // F10 means either KEY_F10 or KEY_MENU, which has to be decided
     350             : // in the independent part.
     351             : struct KeyAlternate
     352             : {
     353             :     sal_uInt16          nKeyCode;
     354             :     sal_Unicode     nCharCode;
     355           0 :     KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
     356           0 :     KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
     357             : };
     358             : 
     359             : inline KeyAlternate
     360           0 : GetAlternateKeyCode( const sal_uInt16 nKeyCode )
     361             : {
     362           0 :     KeyAlternate aAlternate;
     363             : 
     364           0 :     switch( nKeyCode )
     365             :     {
     366           0 :         case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break;
     367           0 :         case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break;
     368             :     }
     369             : 
     370           0 :     return aAlternate;
     371             : }
     372             : 
     373             : #if GTK_CHECK_VERSION(3,0,0)
     374             : static int debugQueuePureRedraw = 0;
     375             : static bool debugRedboxRedraws = false;
     376             : 
     377             : namespace {
     378             : /// Decouple SalFrame lifetime from damagetracker lifetime
     379             : struct DamageTracker : public basebmp::IBitmapDeviceDamageTracker
     380             : {
     381             :     DamageTracker(GtkSalFrame& rFrame) : m_rFrame(rFrame)
     382             :     {}
     383             : 
     384             :     virtual ~DamageTracker() {}
     385             : 
     386             :     virtual void damaged(const basegfx::B2IBox& rDamageRect) const SAL_OVERRIDE
     387             :     {
     388             :         m_rFrame.damaged(rDamageRect);
     389             :     }
     390             : 
     391             :     GtkSalFrame& m_rFrame;
     392             : };
     393             : }
     394             : #endif
     395             : 
     396           0 : void GtkSalFrame::doKeyCallback( guint state,
     397             :                                  guint keyval,
     398             :                                  guint16 hardware_keycode,
     399             :                                  guint8 group,
     400             :                                  guint32 time,
     401             :                                  sal_Unicode aOrigCode,
     402             :                                  bool bDown,
     403             :                                  bool bSendRelease
     404             :                                  )
     405             : {
     406             :     SalKeyEvent aEvent;
     407             : 
     408           0 :     aEvent.mnTime           = time;
     409           0 :     aEvent.mnCharCode       = aOrigCode;
     410           0 :     aEvent.mnRepeat         = 0;
     411             : 
     412           0 :     vcl::DeletionListener aDel( this );
     413             : 
     414             : #if GTK_CHECK_VERSION(3,0,0)
     415             :     // shift-zero forces a re-draw and event is swallowed
     416             :     if (keyval == GDK_0)
     417             :     {
     418             :         debugQueuePureRedraw += 2;
     419             :         fprintf( stderr, "force re-draw %d\n", debugQueuePureRedraw );
     420             :         gtk_widget_queue_draw (m_pWindow);
     421             :         return;
     422             :     }
     423             :     if (keyval == GDK_9)
     424             :     {
     425             :         debugRedboxRedraws = !debugRedboxRedraws;
     426             :         fprintf( stderr, "set redboxing to %d\n", debugRedboxRedraws );
     427             :         return;
     428             :     }
     429             : #endif
     430             : 
     431             :     /*
     432             :      *  #i42122# translate all keys with Ctrl and/or Alt to group 0 else
     433             :      *  shortcuts (e.g. Ctrl-o) will not work but be inserted by the
     434             :      *  application
     435             :      *
     436             :      *  #i52338# do this for all keys that the independent part has no key code
     437             :      *  for
     438             :      *
     439             :      *  fdo#41169 rather than use group 0, detect if there is a group which can
     440             :      *  be used to input Latin text and use that if possible
     441             :      */
     442           0 :     aEvent.mnCode = GetKeyCode( keyval );
     443           0 :     if( aEvent.mnCode == 0 )
     444             :     {
     445           0 :         gint best_group = SAL_MAX_INT32;
     446             : 
     447             :         // Try and find Latin layout
     448           0 :         GdkKeymap* keymap = gdk_keymap_get_default();
     449             :         GdkKeymapKey *keys;
     450             :         gint n_keys;
     451           0 :         if (gdk_keymap_get_entries_for_keyval(keymap, GDK_A, &keys, &n_keys))
     452             :         {
     453             :             // Find the lowest group that supports Latin layout
     454           0 :             for (gint i = 0; i < n_keys; ++i)
     455             :             {
     456           0 :                 if (keys[i].level != 0 && keys[i].level != 1)
     457           0 :                     continue;
     458           0 :                 best_group = std::min(best_group, keys[i].group);
     459           0 :                 if (best_group == 0)
     460           0 :                     break;
     461             :             }
     462           0 :             g_free(keys);
     463             :         }
     464             : 
     465             :         //Unavailable, go with original group then I suppose
     466           0 :         if (best_group == SAL_MAX_INT32)
     467           0 :             best_group = group;
     468             : 
     469           0 :         guint updated_keyval = GetKeyValFor(keymap, hardware_keycode, best_group);
     470           0 :         aEvent.mnCode = GetKeyCode(updated_keyval);
     471             :     }
     472             : 
     473           0 :     aEvent.mnCode   |= GetKeyModCode( state );
     474             : 
     475           0 :     if( bDown )
     476             :     {
     477           0 :         bool bHandled = CallCallback( SALEVENT_KEYINPUT, &aEvent );
     478             :         // #i46889# copy AlternatKeyCode handling from generic plugin
     479           0 :         if( ! bHandled )
     480             :         {
     481           0 :             KeyAlternate aAlternate = GetAlternateKeyCode( aEvent.mnCode );
     482           0 :             if( aAlternate.nKeyCode )
     483             :             {
     484           0 :                 aEvent.mnCode = aAlternate.nKeyCode;
     485           0 :                 if( aAlternate.nCharCode )
     486           0 :                     aEvent.mnCharCode = aAlternate.nCharCode;
     487           0 :                 bHandled = CallCallback( SALEVENT_KEYINPUT, &aEvent );
     488             :             }
     489             :         }
     490           0 :         if( bSendRelease && ! aDel.isDeleted() )
     491             :         {
     492           0 :             CallCallback( SALEVENT_KEYUP, &aEvent );
     493             :         }
     494             :     }
     495             :     else
     496           0 :         CallCallback( SALEVENT_KEYUP, &aEvent );
     497           0 : }
     498             : 
     499           0 : GtkSalFrame::GraphicsHolder::~GraphicsHolder()
     500             : {
     501           0 :     delete pGraphics;
     502           0 : }
     503             : 
     504           0 : GtkSalFrame::GtkSalFrame( SalFrame* pParent, sal_uLong nStyle )
     505           0 :     : m_nXScreen( getDisplay()->GetDefaultXScreen() )
     506             : {
     507           0 :     getDisplay()->registerFrame( this );
     508           0 :     m_nDuringRender     = 0;
     509           0 :     m_bDefaultPos       = true;
     510           0 :     m_bDefaultSize      = ( (nStyle & SAL_FRAME_STYLE_SIZEABLE) && ! pParent );
     511           0 :     m_bWindowIsGtkPlug  = false;
     512             : #if defined(ENABLE_DBUS) && defined(ENABLE_GIO)
     513           0 :     m_pLastSyncedDbusMenu = NULL;
     514             : #endif
     515           0 :     Init( pParent, nStyle );
     516           0 : }
     517             : 
     518           0 : GtkSalFrame::GtkSalFrame( SystemParentData* pSysData )
     519           0 :     : m_nXScreen( getDisplay()->GetDefaultXScreen() )
     520             : {
     521           0 :     getDisplay()->registerFrame( this );
     522             :     // permanently ignore errors from our unruly children ...
     523           0 :     GetGenericData()->ErrorTrapPush();
     524           0 :     m_bDefaultPos       = true;
     525           0 :     m_bDefaultSize      = true;
     526             : #if defined(ENABLE_DBUS) && defined(ENABLE_GIO)
     527           0 :     m_pLastSyncedDbusMenu = NULL;
     528             : #endif
     529           0 :     Init( pSysData );
     530           0 : }
     531             : 
     532             : #ifdef ENABLE_GMENU_INTEGRATION
     533             : 
     534             : static void
     535           0 : gdk_x11_window_set_utf8_property  (GdkWindow *window,
     536             :                                    const gchar *name,
     537             :                                    const gchar *value)
     538             : {
     539             : #if !GTK_CHECK_VERSION(3,0,0)
     540           0 :   GdkDisplay* display = gdk_window_get_display (window);
     541             : 
     542           0 :   if (value != NULL)
     543             :     {
     544             :       XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
     545             :                        GDK_WINDOW_XID (window),
     546             :                        gdk_x11_get_xatom_by_name_for_display (display, name),
     547             :                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
     548           0 :                        PropModeReplace, (guchar *)value, strlen (value));
     549             :     }
     550             :   else
     551             :     {
     552             :       XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
     553             :                        GDK_WINDOW_XID (window),
     554           0 :                        gdk_x11_get_xatom_by_name_for_display (display, name));
     555             :     }
     556             : #endif
     557           0 : }
     558             : 
     559             : // AppMenu watch functions.
     560             : 
     561           0 : static void ObjectDestroyedNotify( gpointer data )
     562             : {
     563           0 :     if ( data ) {
     564           0 :         g_object_unref( data );
     565             :     }
     566           0 : }
     567             : 
     568             : #if defined(ENABLE_DBUS) && defined(ENABLE_GIO)
     569           0 : void GtkSalFrame::EnsureDbusMenuSynced()
     570             : {
     571           0 :     GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*>(GetMenu());
     572           0 :     if(m_pLastSyncedDbusMenu != pSalMenu) {
     573           0 :         m_pLastSyncedDbusMenu = pSalMenu;
     574           0 :         static_cast<GtkSalMenu*>(pSalMenu)->Activate();
     575             :     }
     576           0 : }
     577             : #endif
     578             : 
     579           0 : static void hud_activated( gboolean hud_active, gpointer user_data )
     580             : {
     581           0 :     if ( hud_active )
     582             :     {
     583           0 :         SolarMutexGuard aGuard;
     584           0 :         GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( user_data );
     585           0 :         GtkSalMenu* pSalMenu = reinterpret_cast< GtkSalMenu* >( pSalFrame->GetMenu() );
     586             : 
     587           0 :         if ( pSalMenu )
     588           0 :             pSalMenu->UpdateFull();
     589             :     }
     590           0 : }
     591             : 
     592           0 : static void activate_uno(GSimpleAction *action, GVariant*, gpointer)
     593             : {
     594           0 :     uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
     595             : 
     596           0 :     uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( xContext );
     597             : 
     598           0 :     uno::Reference < css::frame::XFrame > xFrame(xDesktop->getActiveFrame());
     599           0 :     if (!xFrame.is())
     600           0 :         xFrame = uno::Reference < css::frame::XFrame >(xDesktop, uno::UNO_QUERY);
     601             : 
     602           0 :     if (!xFrame.is())
     603           0 :         return;
     604             : 
     605           0 :     uno::Reference< css::frame::XDispatchProvider > xDispatchProvider(xFrame, uno::UNO_QUERY);
     606           0 :     if (!xDispatchProvider.is())
     607           0 :         return;
     608             : 
     609           0 :     gchar *strval = NULL;
     610           0 :     g_object_get(action, "name", &strval, NULL);
     611           0 :     if (!strval)
     612           0 :         return;
     613             : 
     614           0 :     if (strcmp(strval, "New") == 0)
     615             :     {
     616           0 :         uno::Reference<frame::XModuleManager2> xModuleManager(frame::ModuleManager::create(xContext));
     617           0 :         OUString aModuleId(xModuleManager->identify(xFrame));
     618           0 :         if (aModuleId.isEmpty())
     619           0 :             return;
     620             : 
     621           0 :         comphelper::SequenceAsHashMap lModuleDescription(xModuleManager->getByName(aModuleId));
     622           0 :         OUString sFactoryService;
     623           0 :         lModuleDescription[OUString("ooSetupFactoryEmptyDocumentURL")] >>= sFactoryService;
     624           0 :         if (sFactoryService.isEmpty())
     625           0 :             return;
     626             : 
     627           0 :         uno::Sequence < css::beans::PropertyValue > args(0);
     628           0 :         xDesktop->loadComponentFromURL(sFactoryService, OUString("_blank"), 0, args);
     629           0 :         return;
     630             :     }
     631             : 
     632           0 :     OUString sCommand(".uno:");
     633           0 :     sCommand += OUString(strval, strlen(strval), RTL_TEXTENCODING_UTF8);
     634           0 :     g_free(strval);
     635             : 
     636           0 :     css::util::URL aCommand;
     637           0 :     aCommand.Complete = sCommand;
     638           0 :     uno::Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create(xContext);
     639           0 :     xParser->parseStrict(aCommand);
     640             : 
     641           0 :     uno::Reference< css::frame::XDispatch > xDisp = xDispatchProvider->queryDispatch(aCommand, OUString(), 0);
     642             : 
     643           0 :     if (!xDisp.is())
     644           0 :         return;
     645             : 
     646           0 :     xDisp->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());
     647             : }
     648             : 
     649             : static const GActionEntry app_entries[] = {
     650             :   { "OptionsTreeDialog", activate_uno, NULL, NULL, NULL, {0} },
     651             :   { "About", activate_uno, NULL, NULL, NULL, {0} },
     652             :   { "HelpIndex", activate_uno, NULL, NULL, NULL, {0} },
     653             :   { "Quit", activate_uno, NULL, NULL, NULL, {0} },
     654             :   { "New", activate_uno, NULL, NULL, NULL, {0} }
     655             : };
     656             : 
     657           0 : gboolean ensure_dbus_setup( gpointer data )
     658             : {
     659           0 :     GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( data );
     660           0 :     GdkWindow* gdkWindow = widget_get_window( pSalFrame->getWindow() );
     661             : 
     662           0 :     if ( gdkWindow != NULL && g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) == NULL )
     663             :     {
     664             :         // Get a DBus session connection.
     665           0 :         if(!pSessionBus)
     666           0 :             pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
     667           0 :         if( !pSessionBus )
     668           0 :             return FALSE;
     669             : 
     670             :         // Create menu model and action group attached to this frame.
     671           0 :         GMenuModel* pMenuModel = G_MENU_MODEL( g_lo_menu_new() );
     672           0 :         GActionGroup* pActionGroup = ( ( GActionGroup* ) g_lo_action_group_new( reinterpret_cast< gpointer >( pSalFrame ) ) );
     673             : 
     674             :         // Generate menu paths.
     675           0 :         ::Window windowId = GDK_WINDOW_XID( gdkWindow );
     676           0 :         gchar* aDBusWindowPath = g_strdup_printf( "/org/libreoffice/window/%lu", windowId );
     677           0 :         gchar* aDBusMenubarPath = g_strdup_printf( "/org/libreoffice/window/%lu/menus/menubar", windowId );
     678             : 
     679             :         // Set window properties.
     680           0 :         g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-menubar", pMenuModel, ObjectDestroyedNotify );
     681           0 :         g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-action-group", pActionGroup, ObjectDestroyedNotify );
     682             : 
     683           0 :         gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_APPLICATION_ID", "org.libreoffice" );
     684           0 :         gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_UNIQUE_BUS_NAME", g_dbus_connection_get_unique_name( pSessionBus ) );
     685           0 :         gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_APPLICATION_OBJECT_PATH", "/org/libreoffice" );
     686           0 :         gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_WINDOW_OBJECT_PATH", aDBusWindowPath );
     687           0 :         gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_MENUBAR_OBJECT_PATH", aDBusMenubarPath );
     688             : 
     689             :         // Publish the menu model and the action group.
     690             :         SAL_INFO("vcl.unity", "exporting menu model at " << pMenuModel << " for window " << windowId);
     691           0 :         pSalFrame->m_nMenuExportId = g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, pMenuModel, NULL);
     692             :         SAL_INFO("vcl.unity", "exporting action group at " << pActionGroup << " for window " << windowId);
     693           0 :         pSalFrame->m_nActionGroupExportId = g_dbus_connection_export_action_group( pSessionBus, aDBusWindowPath, pActionGroup, NULL);
     694           0 :         pSalFrame->m_nHudAwarenessId = hud_awareness_register( pSessionBus, aDBusMenubarPath, hud_activated, pSalFrame, NULL, NULL );
     695             : 
     696             :         // fdo#70885 we don't want app menu under Unity
     697           0 :         bool bDesktopIsUnity = (SalGetDesktopEnvironment() == "UNITY");
     698             : 
     699           0 :         if (!bDesktopIsUnity)
     700           0 :             gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_APP_MENU_OBJECT_PATH", "/org/libreoffice/menus/appmenu" );
     701             : 
     702             :         //app menu, to-do translations, block normal menus when active, honor use appmenu settings
     703           0 :         ResMgr* pMgr = ImplGetResMgr();
     704           0 :         if( pMgr && !bDesktopIsUnity )
     705             :         {
     706           0 :             GMenu *menu = g_menu_new ();
     707             :             GMenuItem* item;
     708             : 
     709           0 :             GMenu *firstsubmenu = g_menu_new ();
     710             : 
     711             :             OString sNew(OUStringToOString(ResId(SV_BUTTONTEXT_NEW, *pMgr).toString(),
     712           0 :                 RTL_TEXTENCODING_UTF8).replaceFirst("~", "_"));
     713             : 
     714           0 :             item = g_menu_item_new(sNew.getStr(), "app.New");
     715           0 :             g_menu_append_item( firstsubmenu, item );
     716           0 :             g_object_unref(item);
     717             : 
     718           0 :             g_menu_append_section( menu, NULL, G_MENU_MODEL(firstsubmenu));
     719           0 :             g_object_unref(firstsubmenu);
     720             : 
     721           0 :             GMenu *secondsubmenu = g_menu_new ();
     722             : 
     723             :             OString sPreferences(OUStringToOString(ResId(SV_STDTEXT_PREFERENCES, *pMgr).toString(),
     724           0 :                 RTL_TEXTENCODING_UTF8).replaceFirst("~", "_"));
     725             : 
     726           0 :             item = g_menu_item_new(sPreferences.getStr(), "app.OptionsTreeDialog");
     727           0 :             g_menu_append_item( secondsubmenu, item );
     728           0 :             g_object_unref(item);
     729             : 
     730           0 :             g_menu_append_section( menu, NULL, G_MENU_MODEL(secondsubmenu));
     731           0 :             g_object_unref(secondsubmenu);
     732             : 
     733           0 :             GMenu *thirdsubmenu = g_menu_new ();
     734             : 
     735             :             OString sHelp(OUStringToOString(ResId(SV_BUTTONTEXT_HELP, *pMgr).toString(),
     736           0 :                 RTL_TEXTENCODING_UTF8).replaceFirst("~", "_"));
     737             : 
     738           0 :             item = g_menu_item_new(sHelp.getStr(), "app.HelpIndex");
     739           0 :             g_menu_append_item( thirdsubmenu, item );
     740           0 :             g_object_unref(item);
     741             : 
     742             :             OString sAbout(OUStringToOString(ResId(SV_STDTEXT_ABOUT, *pMgr).toString(),
     743           0 :                 RTL_TEXTENCODING_UTF8).replaceFirst("~", "_"));
     744             : 
     745           0 :             item = g_menu_item_new(sAbout.getStr(), "app.About");
     746           0 :             g_menu_append_item( thirdsubmenu, item );
     747           0 :             g_object_unref(item);
     748             : 
     749             :             OString sQuit(OUStringToOString(ResId(SV_MENU_MAC_QUITAPP, *pMgr).toString(),
     750           0 :                 RTL_TEXTENCODING_UTF8).replaceFirst("~", "_"));
     751             : 
     752           0 :             item = g_menu_item_new(sQuit.getStr(), "app.Quit");
     753           0 :             g_menu_append_item( thirdsubmenu, item );
     754           0 :             g_object_unref(item);
     755           0 :             g_menu_append_section( menu, NULL, G_MENU_MODEL(thirdsubmenu));
     756           0 :             g_object_unref(thirdsubmenu);
     757             : 
     758           0 :             GSimpleActionGroup *group = g_simple_action_group_new ();
     759             : #if GLIB_CHECK_VERSION(2,38,0) // g_simple_action_group_add_entries is deprecated since 2.38
     760           0 :             g_action_map_add_action_entries (G_ACTION_MAP (group), app_entries, G_N_ELEMENTS (app_entries), NULL);
     761             : #else
     762             :             g_simple_action_group_add_entries (group, app_entries, G_N_ELEMENTS (app_entries), NULL);
     763             : #endif
     764           0 :             GActionGroup* pAppActionGroup = G_ACTION_GROUP(group);
     765             : 
     766           0 :             pSalFrame->m_nAppActionGroupExportId = g_dbus_connection_export_action_group( pSessionBus, "/org/libreoffice", pAppActionGroup, NULL);
     767           0 :             g_object_unref(pAppActionGroup);
     768           0 :             pSalFrame->m_nAppMenuExportId = g_dbus_connection_export_menu_model (pSessionBus, "/org/libreoffice/menus/appmenu", G_MENU_MODEL (menu), NULL);
     769           0 :             g_object_unref(menu);
     770             :         }
     771             : 
     772           0 :         g_free( aDBusMenubarPath );
     773           0 :         g_free( aDBusWindowPath );
     774             :     }
     775             : 
     776           0 :     return FALSE;
     777             : }
     778             : 
     779           0 : void on_registrar_available( GDBusConnection * /*connection*/,
     780             :                              const gchar     * /*name*/,
     781             :                              const gchar     * /*name_owner*/,
     782             :                              gpointer         user_data )
     783             : {
     784           0 :     SolarMutexGuard aGuard;
     785             : 
     786           0 :     GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( user_data );
     787             : 
     788           0 :     SalMenu* pSalMenu = pSalFrame->GetMenu();
     789             : 
     790           0 :     if ( pSalMenu != NULL )
     791             :     {
     792           0 :         GtkSalMenu* pGtkSalMenu = static_cast<GtkSalMenu*>(pSalMenu);
     793           0 :         pGtkSalMenu->Display( true );
     794           0 :         pGtkSalMenu->UpdateFull();
     795           0 :     }
     796           0 : }
     797             : 
     798             : // This is called when the registrar becomes unavailable. It shows the menubar.
     799           0 : void on_registrar_unavailable( GDBusConnection * /*connection*/,
     800             :                                const gchar     * /*name*/,
     801             :                                gpointer         user_data )
     802             : {
     803           0 :     SolarMutexGuard aGuard;
     804             : 
     805             :     SAL_INFO("vcl.unity", "on_registrar_unavailable");
     806             : 
     807             :     //pSessionBus = NULL;
     808           0 :     GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( user_data );
     809             : 
     810           0 :     SalMenu* pSalMenu = pSalFrame->GetMenu();
     811             : 
     812           0 :     if ( pSalMenu ) {
     813           0 :         GtkSalMenu* pGtkSalMenu = static_cast< GtkSalMenu* >( pSalMenu );
     814           0 :         pGtkSalMenu->Display( false );
     815           0 :     }
     816           0 : }
     817             : #endif
     818             : 
     819           0 : void GtkSalFrame::EnsureAppMenuWatch()
     820             : {
     821             : #ifdef ENABLE_GMENU_INTEGRATION
     822           0 :     if ( !m_nWatcherId )
     823             :     {
     824             :         // Get a DBus session connection.
     825           0 :         if ( pSessionBus == NULL )
     826             :         {
     827           0 :             pSessionBus = g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, NULL );
     828             : 
     829           0 :             if ( pSessionBus == NULL )
     830           0 :                 return;
     831             :         }
     832             : 
     833             :         // Publish the menu only if AppMenu registrar is available.
     834             :         m_nWatcherId = g_bus_watch_name_on_connection( pSessionBus,
     835             :                                                        "com.canonical.AppMenu.Registrar",
     836             :                                                        G_BUS_NAME_WATCHER_FLAGS_NONE,
     837             :                                                        on_registrar_available,
     838             :                                                        on_registrar_unavailable,
     839             :                                                        static_cast<GtkSalFrame*>(this),
     840           0 :                                                        NULL );
     841             :     }
     842             : 
     843             :     //ensure_dbus_setup( this );
     844             : #endif
     845             : }
     846             : 
     847           0 : GtkSalFrame::~GtkSalFrame()
     848             : {
     849           0 :     for( unsigned int i = 0; i < SAL_N_ELEMENTS(m_aGraphics); ++i )
     850             :     {
     851           0 :         if( !m_aGraphics[i].pGraphics )
     852           0 :             continue;
     853             : #if !GTK_CHECK_VERSION(3,0,0)
     854           0 :         m_aGraphics[i].pGraphics->SetDrawable( None, m_nXScreen );
     855             : #endif
     856           0 :         m_aGraphics[i].bInUse = false;
     857             :     }
     858             : 
     859           0 :     if( m_pParent )
     860           0 :         m_pParent->m_aChildren.remove( this );
     861             : 
     862           0 :     getDisplay()->deregisterFrame( this );
     863             : 
     864           0 :     if( m_pRegion )
     865             :     {
     866             : #if GTK_CHECK_VERSION(3,0,0)
     867             :         cairo_region_destroy( m_pRegion );
     868             : #else
     869           0 :         gdk_region_destroy( m_pRegion );
     870             : #endif
     871             :     }
     872             : 
     873             : #if !GTK_CHECK_VERSION(3,0,0)
     874           0 :     if( m_hBackgroundPixmap )
     875             :     {
     876           0 :         XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
     877             :                                     widget_get_xid(m_pWindow),
     878           0 :                                     None );
     879           0 :         XFreePixmap( getDisplay()->GetDisplay(), m_hBackgroundPixmap );
     880             :     }
     881             : #endif
     882             : 
     883           0 :     if( m_pIMHandler )
     884           0 :         delete m_pIMHandler;
     885             : 
     886           0 :     if( m_pFixedContainer )
     887           0 :         gtk_widget_destroy( GTK_WIDGET( m_pFixedContainer ) );
     888             :     {
     889           0 :         SolarMutexGuard aGuard;
     890             : #if defined ENABLE_GMENU_INTEGRATION
     891           0 :         if(m_nWatcherId)
     892           0 :             g_bus_unwatch_name(m_nWatcherId);
     893             : #endif
     894           0 :         if( m_pWindow )
     895             :         {
     896           0 :             g_object_set_data( G_OBJECT( m_pWindow ), "SalFrame", NULL );
     897             : 
     898             : #if defined ENABLE_GMENU_INTEGRATION
     899           0 :             if ( pSessionBus )
     900             :             {
     901           0 :                 if ( m_nHudAwarenessId )
     902           0 :                     hud_awareness_unregister( pSessionBus, m_nHudAwarenessId );
     903           0 :                 if ( m_nMenuExportId )
     904           0 :                     g_dbus_connection_unexport_menu_model( pSessionBus, m_nMenuExportId );
     905           0 :                 if ( m_nAppMenuExportId )
     906           0 :                     g_dbus_connection_unexport_menu_model( pSessionBus, m_nAppMenuExportId );
     907           0 :                 if ( m_nActionGroupExportId )
     908           0 :                     g_dbus_connection_unexport_action_group( pSessionBus, m_nActionGroupExportId );
     909           0 :                 if ( m_nAppActionGroupExportId )
     910           0 :                     g_dbus_connection_unexport_action_group( pSessionBus, m_nAppActionGroupExportId );
     911             :             }
     912             : #endif
     913           0 :             gtk_widget_destroy( m_pWindow );
     914           0 :         }
     915             :     }
     916           0 :     if( m_pForeignParent )
     917           0 :         g_object_unref( G_OBJECT( m_pForeignParent ) );
     918           0 :     if( m_pForeignTopLevel )
     919           0 :         g_object_unref( G_OBJECT( m_pForeignTopLevel) );
     920           0 : }
     921             : 
     922           0 : void GtkSalFrame::moveWindow( long nX, long nY )
     923             : {
     924           0 :     if( isChild( false, true ) )
     925             :     {
     926           0 :         if( m_pParent )
     927             :             gtk_fixed_move( m_pParent->getFixedContainer(),
     928             :                             m_pWindow,
     929           0 :                             nX - m_pParent->maGeometry.nX, nY - m_pParent->maGeometry.nY );
     930             :     }
     931             :     else
     932           0 :         gtk_window_move( GTK_WINDOW(m_pWindow), nX, nY );
     933           0 : }
     934             : 
     935           0 : void GtkSalFrame::resizeWindow( long nWidth, long nHeight )
     936             : {
     937           0 :     if( isChild( false, true ) )
     938           0 :         gtk_widget_set_size_request( m_pWindow, nWidth, nHeight );
     939           0 :     else if( ! isChild( true, false ) )
     940           0 :         gtk_window_resize( GTK_WINDOW(m_pWindow), nWidth, nHeight );
     941           0 : }
     942             : 
     943             : /*
     944             :  * Always use a sub-class of GtkFixed we can tag for a11y. This allows us to
     945             :  * utilize GAIL for the toplevel window and toolkit implementation incl.
     946             :  * key event listener support ..
     947             :  */
     948             : 
     949             : GType
     950           0 : ooo_fixed_get_type()
     951             : {
     952             :     static GType type = 0;
     953             : 
     954           0 :     if (!type) {
     955             :         static const GTypeInfo tinfo =
     956             :         {
     957             :             sizeof (GtkFixedClass),
     958             :             (GBaseInitFunc) NULL,      /* base init */
     959             :             (GBaseFinalizeFunc) NULL,  /* base finalize */
     960             :             (GClassInitFunc) NULL,     /* class init */
     961             :             (GClassFinalizeFunc) NULL, /* class finalize */
     962             :             NULL,                      /* class data */
     963             :             sizeof (GtkFixed),         /* instance size */
     964             :             0,                         /* nb preallocs */
     965             :             (GInstanceInitFunc) NULL,  /* instance init */
     966             :             NULL                       /* value table */
     967             :         };
     968             : 
     969             :         type = g_type_register_static( GTK_TYPE_FIXED, "OOoFixed",
     970           0 :                                        &tinfo, (GTypeFlags) 0);
     971             :     }
     972             : 
     973           0 :     return type;
     974             : }
     975             : 
     976           0 : void GtkSalFrame::updateScreenNumber()
     977             : {
     978           0 :     int nScreen = 0;
     979           0 :     GdkScreen *pScreen = gtk_widget_get_screen( m_pWindow );
     980           0 :     if( pScreen )
     981           0 :         nScreen = getDisplay()->getSystem()->getScreenMonitorIdx( pScreen, maGeometry.nX, maGeometry.nY );
     982           0 :     maGeometry.nDisplayScreenNumber = nScreen;
     983           0 : }
     984             : 
     985           0 : void GtkSalFrame::InitCommon()
     986             : {
     987             :     // connect signals
     988           0 :     g_signal_connect( G_OBJECT(m_pWindow), "style-set", G_CALLBACK(signalStyleSet), this );
     989           0 :     g_signal_connect( G_OBJECT(m_pWindow), "button-press-event", G_CALLBACK(signalButton), this );
     990           0 :     g_signal_connect( G_OBJECT(m_pWindow), "button-release-event", G_CALLBACK(signalButton), this );
     991             : #if GTK_CHECK_VERSION(3,0,0)
     992             :     g_signal_connect( G_OBJECT(m_pWindow), "draw", G_CALLBACK(signalDraw), this );
     993             : #else
     994           0 :     g_signal_connect( G_OBJECT(m_pWindow), "expose-event", G_CALLBACK(signalExpose), this );
     995             : #endif
     996           0 :     g_signal_connect( G_OBJECT(m_pWindow), "focus-in-event", G_CALLBACK(signalFocus), this );
     997           0 :     g_signal_connect( G_OBJECT(m_pWindow), "focus-out-event", G_CALLBACK(signalFocus), this );
     998           0 :     g_signal_connect( G_OBJECT(m_pWindow), "map-event", G_CALLBACK(signalMap), this );
     999           0 :     g_signal_connect( G_OBJECT(m_pWindow), "unmap-event", G_CALLBACK(signalUnmap), this );
    1000           0 :     g_signal_connect( G_OBJECT(m_pWindow), "configure-event", G_CALLBACK(signalConfigure), this );
    1001           0 :     g_signal_connect( G_OBJECT(m_pWindow), "motion-notify-event", G_CALLBACK(signalMotion), this );
    1002           0 :     g_signal_connect( G_OBJECT(m_pWindow), "key-press-event", G_CALLBACK(signalKey), this );
    1003           0 :     g_signal_connect( G_OBJECT(m_pWindow), "key-release-event", G_CALLBACK(signalKey), this );
    1004           0 :     g_signal_connect( G_OBJECT(m_pWindow), "delete-event", G_CALLBACK(signalDelete), this );
    1005           0 :     g_signal_connect( G_OBJECT(m_pWindow), "window-state-event", G_CALLBACK(signalState), this );
    1006           0 :     g_signal_connect( G_OBJECT(m_pWindow), "scroll-event", G_CALLBACK(signalScroll), this );
    1007           0 :     g_signal_connect( G_OBJECT(m_pWindow), "leave-notify-event", G_CALLBACK(signalCrossing), this );
    1008           0 :     g_signal_connect( G_OBJECT(m_pWindow), "enter-notify-event", G_CALLBACK(signalCrossing), this );
    1009           0 :     g_signal_connect( G_OBJECT(m_pWindow), "visibility-notify-event", G_CALLBACK(signalVisibility), this );
    1010           0 :     g_signal_connect( G_OBJECT(m_pWindow), "destroy", G_CALLBACK(signalDestroy), this );
    1011             : 
    1012             :     // init members
    1013           0 :     m_pCurrentCursor    = NULL;
    1014           0 :     m_nKeyModifiers     = 0;
    1015           0 :     m_bFullscreen       = false;
    1016           0 :     m_bSpanMonitorsWhenFullscreen = false;
    1017           0 :     m_nState            = GDK_WINDOW_STATE_WITHDRAWN;
    1018           0 :     m_nVisibility       = GDK_VISIBILITY_FULLY_OBSCURED;
    1019           0 :     m_bSendModChangeOnRelease = false;
    1020           0 :     m_pIMHandler        = NULL;
    1021           0 :     m_hBackgroundPixmap = None;
    1022           0 :     m_nSavedScreenSaverTimeout = 0;
    1023           0 :     m_nGSMCookie = 0;
    1024           0 :     m_nExtStyle         = 0;
    1025           0 :     m_pRegion           = NULL;
    1026           0 :     m_ePointerStyle     = 0xffff;
    1027           0 :     m_bSetFocusOnMap    = false;
    1028           0 :     m_pSalMenu          = NULL;
    1029           0 :     m_nWatcherId        = 0;
    1030           0 :     m_nMenuExportId     = 0;
    1031           0 :     m_nAppMenuExportId  = 0;
    1032           0 :     m_nActionGroupExportId = 0;
    1033           0 :     m_nAppActionGroupExportId = 0;
    1034           0 :     m_nHudAwarenessId   = 0;
    1035             : 
    1036           0 :     gtk_widget_set_app_paintable( m_pWindow, TRUE );
    1037           0 :     gtk_widget_set_double_buffered( m_pWindow, FALSE );
    1038           0 :     gtk_widget_set_redraw_on_allocate( m_pWindow, FALSE );
    1039             : 
    1040             :     gtk_widget_add_events( m_pWindow,
    1041             :                            GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
    1042             :                            GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
    1043             :                            GDK_VISIBILITY_NOTIFY_MASK
    1044           0 :                            );
    1045             : 
    1046             :     // add the fixed container child,
    1047             :     // fixed is needed since we have to position plugin windows
    1048           0 :     m_pFixedContainer = GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL ));
    1049           0 :     gtk_container_add( GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pFixedContainer) );
    1050             : 
    1051             :     // show the widgets
    1052           0 :     gtk_widget_show( GTK_WIDGET(m_pFixedContainer) );
    1053             : 
    1054             :     // realize the window, we need an XWindow id
    1055           0 :     gtk_widget_realize( m_pWindow );
    1056             : 
    1057             :     //system data
    1058           0 :     m_aSystemData.nSize         = sizeof( SystemEnvData );
    1059             : #if !GTK_CHECK_VERSION(3,0,0)
    1060           0 :     GtkSalDisplay* pDisp = GetGtkSalData()->GetGtkDisplay();
    1061           0 :     m_aSystemData.pDisplay      = pDisp->GetDisplay();
    1062           0 :     m_aSystemData.pVisual       = pDisp->GetVisual( m_nXScreen ).GetVisual();
    1063           0 :     m_aSystemData.nDepth        = pDisp->GetVisual( m_nXScreen ).GetDepth();
    1064           0 :     m_aSystemData.aColormap     = pDisp->GetColormap( m_nXScreen ).GetXColormap();
    1065           0 :     m_aSystemData.aWindow       = widget_get_xid(m_pWindow);
    1066             : #else
    1067             :     static int nWindow = 0;
    1068             :     m_aSystemData.aWindow       = nWindow++;
    1069             : #endif
    1070           0 :     m_aSystemData.pSalFrame     = this;
    1071           0 :     m_aSystemData.pWidget       = m_pWindow;
    1072           0 :     m_aSystemData.nScreen       = m_nXScreen.getXScreen();
    1073           0 :     m_aSystemData.pAppContext   = NULL;
    1074           0 :     m_aSystemData.aShellWindow  = m_aSystemData.aWindow;
    1075           0 :     m_aSystemData.pShellWidget  = m_aSystemData.pWidget;
    1076             : 
    1077             :     // fake an initial geometry, gets updated via configure event or SetPosSize
    1078           0 :     if( m_bDefaultPos || m_bDefaultSize )
    1079             :     {
    1080           0 :         Size aDefSize = calcDefaultSize();
    1081           0 :         maGeometry.nX                   = -1;
    1082           0 :         maGeometry.nY                   = -1;
    1083           0 :         maGeometry.nWidth               = aDefSize.Width();
    1084           0 :         maGeometry.nHeight              = aDefSize.Height();
    1085           0 :         if( m_pParent )
    1086             :         {
    1087             :             // approximation
    1088           0 :             maGeometry.nTopDecoration       = m_pParent->maGeometry.nTopDecoration;
    1089           0 :             maGeometry.nBottomDecoration    = m_pParent->maGeometry.nBottomDecoration;
    1090           0 :             maGeometry.nLeftDecoration      = m_pParent->maGeometry.nLeftDecoration;
    1091           0 :             maGeometry.nRightDecoration     = m_pParent->maGeometry.nRightDecoration;
    1092             :         }
    1093             :         else
    1094             :         {
    1095           0 :             maGeometry.nTopDecoration       = 0;
    1096           0 :             maGeometry.nBottomDecoration    = 0;
    1097           0 :             maGeometry.nLeftDecoration      = 0;
    1098           0 :             maGeometry.nRightDecoration     = 0;
    1099           0 :         }
    1100             :     }
    1101             :     else
    1102             :     {
    1103           0 :         resizeWindow( maGeometry.nWidth, maGeometry.nHeight );
    1104           0 :         moveWindow( maGeometry.nX, maGeometry.nY );
    1105             :     }
    1106           0 :     updateScreenNumber();
    1107             : 
    1108           0 :     SetIcon(1);
    1109             : 
    1110             : #if !GTK_CHECK_VERSION(3,0,0)
    1111           0 :     m_nWorkArea = pDisp->getWMAdaptor()->getCurrentWorkArea();
    1112             :     /* #i64117# gtk sets a nice background pixmap
    1113             :     *  but we actually don't really want that, so save
    1114             :     *  some time on the Xserver as well as prevent
    1115             :     *  some paint issues
    1116             :     */
    1117           0 :     XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
    1118             :                                 widget_get_xid(m_pWindow),
    1119           0 :                                 m_hBackgroundPixmap );
    1120             : #endif
    1121           0 : }
    1122             : 
    1123             : /*  Sadly gtk_window_set_accept_focus exists only since gtk 2.4
    1124             :  *  for achieving the same effect we will remove the WM_TAKE_FOCUS
    1125             :  *  protocol from the window and set the input hint to false.
    1126             :  *  But gtk_window_set_accept_focus needs to be called before
    1127             :  *  window realization whereas the removal obviously can only happen
    1128             :  *  after realization.
    1129             :  */
    1130             : 
    1131             : #if !GTK_CHECK_VERSION(3,0,0)
    1132             : extern "C" {
    1133             :     typedef void(*setAcceptFn)( GtkWindow*, gboolean );
    1134             :     static setAcceptFn p_gtk_window_set_accept_focus = NULL;
    1135             :     static bool bGetAcceptFocusFn = true;
    1136             : 
    1137             :     typedef void(*setUserTimeFn)( GdkWindow*, guint32 );
    1138             :     static setUserTimeFn p_gdk_x11_window_set_user_time = NULL;
    1139             :     static bool bGetSetUserTimeFn = true;
    1140             : }
    1141             : #endif
    1142             : 
    1143           0 : static void lcl_set_accept_focus( GtkWindow* pWindow, gboolean bAccept, bool bBeforeRealize )
    1144             : {
    1145             : #if !GTK_CHECK_VERSION(3,0,0)
    1146           0 :     if( bGetAcceptFocusFn )
    1147             :     {
    1148           0 :         bGetAcceptFocusFn = false;
    1149           0 :         p_gtk_window_set_accept_focus = (setAcceptFn)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gtk_window_set_accept_focus" );
    1150             :     }
    1151           0 :     if( p_gtk_window_set_accept_focus && bBeforeRealize )
    1152           0 :         p_gtk_window_set_accept_focus( pWindow, bAccept );
    1153           0 :     else if( ! bBeforeRealize )
    1154             :     {
    1155           0 :         Display* pDisplay = GetGtkSalData()->GetGtkDisplay()->GetDisplay();
    1156           0 :         ::Window aWindow = widget_get_xid(GTK_WIDGET(pWindow));
    1157           0 :         XWMHints* pHints = XGetWMHints( pDisplay, aWindow );
    1158           0 :         if( ! pHints )
    1159             :         {
    1160           0 :             pHints = XAllocWMHints();
    1161           0 :             pHints->flags = 0;
    1162             :         }
    1163           0 :         pHints->flags |= InputHint;
    1164           0 :         pHints->input = bAccept ? True : False;
    1165           0 :         XSetWMHints( pDisplay, aWindow, pHints );
    1166           0 :         XFree( pHints );
    1167             : 
    1168           0 :         if (GetGtkSalData()->GetGtkDisplay()->getWMAdaptor()->getWindowManagerName().equalsAscii("compiz"))
    1169           0 :             return;
    1170             : 
    1171             :         /*  remove WM_TAKE_FOCUS protocol; this would usually be the
    1172             :          *  right thing, but gtk handles it internally whereas we
    1173             :          *  want to handle it ourselves (as to sometimes not get
    1174             :          *  the focus)
    1175             :          */
    1176           0 :         Atom* pProtocols = NULL;
    1177           0 :         int nProtocols = 0;
    1178             :         XGetWMProtocols( pDisplay,
    1179             :                          aWindow,
    1180           0 :                          &pProtocols, &nProtocols );
    1181           0 :         if( pProtocols )
    1182             :         {
    1183           0 :             bool bSet = false;
    1184           0 :             Atom nTakeFocus = XInternAtom( pDisplay, "WM_TAKE_FOCUS", True );
    1185           0 :             if( nTakeFocus )
    1186             :             {
    1187           0 :                 for( int i = 0; i < nProtocols; i++ )
    1188             :                 {
    1189           0 :                     if( pProtocols[i] == nTakeFocus )
    1190             :                     {
    1191           0 :                         for( int n = i; n < nProtocols-1; n++ )
    1192           0 :                             pProtocols[n] = pProtocols[n+1];
    1193           0 :                         nProtocols--;
    1194           0 :                         i--;
    1195           0 :                         bSet = true;
    1196             :                     }
    1197             :                 }
    1198             :             }
    1199           0 :             if( bSet )
    1200           0 :                 XSetWMProtocols( pDisplay, aWindow, pProtocols, nProtocols );
    1201           0 :             XFree( pProtocols );
    1202             :         }
    1203             :     }
    1204             : #else
    1205             :     (void)pWindow; (void)bAccept; (void)bBeforeRealize;
    1206             :     //FIXME: No set_accept_focus impl
    1207             : #endif
    1208             : }
    1209             : 
    1210           0 : static void lcl_set_user_time( GtkWindow* i_pWindow, guint32 i_nTime )
    1211             : {
    1212             : #if !GTK_CHECK_VERSION(3,0,0)
    1213           0 :     if( bGetSetUserTimeFn )
    1214             :     {
    1215           0 :         bGetSetUserTimeFn = false;
    1216           0 :         p_gdk_x11_window_set_user_time = (setUserTimeFn)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_x11_window_set_user_time" );
    1217             :     }
    1218           0 :     bool bSet = false;
    1219           0 :     if( p_gdk_x11_window_set_user_time )
    1220             :     {
    1221           0 :         GdkWindow* pWin = widget_get_window(GTK_WIDGET(i_pWindow));
    1222           0 :         if( pWin ) // only if the window is realized.
    1223             :         {
    1224           0 :             p_gdk_x11_window_set_user_time( pWin, i_nTime );
    1225           0 :             bSet = true;
    1226             :         }
    1227             :     }
    1228           0 :     if( !bSet )
    1229             :     {
    1230           0 :         Display* pDisplay = GetGtkSalData()->GetGtkDisplay()->GetDisplay();
    1231           0 :         Atom nUserTime = XInternAtom( pDisplay, "_NET_WM_USER_TIME", True );
    1232           0 :         if( nUserTime )
    1233             :         {
    1234           0 :             XChangeProperty( pDisplay, widget_get_xid(GTK_WIDGET(i_pWindow)),
    1235             :                              nUserTime, XA_CARDINAL, 32,
    1236           0 :                              PropModeReplace, (unsigned char*)&i_nTime, 1 );
    1237             :         }
    1238             :     }
    1239             : #else
    1240             :     (void)i_pWindow; (void)i_nTime;
    1241             :     //FIXME: no lcl_set_user_time impl.
    1242             : #endif
    1243           0 : };
    1244             : 
    1245           0 : GtkSalFrame *GtkSalFrame::getFromWindow( GtkWindow *pWindow )
    1246             : {
    1247           0 :     return (GtkSalFrame *) g_object_get_data( G_OBJECT( pWindow ), "SalFrame" );
    1248             : }
    1249             : 
    1250           0 : void GtkSalFrame::Init( SalFrame* pParent, sal_uLong nStyle )
    1251             : {
    1252           0 :     if( nStyle & SAL_FRAME_STYLE_DEFAULT ) // ensure default style
    1253             :     {
    1254           0 :         nStyle |= SAL_FRAME_STYLE_MOVEABLE | SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_CLOSEABLE;
    1255           0 :         nStyle &= ~SAL_FRAME_STYLE_FLOAT;
    1256             :     }
    1257             : 
    1258           0 :     m_pParent = static_cast<GtkSalFrame*>(pParent);
    1259           0 :     m_pForeignParent = NULL;
    1260           0 :     m_aForeignParentWindow = None;
    1261           0 :     m_pForeignTopLevel = NULL;
    1262           0 :     m_aForeignTopLevelWindow = None;
    1263           0 :     m_nStyle = nStyle;
    1264             : 
    1265           0 :     GtkWindowType eWinType = (  (nStyle & SAL_FRAME_STYLE_FLOAT) &&
    1266           0 :                               ! (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|
    1267             :                                            SAL_FRAME_STYLE_FLOAT_FOCUSABLE))
    1268             :                               )
    1269           0 :         ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL;
    1270             : 
    1271           0 :     if( nStyle & SAL_FRAME_STYLE_SYSTEMCHILD )
    1272             :     {
    1273           0 :         m_pWindow = gtk_event_box_new();
    1274           0 :         if( m_pParent )
    1275             :         {
    1276             :             // insert into container
    1277             :             gtk_fixed_put( m_pParent->getFixedContainer(),
    1278           0 :                            m_pWindow, 0, 0 );
    1279             : 
    1280             :         }
    1281             :     }
    1282             :     else
    1283             :         m_pWindow = gtk_widget_new( GTK_TYPE_WINDOW, "type", eWinType,
    1284           0 :                                     "visible", FALSE, NULL );
    1285           0 :     g_object_set_data( G_OBJECT( m_pWindow ), "SalFrame", this );
    1286           0 :     g_object_set_data( G_OBJECT( m_pWindow ), "libo-version", (gpointer)LIBO_VERSION_DOTTED);
    1287             : 
    1288             :     // force wm class hint
    1289           0 :     m_nExtStyle = ~0;
    1290           0 :     if (m_pParent)
    1291           0 :         m_sWMClass = m_pParent->m_sWMClass;
    1292           0 :     SetExtendedFrameStyle( 0 );
    1293             : 
    1294           0 :     if( m_pParent && m_pParent->m_pWindow && ! isChild() )
    1295           0 :         gtk_window_set_screen( GTK_WINDOW(m_pWindow), gtk_window_get_screen( GTK_WINDOW(m_pParent->m_pWindow) ) );
    1296             : 
    1297             :     // set window type
    1298             :     bool bDecoHandling =
    1299           0 :         ! isChild() &&
    1300           0 :         ( ! (nStyle & SAL_FRAME_STYLE_FLOAT) ||
    1301           0 :           (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) );
    1302             : 
    1303           0 :     if( bDecoHandling )
    1304             :     {
    1305           0 :         GdkWindowTypeHint eType = GDK_WINDOW_TYPE_HINT_NORMAL;
    1306           0 :         if( (nStyle & SAL_FRAME_STYLE_DIALOG) && m_pParent != 0 )
    1307           0 :             eType = GDK_WINDOW_TYPE_HINT_DIALOG;
    1308           0 :         if( (nStyle & SAL_FRAME_STYLE_INTRO) )
    1309             :         {
    1310           0 :             gtk_window_set_role( GTK_WINDOW(m_pWindow), "splashscreen" );
    1311           0 :             eType = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
    1312             :         }
    1313           0 :         else if( (nStyle & SAL_FRAME_STYLE_TOOLWINDOW ) )
    1314             :         {
    1315           0 :             eType = GDK_WINDOW_TYPE_HINT_UTILITY;
    1316           0 :             gtk_window_set_skip_taskbar_hint( GTK_WINDOW(m_pWindow), true );
    1317             :         }
    1318           0 :         else if( (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
    1319             :         {
    1320           0 :             eType = GDK_WINDOW_TYPE_HINT_TOOLBAR;
    1321           0 :             lcl_set_accept_focus( GTK_WINDOW(m_pWindow), false, true );
    1322             :         }
    1323           0 :         else if( (nStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
    1324             :         {
    1325           0 :             eType = GDK_WINDOW_TYPE_HINT_UTILITY;
    1326             :         }
    1327             : #if !GTK_CHECK_VERSION(3,0,0)
    1328           0 :         if( (nStyle & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN )
    1329           0 :             && getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
    1330             :         {
    1331           0 :             eType = GDK_WINDOW_TYPE_HINT_TOOLBAR;
    1332           0 :             gtk_window_set_keep_above( GTK_WINDOW(m_pWindow), true );
    1333             :         }
    1334             : #endif
    1335           0 :         gtk_window_set_type_hint( GTK_WINDOW(m_pWindow), eType );
    1336           0 :         gtk_window_set_gravity( GTK_WINDOW(m_pWindow), GDK_GRAVITY_STATIC );
    1337           0 :         if( m_pParent && ! (m_pParent->m_nStyle & SAL_FRAME_STYLE_PLUG) )
    1338           0 :             gtk_window_set_transient_for( GTK_WINDOW(m_pWindow), GTK_WINDOW(m_pParent->m_pWindow) );
    1339             :     }
    1340           0 :     else if( (nStyle & SAL_FRAME_STYLE_FLOAT) )
    1341             :     {
    1342           0 :         gtk_window_set_type_hint( GTK_WINDOW(m_pWindow), GDK_WINDOW_TYPE_HINT_UTILITY );
    1343             :     }
    1344           0 :     if( m_pParent )
    1345           0 :         m_pParent->m_aChildren.push_back( this );
    1346             : 
    1347           0 :     InitCommon();
    1348             : 
    1349             : #if !GTK_CHECK_VERSION(3,0,0)
    1350           0 :     if( eWinType == GTK_WINDOW_TOPLEVEL )
    1351             :     {
    1352             : #ifdef ENABLE_GMENU_INTEGRATION
    1353             :         // Enable DBus native menu if available.
    1354           0 :         ensure_dbus_setup( this );
    1355             : #endif
    1356             : 
    1357           0 :         guint32 nUserTime = 0;
    1358           0 :         if( (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 )
    1359             :         {
    1360             :             /* #i99360# ugly workaround an X11 library bug */
    1361           0 :             nUserTime= getDisplay()->GetLastUserEventTime( true );
    1362             :         }
    1363           0 :         lcl_set_user_time(GTK_WINDOW(m_pWindow), nUserTime);
    1364             :     }
    1365             : #endif
    1366             : 
    1367           0 :     if( bDecoHandling )
    1368             :     {
    1369           0 :         gtk_window_set_resizable( GTK_WINDOW(m_pWindow), (nStyle & SAL_FRAME_STYLE_SIZEABLE) != 0 );
    1370           0 :         if( ( (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION)) ) )
    1371           0 :             lcl_set_accept_focus( GTK_WINDOW(m_pWindow), false, false );
    1372             :     }
    1373           0 : }
    1374             : 
    1375           0 : GdkNativeWindow GtkSalFrame::findTopLevelSystemWindow( GdkNativeWindow aWindow )
    1376             : {
    1377             : #if !GTK_CHECK_VERSION(3,0,0)
    1378             :     ::Window aRoot, aParent;
    1379             :     ::Window* pChildren;
    1380             :     unsigned int nChildren;
    1381           0 :     bool bBreak = false;
    1382           0 :     do
    1383             :     {
    1384           0 :         pChildren = NULL;
    1385           0 :         nChildren = 0;
    1386           0 :         aParent = aRoot = None;
    1387           0 :         XQueryTree( getDisplay()->GetDisplay(), aWindow,
    1388           0 :                     &aRoot, &aParent, &pChildren, &nChildren );
    1389           0 :         XFree( pChildren );
    1390           0 :         if( aParent != aRoot )
    1391           0 :             aWindow = aParent;
    1392           0 :         int nCount = 0;
    1393           0 :         Atom* pProps = XListProperties( getDisplay()->GetDisplay(),
    1394             :                                         aWindow,
    1395           0 :                                         &nCount );
    1396           0 :         for( int i = 0; i < nCount && ! bBreak; ++i )
    1397           0 :             bBreak = (pProps[i] == XA_WM_HINTS);
    1398           0 :         if( pProps )
    1399           0 :             XFree( pProps );
    1400           0 :     } while( aParent != aRoot && ! bBreak );
    1401             : 
    1402           0 :     return aWindow;
    1403             : #else
    1404             :     (void)aWindow;
    1405             :     //FIXME: no findToplevelSystemWindow
    1406             :     return 0;
    1407             : #endif
    1408             : }
    1409             : 
    1410           0 : void GtkSalFrame::Init( SystemParentData* pSysData )
    1411             : {
    1412           0 :     m_pParent = NULL;
    1413           0 :     m_aForeignParentWindow = (GdkNativeWindow)pSysData->aWindow;
    1414           0 :     m_pForeignParent = NULL;
    1415           0 :     m_aForeignTopLevelWindow = findTopLevelSystemWindow( (GdkNativeWindow)pSysData->aWindow );
    1416           0 :     m_pForeignTopLevel = gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignTopLevelWindow );
    1417           0 :     gdk_window_set_events( m_pForeignTopLevel, GDK_STRUCTURE_MASK );
    1418             : 
    1419           0 :     if( pSysData->nSize > sizeof(pSysData->nSize)+sizeof(pSysData->aWindow) && pSysData->bXEmbedSupport )
    1420             :     {
    1421             : #if GTK_CHECK_VERSION(3,0,0)
    1422             :         m_pWindow = gtk_plug_new_for_display( getGdkDisplay(), pSysData->aWindow );
    1423             : #else
    1424           0 :         m_pWindow = gtk_plug_new( pSysData->aWindow );
    1425             : #endif
    1426           0 :         m_bWindowIsGtkPlug  = true;
    1427           0 :         widget_set_can_default( m_pWindow, true );
    1428           0 :         widget_set_can_focus( m_pWindow, true );
    1429           0 :         gtk_widget_set_sensitive( m_pWindow, true );
    1430             :     }
    1431             :     else
    1432             :     {
    1433           0 :         m_pWindow = gtk_window_new( GTK_WINDOW_POPUP );
    1434           0 :         m_bWindowIsGtkPlug  = false;
    1435             :     }
    1436           0 :     m_nStyle = SAL_FRAME_STYLE_PLUG;
    1437           0 :     InitCommon();
    1438             : 
    1439           0 :     m_pForeignParent = gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignParentWindow );
    1440           0 :     gdk_window_set_events( m_pForeignParent, GDK_STRUCTURE_MASK );
    1441             : 
    1442             : #if !GTK_CHECK_VERSION(3,0,0)
    1443             :     int x_ret, y_ret;
    1444             :     unsigned int w, h, bw, d;
    1445             :     ::Window aRoot;
    1446           0 :     XGetGeometry( getDisplay()->GetDisplay(), pSysData->aWindow,
    1447           0 :                   &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d );
    1448           0 :     maGeometry.nWidth   = w;
    1449           0 :     maGeometry.nHeight  = h;
    1450           0 :     gtk_window_resize( GTK_WINDOW(m_pWindow), w, h );
    1451           0 :     gtk_window_move( GTK_WINDOW(m_pWindow), 0, 0 );
    1452           0 :     if( ! m_bWindowIsGtkPlug )
    1453             :     {
    1454           0 :         XReparentWindow( getDisplay()->GetDisplay(),
    1455             :                          widget_get_xid(m_pWindow),
    1456             :                          (::Window)pSysData->aWindow,
    1457           0 :                          0, 0 );
    1458             :     }
    1459             : #else
    1460             :     //FIXME: Handling embedded windows, is going to be fun ...
    1461             : #endif
    1462           0 : }
    1463             : 
    1464           0 : void GtkSalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode )
    1465             : {
    1466             : #if !GTK_CHECK_VERSION(3,0,0)
    1467             :     XEvent aEvent;
    1468             : 
    1469           0 :     memset( &aEvent, 0, sizeof(aEvent) );
    1470           0 :     aEvent.xclient.window = m_aForeignParentWindow;
    1471           0 :     aEvent.xclient.type = ClientMessage;
    1472           0 :     aEvent.xclient.message_type = getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED );
    1473           0 :     aEvent.xclient.format = 32;
    1474           0 :     aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime;
    1475           0 :     aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS
    1476           0 :     aEvent.xclient.data.l[2] = 0;
    1477           0 :     aEvent.xclient.data.l[3] = 0;
    1478           0 :     aEvent.xclient.data.l[4] = 0;
    1479             : 
    1480           0 :     GetGenericData()->ErrorTrapPush();
    1481           0 :     XSendEvent( getDisplay()->GetDisplay(),
    1482             :                 m_aForeignParentWindow,
    1483           0 :                 False, NoEventMask, &aEvent );
    1484           0 :     GetGenericData()->ErrorTrapPop();
    1485             : #else
    1486             :     (void)i_nTimeCode;
    1487             :     //FIXME: no askForXEmbedFocus for gtk3 yet
    1488             : #endif
    1489           0 : }
    1490             : 
    1491           0 : void GtkSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
    1492             : {
    1493           0 :     if( nStyle != m_nExtStyle && ! isChild() )
    1494             :     {
    1495           0 :         m_nExtStyle = nStyle;
    1496           0 :         updateWMClass();
    1497             :     }
    1498           0 : }
    1499             : 
    1500           0 : SalGraphics* GtkSalFrame::AcquireGraphics()
    1501             : {
    1502           0 :     if( m_pWindow )
    1503             :     {
    1504           0 :         for( int i = 0; i < nMaxGraphics; i++ )
    1505             :         {
    1506           0 :             if( ! m_aGraphics[i].bInUse )
    1507             :             {
    1508           0 :                 m_aGraphics[i].bInUse = true;
    1509           0 :                 if( ! m_aGraphics[i].pGraphics )
    1510             :                 {
    1511             : #if GTK_CHECK_VERSION(3,0,0)
    1512             :                     m_aGraphics[i].pGraphics = new GtkSalGraphics( this, m_pWindow );
    1513             :                     if( !m_aFrame.get() )
    1514             :                         AllocateFrame();
    1515             :                     m_aGraphics[i].pGraphics->setDevice( m_aFrame );
    1516             : #else // common case:
    1517           0 :                     m_aGraphics[i].pGraphics = new GtkSalGraphics( this, m_pWindow, m_nXScreen );
    1518             : #endif
    1519             :                 }
    1520           0 :                 return m_aGraphics[i].pGraphics;
    1521             :             }
    1522             :         }
    1523             :     }
    1524             : 
    1525           0 :     return NULL;
    1526             : }
    1527             : 
    1528           0 : void GtkSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
    1529             : {
    1530           0 :     for( int i = 0; i < nMaxGraphics; i++ )
    1531             :     {
    1532           0 :         if( m_aGraphics[i].pGraphics == pGraphics )
    1533             :         {
    1534           0 :             m_aGraphics[i].bInUse = false;
    1535           0 :             break;
    1536             :         }
    1537             :     }
    1538           0 : }
    1539             : 
    1540           0 : bool GtkSalFrame::PostEvent( void* pData )
    1541             : {
    1542           0 :     getDisplay()->SendInternalEvent( this, pData );
    1543           0 :     return true;
    1544             : }
    1545             : 
    1546           0 : void GtkSalFrame::SetTitle( const OUString& rTitle )
    1547             : {
    1548           0 :     m_aTitle = rTitle;
    1549           0 :     if( m_pWindow && ! isChild() )
    1550           0 :         gtk_window_set_title( GTK_WINDOW(m_pWindow), OUStringToOString( rTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
    1551           0 : }
    1552             : 
    1553             : static inline sal_uInt8 *
    1554           0 : getRow( BitmapBuffer *pBuffer, sal_uLong nRow )
    1555             : {
    1556           0 :     if( BMP_SCANLINE_ADJUSTMENT( pBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
    1557           0 :         return pBuffer->mpBits + nRow * pBuffer->mnScanlineSize;
    1558             :     else
    1559           0 :         return pBuffer->mpBits + ( pBuffer->mnHeight - nRow - 1 ) * pBuffer->mnScanlineSize;
    1560             : }
    1561             : 
    1562             : static GdkPixbuf *
    1563           0 : bitmapToPixbuf( SalBitmap *pSalBitmap, SalBitmap *pSalAlpha )
    1564             : {
    1565           0 :     g_return_val_if_fail( pSalBitmap != NULL, NULL );
    1566           0 :     g_return_val_if_fail( pSalAlpha != NULL, NULL );
    1567             : 
    1568           0 :     BitmapBuffer *pBitmap = pSalBitmap->AcquireBuffer( true );
    1569           0 :     g_return_val_if_fail( pBitmap != NULL, NULL );
    1570           0 :     g_return_val_if_fail( pBitmap->mnBitCount == 24, NULL );
    1571             : 
    1572           0 :     BitmapBuffer *pAlpha = pSalAlpha->AcquireBuffer( true );
    1573           0 :     g_return_val_if_fail( pAlpha != NULL, NULL );
    1574           0 :     g_return_val_if_fail( pAlpha->mnBitCount == 8, NULL );
    1575             : 
    1576           0 :     Size aSize = pSalBitmap->GetSize();
    1577           0 :     g_return_val_if_fail( pSalAlpha->GetSize() == aSize, NULL );
    1578             : 
    1579             :     int nX, nY;
    1580           0 :     guchar *pPixbufData = (guchar *)g_malloc (4 * aSize.Width() * aSize.Height() );
    1581           0 :     guchar *pDestData = pPixbufData;
    1582             : 
    1583           0 :     for( nY = 0; nY < pBitmap->mnHeight; nY++ )
    1584             :     {
    1585           0 :         sal_uInt8 *pData = getRow( pBitmap, nY );
    1586           0 :         sal_uInt8 *pAlphaData = getRow( pAlpha, nY );
    1587             : 
    1588           0 :         for( nX = 0; nX < pBitmap->mnWidth; nX++ )
    1589             :         {
    1590           0 :             if( pBitmap->mnFormat == BMP_FORMAT_24BIT_TC_BGR )
    1591             :             {
    1592           0 :                 pDestData[2] = *pData++;
    1593           0 :                 pDestData[1] = *pData++;
    1594           0 :                 pDestData[0] = *pData++;
    1595             :             }
    1596             :             else // BMP_FORMAT_24BIT_TC_RGB
    1597             :             {
    1598           0 :                 pDestData[0] = *pData++;
    1599           0 :                 pDestData[1] = *pData++;
    1600           0 :                 pDestData[2] = *pData++;
    1601             :             }
    1602           0 :             pDestData += 3;
    1603           0 :             *pDestData++ = 255 - *pAlphaData++;
    1604             :         }
    1605             :     }
    1606             : 
    1607           0 :     pSalBitmap->ReleaseBuffer( pBitmap, true );
    1608           0 :     pSalAlpha->ReleaseBuffer( pAlpha, true );
    1609             : 
    1610             :     return gdk_pixbuf_new_from_data( pPixbufData,
    1611             :                                      GDK_COLORSPACE_RGB, true, 8,
    1612           0 :                                      aSize.Width(), aSize.Height(),
    1613           0 :                                      aSize.Width() * 4,
    1614             :                                      (GdkPixbufDestroyNotify) g_free,
    1615           0 :                                      NULL );
    1616             : }
    1617             : 
    1618           0 : void GtkSalFrame::SetIcon( sal_uInt16 nIcon )
    1619             : {
    1620           0 :     if( (m_nStyle & (SAL_FRAME_STYLE_PLUG|SAL_FRAME_STYLE_SYSTEMCHILD|SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_INTRO|SAL_FRAME_STYLE_OWNERDRAWDECORATION))
    1621           0 :         || ! m_pWindow )
    1622           0 :         return;
    1623             : 
    1624           0 :     if( !ImplGetResMgr() )
    1625           0 :         return;
    1626             : 
    1627             :     GdkPixbuf *pBuf;
    1628           0 :     GList *pIcons = NULL;
    1629             : 
    1630           0 :     sal_uInt16 nOffsets[2] = { SV_ICON_SMALL_START, SV_ICON_LARGE_START };
    1631             :     sal_uInt16 nIndex;
    1632             : 
    1633           0 :     for( nIndex = 0; nIndex < sizeof(nOffsets)/ sizeof(sal_uInt16); nIndex++ )
    1634             :     {
    1635             :         // #i44723# workaround gcc temporary problem
    1636           0 :         ResId aResId( nOffsets[nIndex] + nIcon, *ImplGetResMgr() );
    1637           0 :         BitmapEx aIcon( aResId );
    1638             : 
    1639             :         // #i81083# convert to 24bit/8bit alpha bitmap
    1640           0 :         Bitmap aBmp = aIcon.GetBitmap();
    1641           0 :         if( aBmp.GetBitCount() != 24 || ! aIcon.IsAlpha() )
    1642             :         {
    1643           0 :             if( aBmp.GetBitCount() != 24 )
    1644           0 :                 aBmp.Convert( BMP_CONVERSION_24BIT );
    1645           0 :             AlphaMask aMask;
    1646           0 :             if( ! aIcon.IsAlpha() )
    1647             :             {
    1648           0 :                 switch( aIcon.GetTransparentType() )
    1649             :                 {
    1650             :                     case TRANSPARENT_NONE:
    1651             :                     {
    1652           0 :                         sal_uInt8 nTrans = 0;
    1653           0 :                         aMask = AlphaMask( aBmp.GetSizePixel(), &nTrans );
    1654             :                     }
    1655           0 :                     break;
    1656             :                     case TRANSPARENT_COLOR:
    1657           0 :                         aMask = AlphaMask( aBmp.CreateMask( aIcon.GetTransparentColor() ) );
    1658           0 :                     break;
    1659             :                     case TRANSPARENT_BITMAP:
    1660           0 :                         aMask = AlphaMask( aIcon.GetMask() );
    1661           0 :                     break;
    1662             :                     default:
    1663             :                         OSL_FAIL( "unhandled transparent type" );
    1664           0 :                     break;
    1665             :                 }
    1666             :             }
    1667             :             else
    1668           0 :                 aMask = aIcon.GetAlpha();
    1669           0 :             aIcon = BitmapEx( aBmp, aMask );
    1670             :         }
    1671             : 
    1672           0 :         ImpBitmap *pIconImpBitmap = aIcon.ImplGetBitmapImpBitmap();
    1673           0 :         ImpBitmap *pIconImpMask   = aIcon.ImplGetMaskImpBitmap();
    1674             : 
    1675           0 :         if( pIconImpBitmap && pIconImpMask )
    1676             :         {
    1677             :             SalBitmap *pIconBitmap =
    1678           0 :                 pIconImpBitmap->ImplGetSalBitmap();
    1679             :             SalBitmap *pIconMask =
    1680           0 :                 pIconImpMask->ImplGetSalBitmap();
    1681             : 
    1682           0 :             if( ( pBuf = bitmapToPixbuf( pIconBitmap, pIconMask ) ) )
    1683           0 :                 pIcons = g_list_prepend( pIcons, pBuf );
    1684             :         }
    1685           0 :     }
    1686             : 
    1687           0 :     gtk_window_set_icon_list( GTK_WINDOW(m_pWindow), pIcons );
    1688             : 
    1689           0 :     g_list_foreach( pIcons, (GFunc) g_object_unref, NULL );
    1690           0 :     g_list_free( pIcons );
    1691             : }
    1692             : 
    1693           0 : void GtkSalFrame::SetMenu( SalMenu* pSalMenu )
    1694             : {
    1695             : //    if(m_pSalMenu)
    1696             : //    {
    1697             : //        static_cast<GtkSalMenu*>(m_pSalMenu)->DisconnectFrame();
    1698             : //    }
    1699           0 :     m_pSalMenu = pSalMenu;
    1700           0 : }
    1701             : 
    1702           0 : SalMenu* GtkSalFrame::GetMenu( void )
    1703             : {
    1704           0 :     return m_pSalMenu;
    1705             : }
    1706             : 
    1707           0 : void GtkSalFrame::DrawMenuBar()
    1708             : {
    1709           0 : }
    1710             : 
    1711           0 : void GtkSalFrame::Center()
    1712             : {
    1713             :     long nX, nY;
    1714             : 
    1715           0 :     if( m_pParent )
    1716             :     {
    1717           0 :         nX = ((long)m_pParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2;
    1718           0 :         nY = ((long)m_pParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2;
    1719             :     }
    1720             :     else
    1721             :     {
    1722           0 :         GdkScreen *pScreen = NULL;
    1723             :         gint px, py;
    1724             :         GdkModifierType nMask;
    1725           0 :         gdk_display_get_pointer( getGdkDisplay(), &pScreen, &px, &py, &nMask );
    1726           0 :         if( !pScreen )
    1727           0 :             pScreen = gtk_widget_get_screen( m_pWindow );
    1728             : 
    1729             :         gint nMonitor;
    1730           0 :         nMonitor = gdk_screen_get_monitor_at_point( pScreen, px, py );
    1731             : 
    1732             :         GdkRectangle aMonitor;
    1733           0 :         gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aMonitor );
    1734             : 
    1735           0 :         nX = aMonitor.x + (aMonitor.width - (long)maGeometry.nWidth)/2;
    1736           0 :         nY = aMonitor.y + (aMonitor.height - (long)maGeometry.nHeight)/2;
    1737             :     }
    1738           0 :     SetPosSize( nX, nY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
    1739           0 : }
    1740             : 
    1741           0 : Size GtkSalFrame::calcDefaultSize()
    1742             : {
    1743           0 :     return bestmaxFrameSizeForScreenSize(getDisplay()->GetScreenSize(GetDisplayScreen()));
    1744             : }
    1745             : 
    1746           0 : void GtkSalFrame::SetDefaultSize()
    1747             : {
    1748           0 :     Size aDefSize = calcDefaultSize();
    1749             : 
    1750           0 :     SetPosSize( 0, 0, aDefSize.Width(), aDefSize.Height(),
    1751           0 :                 SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
    1752             : 
    1753           0 :     if( (m_nStyle & SAL_FRAME_STYLE_DEFAULT) && m_pWindow )
    1754           0 :         gtk_window_maximize( GTK_WINDOW(m_pWindow) );
    1755           0 : }
    1756             : 
    1757           0 : static void initClientId()
    1758             : {
    1759             : #if !GTK_CHECK_VERSION(3,0,0)
    1760             :     static bool bOnce = false;
    1761           0 :     if (!bOnce)
    1762             :     {
    1763           0 :         bOnce = true;
    1764           0 :         const OString& rID = SessionManagerClient::getSessionID();
    1765           0 :         if (!rID.isEmpty())
    1766           0 :             gdk_set_sm_client_id(rID.getStr());
    1767             :     }
    1768             : #else
    1769             :     // No session management support for gtk3+ - this is now legacy.
    1770             : #endif
    1771           0 : }
    1772             : 
    1773           0 : void GtkSalFrame::Show( bool bVisible, bool bNoActivate )
    1774             : {
    1775           0 :     if( m_pWindow )
    1776             :     {
    1777             : #if !GTK_CHECK_VERSION(3,0,0)
    1778           0 :         if( m_pParent && (m_pParent->m_nStyle & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN)
    1779           0 :             && getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
    1780           0 :             gtk_window_set_keep_above( GTK_WINDOW(m_pWindow), bVisible );
    1781             : #endif
    1782           0 :         if( bVisible )
    1783             :         {
    1784           0 :             initClientId();
    1785           0 :             getDisplay()->startupNotificationCompleted();
    1786             : 
    1787           0 :             if( m_bDefaultPos )
    1788           0 :                 Center();
    1789           0 :             if( m_bDefaultSize )
    1790           0 :                 SetDefaultSize();
    1791           0 :             setMinMaxSize();
    1792             : 
    1793             : #if !GTK_CHECK_VERSION(3,0,0)
    1794             :             // #i45160# switch to desktop where a dialog with parent will appear
    1795           0 :             if( m_pParent && m_pParent->m_nWorkArea != m_nWorkArea && IS_WIDGET_MAPPED(m_pParent->m_pWindow) )
    1796           0 :                 getDisplay()->getWMAdaptor()->switchToWorkArea( m_pParent->m_nWorkArea );
    1797             : #endif
    1798             : 
    1799           0 :             if( isFloatGrabWindow() &&
    1800           0 :                 m_pParent &&
    1801           0 :                 m_nFloats == 0 &&
    1802           0 :                 ! getDisplay()->GetCaptureFrame() )
    1803             :             {
    1804             :                 /* #i63086#
    1805             :                  * outsmart Metacity's "focus:mouse" mode
    1806             :                  * which insists on taking the focus from the document
    1807             :                  * to the new float. Grab focus to parent frame BEFORE
    1808             :                  * showing the float (cannot grab it to the float
    1809             :                  * before show).
    1810             :                  */
    1811           0 :                  m_pParent->grabPointer( true, true );
    1812             :             }
    1813             : 
    1814           0 :             guint32 nUserTime = 0;
    1815           0 :             if( ! bNoActivate && (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 )
    1816             :                 /* #i99360# ugly workaround an X11 library bug */
    1817           0 :                 nUserTime= getDisplay()->GetLastUserEventTime( true );
    1818             :                 //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
    1819             : 
    1820             :             //For these floating windows we don't want the main window to lose focus, and metacity has...
    1821             :             // metacity-2.24.0/src/core/window.c
    1822             : 
    1823             :             //  if ((focus_window != NULL) && XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time))
    1824             :             //      "compare" window focus prevented by other activity
    1825             : 
    1826             :             //  where "compare" is this window
    1827             : 
    1828             :             //  which leads to...
    1829             : 
    1830             :             // /* This happens for error dialogs or alerts; these need to remain on
    1831             :             // * top, but it would be confusing to have its ancestor remain
    1832             :             // * focused.
    1833             :             // */
    1834             :             // if (meta_window_is_ancestor_of_transient (focus_window, window))
    1835             :             //          "The focus window %s is an ancestor of the newly mapped "
    1836             :             //         "window %s which isn't being focused.  Unfocusing the "
    1837             :             //          "ancestor.\n",
    1838             : 
    1839             :             // i.e. having a time < that of the toplevel frame means that the toplevel frame gets unfocused.
    1840             :             // awesome.
    1841           0 :             if( nUserTime == 0 )
    1842             :             {
    1843             :                 /* #i99360# ugly workaround an X11 library bug */
    1844           0 :                 nUserTime= getDisplay()->GetLastUserEventTime( true );
    1845             :                 //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
    1846             :             }
    1847           0 :             lcl_set_user_time(GTK_WINDOW(m_pWindow), nUserTime );
    1848             : 
    1849           0 :             if( ! bNoActivate && (m_nStyle & SAL_FRAME_STYLE_TOOLWINDOW) )
    1850           0 :                 m_bSetFocusOnMap = true;
    1851             : 
    1852           0 :             gtk_widget_show( m_pWindow );
    1853             : 
    1854           0 :             if( isFloatGrabWindow() )
    1855             :             {
    1856           0 :                 m_nFloats++;
    1857           0 :                 if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 1 )
    1858           0 :                     grabPointer( true, true );
    1859             :                 // #i44068# reset parent's IM context
    1860           0 :                 if( m_pParent )
    1861           0 :                     m_pParent->EndExtTextInput(0);
    1862             :             }
    1863           0 :             if( m_bWindowIsGtkPlug )
    1864           0 :                 askForXEmbedFocus( 0 );
    1865             :         }
    1866             :         else
    1867             :         {
    1868           0 :             if( isFloatGrabWindow() )
    1869             :             {
    1870           0 :                 m_nFloats--;
    1871           0 :                 if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 0)
    1872           0 :                     grabPointer( false );
    1873             :             }
    1874           0 :             gtk_widget_hide( m_pWindow );
    1875           0 :             if( m_pIMHandler )
    1876           0 :                 m_pIMHandler->focusChanged( false );
    1877             :             // flush here; there may be a very seldom race between
    1878             :             // the display connection used for clipboard and our connection
    1879           0 :             Flush();
    1880             :         }
    1881           0 :         CallCallback( SALEVENT_RESIZE, NULL );
    1882             :     }
    1883           0 : }
    1884             : 
    1885           0 : void GtkSalFrame::setMinMaxSize()
    1886             : {
    1887             :     /*  #i34504# metacity (and possibly others) do not treat
    1888             :      *  _NET_WM_STATE_FULLSCREEN and max_width/height independently;
    1889             :      *  whether they should is undefined. So don't set the max size hint
    1890             :      *  for a full screen window.
    1891             :     */
    1892           0 :     if( m_pWindow && ! isChild() )
    1893             :     {
    1894             :         GdkGeometry aGeo;
    1895           0 :         int aHints = 0;
    1896           0 :         if( m_nStyle & SAL_FRAME_STYLE_SIZEABLE )
    1897             :         {
    1898           0 :             if( m_aMinSize.Width() && m_aMinSize.Height() && ! m_bFullscreen )
    1899             :             {
    1900           0 :                 aGeo.min_width  = m_aMinSize.Width();
    1901           0 :                 aGeo.min_height = m_aMinSize.Height();
    1902           0 :                 aHints |= GDK_HINT_MIN_SIZE;
    1903             :             }
    1904           0 :             if( m_aMaxSize.Width() && m_aMaxSize.Height() && ! m_bFullscreen )
    1905             :             {
    1906           0 :                 aGeo.max_width  = m_aMaxSize.Width();
    1907           0 :                 aGeo.max_height = m_aMaxSize.Height();
    1908           0 :                 aHints |= GDK_HINT_MAX_SIZE;
    1909             :             }
    1910             :         }
    1911             :         else
    1912             :         {
    1913           0 :             if( ! m_bFullscreen )
    1914             :             {
    1915           0 :                 aGeo.min_width = maGeometry.nWidth;
    1916           0 :                 aGeo.min_height = maGeometry.nHeight;
    1917           0 :                 aHints |= GDK_HINT_MIN_SIZE;
    1918             : 
    1919           0 :                 aGeo.max_width = maGeometry.nWidth;
    1920           0 :                 aGeo.max_height = maGeometry.nHeight;
    1921           0 :                 aHints |= GDK_HINT_MAX_SIZE;
    1922             :             }
    1923             :         }
    1924           0 :         if( m_bFullscreen && m_aMaxSize.Width() && m_aMaxSize.Height() )
    1925             :         {
    1926           0 :             aGeo.max_width = m_aMaxSize.Width();
    1927           0 :             aGeo.max_height = m_aMaxSize.Height();
    1928           0 :             aHints |= GDK_HINT_MAX_SIZE;
    1929             :         }
    1930           0 :         if( aHints )
    1931           0 :             gtk_window_set_geometry_hints( GTK_WINDOW(m_pWindow),
    1932             :                                            NULL,
    1933             :                                            &aGeo,
    1934           0 :                                            GdkWindowHints( aHints ) );
    1935             :     }
    1936           0 : }
    1937             : 
    1938           0 : void GtkSalFrame::SetMaxClientSize( long nWidth, long nHeight )
    1939             : {
    1940           0 :     if( ! isChild() )
    1941             :     {
    1942           0 :         m_aMaxSize = Size( nWidth, nHeight );
    1943             :         // Show does a setMinMaxSize
    1944           0 :         if( IS_WIDGET_MAPPED( m_pWindow ) )
    1945           0 :             setMinMaxSize();
    1946             :     }
    1947           0 : }
    1948           0 : void GtkSalFrame::SetMinClientSize( long nWidth, long nHeight )
    1949             : {
    1950           0 :     if( ! isChild() )
    1951             :     {
    1952           0 :         m_aMinSize = Size( nWidth, nHeight );
    1953           0 :         if( m_pWindow )
    1954             :         {
    1955           0 :             gtk_widget_set_size_request( m_pWindow, nWidth, nHeight );
    1956             :             // Show does a setMinMaxSize
    1957           0 :             if( IS_WIDGET_MAPPED( m_pWindow ) )
    1958           0 :                 setMinMaxSize();
    1959             :         }
    1960             :     }
    1961           0 : }
    1962             : 
    1963             : // FIXME: we should really be an SvpSalFrame sub-class, and
    1964             : // share their AllocateFrame !
    1965           0 : void GtkSalFrame::AllocateFrame()
    1966             : {
    1967             : #if GTK_CHECK_VERSION(3,0,0)
    1968             :     basegfx::B2IVector aFrameSize( maGeometry.nWidth, maGeometry.nHeight );
    1969             :     if( ! m_aFrame.get() || m_aFrame->getSize() != aFrameSize )
    1970             :     {
    1971             :         if( aFrameSize.getX() == 0 )
    1972             :             aFrameSize.setX( 1 );
    1973             :         if( aFrameSize.getY() == 0 )
    1974             :             aFrameSize.setY( 1 );
    1975             :         m_aFrame = basebmp::createBitmapDevice( aFrameSize, true,
    1976             :                                                 basebmp::FORMAT_TWENTYFOUR_BIT_TC_MASK );
    1977             :         m_aFrame->setDamageTracker(
    1978             :             basebmp::IBitmapDeviceDamageTrackerSharedPtr(new DamageTracker(*this)) );
    1979             :         fprintf( stderr, "allocated m_aFrame size of %dx%d \n",
    1980             :                  (int)maGeometry.nWidth, (int)maGeometry.nHeight );
    1981             : 
    1982             : #if OSL_DEBUG_LEVEL > 0 // set background to orange
    1983             :         m_aFrame->clear( basebmp::Color( 255, 127, 0 ) );
    1984             : #endif
    1985             : 
    1986             :         // update device in existing graphics
    1987             :         for( unsigned int i = 0; i < SAL_N_ELEMENTS( m_aGraphics ); ++i )
    1988             :         {
    1989             :             if( !m_aGraphics[i].pGraphics )
    1990             :                 continue;
    1991             :             m_aGraphics[i].pGraphics->setDevice( m_aFrame );
    1992             :         }
    1993             :     }
    1994             : #endif
    1995           0 : }
    1996             : 
    1997           0 : void GtkSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
    1998             : {
    1999           0 :     if( !m_pWindow || isChild( true, false ) )
    2000           0 :         return;
    2001             : 
    2002           0 :     bool bSized = false, bMoved = false;
    2003             : 
    2004           0 :     if( (nFlags & ( SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT )) &&
    2005           0 :         (nWidth > 0 && nHeight > 0 ) // sometimes stupid things happen
    2006             :             )
    2007             :     {
    2008           0 :         m_bDefaultSize = false;
    2009             : 
    2010           0 :         if( (unsigned long)nWidth != maGeometry.nWidth || (unsigned long)nHeight != maGeometry.nHeight )
    2011           0 :             bSized = true;
    2012           0 :         maGeometry.nWidth   = nWidth;
    2013           0 :         maGeometry.nHeight  = nHeight;
    2014             : 
    2015           0 :         if( isChild( false, true ) )
    2016           0 :             gtk_widget_set_size_request( m_pWindow, nWidth, nHeight );
    2017           0 :         else if( ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) )
    2018           0 :             gtk_window_resize( GTK_WINDOW(m_pWindow), nWidth, nHeight );
    2019           0 :         setMinMaxSize();
    2020             :     }
    2021           0 :     else if( m_bDefaultSize )
    2022           0 :         SetDefaultSize();
    2023             : 
    2024           0 :     m_bDefaultSize = false;
    2025             : 
    2026           0 :     if( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) )
    2027             :     {
    2028           0 :         if( m_pParent )
    2029             :         {
    2030           0 :             if( Application::GetSettings().GetLayoutRTL() )
    2031           0 :                 nX = m_pParent->maGeometry.nWidth-maGeometry.nWidth-1-nX;
    2032           0 :             nX += m_pParent->maGeometry.nX;
    2033           0 :             nY += m_pParent->maGeometry.nY;
    2034             :         }
    2035             : 
    2036             : #if GTK_CHECK_VERSION(3,0,0)
    2037             :         // adjust position to avoid off screen windows
    2038             :         // but allow toolbars to be positioned partly off screen by the user
    2039             :         Size aScreenSize = getDisplay()->GetScreenSize( GetDisplayScreen() );
    2040             :         if( ! (m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
    2041             :         {
    2042             :             if( nX < (long)maGeometry.nLeftDecoration )
    2043             :                 nX = maGeometry.nLeftDecoration;
    2044             :             if( nY < (long)maGeometry.nTopDecoration )
    2045             :                 nY = maGeometry.nTopDecoration;
    2046             :             if( (nX + (long)maGeometry.nWidth + (long)maGeometry.nRightDecoration) > (long)aScreenSize.Width() )
    2047             :                 nX = aScreenSize.Width() - maGeometry.nWidth - maGeometry.nRightDecoration;
    2048             :             if( (nY + (long)maGeometry.nHeight + (long)maGeometry.nBottomDecoration) > (long)aScreenSize.Height() )
    2049             :                 nY = aScreenSize.Height() - maGeometry.nHeight - maGeometry.nBottomDecoration;
    2050             :         }
    2051             :         else
    2052             :         {
    2053             :             if( nX + (long)maGeometry.nWidth < 10 )
    2054             :                 nX = 10 - (long)maGeometry.nWidth;
    2055             :             if( nY + (long)maGeometry.nHeight < 10 )
    2056             :                 nY = 10 - (long)maGeometry.nHeight;
    2057             :             if( nX > (long)aScreenSize.Width() - 10 )
    2058             :                 nX = (long)aScreenSize.Width() - 10;
    2059             :             if( nY > (long)aScreenSize.Height() - 10 )
    2060             :                 nY = (long)aScreenSize.Height() - 10;
    2061             :         }
    2062             : #endif
    2063             : 
    2064           0 :         if( nX != maGeometry.nX || nY != maGeometry.nY )
    2065           0 :             bMoved = true;
    2066           0 :         maGeometry.nX = nX;
    2067           0 :         maGeometry.nY = nY;
    2068             : 
    2069           0 :         m_bDefaultPos = false;
    2070             : 
    2071           0 :         moveWindow( maGeometry.nX, maGeometry.nY );
    2072             : 
    2073           0 :         updateScreenNumber();
    2074             :     }
    2075           0 :     else if( m_bDefaultPos )
    2076           0 :         Center();
    2077             : 
    2078           0 :     m_bDefaultPos = false;
    2079             : 
    2080           0 :     if( bSized )
    2081           0 :         AllocateFrame();
    2082             : 
    2083           0 :     if( bSized && ! bMoved )
    2084           0 :         CallCallback( SALEVENT_RESIZE, NULL );
    2085           0 :     else if( bMoved && ! bSized )
    2086           0 :         CallCallback( SALEVENT_MOVE, NULL );
    2087           0 :     else if( bMoved && bSized )
    2088           0 :         CallCallback( SALEVENT_MOVERESIZE, NULL );
    2089             : }
    2090             : 
    2091           0 : void GtkSalFrame::GetClientSize( long& rWidth, long& rHeight )
    2092             : {
    2093           0 :     if( m_pWindow && !(m_nState & GDK_WINDOW_STATE_ICONIFIED) )
    2094             :     {
    2095           0 :         rWidth = maGeometry.nWidth;
    2096           0 :         rHeight = maGeometry.nHeight;
    2097             :     }
    2098             :     else
    2099           0 :         rWidth = rHeight = 0;
    2100           0 : }
    2101             : 
    2102           0 : void GtkSalFrame::GetWorkArea( Rectangle& rRect )
    2103             : {
    2104             : #if !GTK_CHECK_VERSION(3,0,0)
    2105           0 :     rRect = GetGtkSalData()->GetGtkDisplay()->getWMAdaptor()->getWorkArea( 0 );
    2106             : #else
    2107             :     g_warning ("no get work area");
    2108             :     rRect = Rectangle( 0, 0, 1024, 768 );
    2109             : #endif
    2110           0 : }
    2111             : 
    2112           0 : SalFrame* GtkSalFrame::GetParent() const
    2113             : {
    2114           0 :     return m_pParent;
    2115             : }
    2116             : 
    2117           0 : void GtkSalFrame::SetWindowState( const SalFrameState* pState )
    2118             : {
    2119           0 :     if( ! m_pWindow || ! pState || isChild( true, false ) )
    2120           0 :         return;
    2121             : 
    2122             :     const sal_uLong nMaxGeometryMask =
    2123             :         WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y |
    2124             :         WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT |
    2125             :         WINDOWSTATE_MASK_MAXIMIZED_X | WINDOWSTATE_MASK_MAXIMIZED_Y |
    2126           0 :         WINDOWSTATE_MASK_MAXIMIZED_WIDTH | WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
    2127             : 
    2128           0 :     if( (pState->mnMask & WINDOWSTATE_MASK_STATE) &&
    2129           0 :         ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) &&
    2130           0 :         (pState->mnState & WINDOWSTATE_STATE_MAXIMIZED) &&
    2131           0 :         (pState->mnMask & nMaxGeometryMask) == nMaxGeometryMask )
    2132             :     {
    2133           0 :         resizeWindow( pState->mnWidth, pState->mnHeight );
    2134           0 :         moveWindow( pState->mnX, pState->mnY );
    2135           0 :         m_bDefaultPos = m_bDefaultSize = false;
    2136             : 
    2137           0 :         maGeometry.nX       = pState->mnMaximizedX;
    2138           0 :         maGeometry.nY       = pState->mnMaximizedY;
    2139           0 :         maGeometry.nWidth   = pState->mnMaximizedWidth;
    2140           0 :         maGeometry.nHeight  = pState->mnMaximizedHeight;
    2141           0 :         updateScreenNumber();
    2142           0 :         AllocateFrame();
    2143             : 
    2144           0 :         m_nState = GdkWindowState( m_nState | GDK_WINDOW_STATE_MAXIMIZED );
    2145             :         m_aRestorePosSize = Rectangle( Point( pState->mnX, pState->mnY ),
    2146           0 :                                        Size( pState->mnWidth, pState->mnHeight ) );
    2147           0 :         CallCallback( SALEVENT_RESIZE, NULL );
    2148             :     }
    2149           0 :     else if( pState->mnMask & (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y |
    2150             :                                WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT ) )
    2151             :     {
    2152           0 :         sal_uInt16 nPosSizeFlags = 0;
    2153           0 :         long nX         = pState->mnX - (m_pParent ? m_pParent->maGeometry.nX : 0);
    2154           0 :         long nY         = pState->mnY - (m_pParent ? m_pParent->maGeometry.nY : 0);
    2155           0 :         if( pState->mnMask & WINDOWSTATE_MASK_X )
    2156           0 :             nPosSizeFlags |= SAL_FRAME_POSSIZE_X;
    2157             :         else
    2158           0 :             nX = maGeometry.nX - (m_pParent ? m_pParent->maGeometry.nX : 0);
    2159           0 :         if( pState->mnMask & WINDOWSTATE_MASK_Y )
    2160           0 :             nPosSizeFlags |= SAL_FRAME_POSSIZE_Y;
    2161             :         else
    2162           0 :             nY = maGeometry.nY - (m_pParent ? m_pParent->maGeometry.nY : 0);
    2163           0 :         if( pState->mnMask & WINDOWSTATE_MASK_WIDTH )
    2164           0 :             nPosSizeFlags |= SAL_FRAME_POSSIZE_WIDTH;
    2165           0 :         if( pState->mnMask & WINDOWSTATE_MASK_HEIGHT )
    2166           0 :             nPosSizeFlags |= SAL_FRAME_POSSIZE_HEIGHT;
    2167           0 :         SetPosSize( nX, nY, pState->mnWidth, pState->mnHeight, nPosSizeFlags );
    2168             :     }
    2169           0 :     if( pState->mnMask & WINDOWSTATE_MASK_STATE && ! isChild() )
    2170             :     {
    2171           0 :         if( pState->mnState & WINDOWSTATE_STATE_MAXIMIZED )
    2172           0 :             gtk_window_maximize( GTK_WINDOW(m_pWindow) );
    2173             :         else
    2174           0 :             gtk_window_unmaximize( GTK_WINDOW(m_pWindow) );
    2175             :         /* #i42379# there is no rollup state in GDK; and rolled up windows are
    2176             :         *  (probably depending on the WM) reported as iconified. If we iconify a
    2177             :         *  window here that was e.g. a dialog, then it will be unmapped but still
    2178             :         *  not be displayed in the task list, so it's an iconified window that
    2179             :         *  the user cannot get out of this state. So do not set the iconified state
    2180             :         *  on windows with a parent (that is transient frames) since these tend
    2181             :         *  to not be represented in an icon task list.
    2182             :         */
    2183           0 :         if( (pState->mnState & WINDOWSTATE_STATE_MINIMIZED)
    2184           0 :             && ! m_pParent )
    2185           0 :             gtk_window_iconify( GTK_WINDOW(m_pWindow) );
    2186             :         else
    2187           0 :             gtk_window_deiconify( GTK_WINDOW(m_pWindow) );
    2188             :     }
    2189             : }
    2190             : 
    2191           0 : bool GtkSalFrame::GetWindowState( SalFrameState* pState )
    2192             : {
    2193           0 :     pState->mnState = WINDOWSTATE_STATE_NORMAL;
    2194           0 :     pState->mnMask  = WINDOWSTATE_MASK_STATE;
    2195             :     // rollup ? gtk 2.2 does not seem to support the shaded state
    2196           0 :     if( (m_nState & GDK_WINDOW_STATE_ICONIFIED) )
    2197           0 :         pState->mnState |= WINDOWSTATE_STATE_MINIMIZED;
    2198           0 :     if( m_nState & GDK_WINDOW_STATE_MAXIMIZED )
    2199             :     {
    2200           0 :         pState->mnState |= WINDOWSTATE_STATE_MAXIMIZED;
    2201           0 :         pState->mnX                 = m_aRestorePosSize.Left();
    2202           0 :         pState->mnY                 = m_aRestorePosSize.Top();
    2203           0 :         pState->mnWidth             = m_aRestorePosSize.GetWidth();
    2204           0 :         pState->mnHeight            = m_aRestorePosSize.GetHeight();
    2205           0 :         pState->mnMaximizedX        = maGeometry.nX;
    2206           0 :         pState->mnMaximizedY        = maGeometry.nY;
    2207           0 :         pState->mnMaximizedWidth    = maGeometry.nWidth;
    2208           0 :         pState->mnMaximizedHeight   = maGeometry.nHeight;
    2209             :         pState->mnMask  |= WINDOWSTATE_MASK_MAXIMIZED_X          |
    2210             :                            WINDOWSTATE_MASK_MAXIMIZED_Y          |
    2211             :                            WINDOWSTATE_MASK_MAXIMIZED_WIDTH      |
    2212           0 :                            WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
    2213             :     }
    2214             :     else
    2215             :     {
    2216           0 :         pState->mnX         = maGeometry.nX;
    2217           0 :         pState->mnY         = maGeometry.nY;
    2218           0 :         pState->mnWidth     = maGeometry.nWidth;
    2219           0 :         pState->mnHeight    = maGeometry.nHeight;
    2220             :     }
    2221             :     pState->mnMask  |= WINDOWSTATE_MASK_X            |
    2222             :                        WINDOWSTATE_MASK_Y            |
    2223             :                        WINDOWSTATE_MASK_WIDTH        |
    2224           0 :                        WINDOWSTATE_MASK_HEIGHT;
    2225             : 
    2226           0 :     return true;
    2227             : }
    2228             : 
    2229             : typedef enum {
    2230             :     SET_RETAIN_SIZE,
    2231             :     SET_FULLSCREEN,
    2232             :     SET_UN_FULLSCREEN
    2233             : } SetType;
    2234             : 
    2235           0 : void GtkSalFrame::SetScreen( unsigned int nNewScreen, int eType, Rectangle *pSize )
    2236             : {
    2237           0 :     if( !m_pWindow )
    2238           0 :         return;
    2239             : 
    2240           0 :     if (maGeometry.nDisplayScreenNumber == nNewScreen && eType == SET_RETAIN_SIZE)
    2241           0 :         return;
    2242             : 
    2243           0 :     GdkScreen *pScreen = NULL;
    2244             :     GdkRectangle aNewMonitor;
    2245             : 
    2246           0 :     bool bSpanAllScreens = nNewScreen == (unsigned int)-1;
    2247           0 :     m_bSpanMonitorsWhenFullscreen = bSpanAllScreens && getDisplay()->getSystem()->GetDisplayScreenCount() > 1;
    2248             : 
    2249           0 :     if (m_bSpanMonitorsWhenFullscreen)   //span all screens
    2250             :     {
    2251           0 :         pScreen = gtk_widget_get_screen( m_pWindow );
    2252           0 :         aNewMonitor.x = 0;
    2253           0 :         aNewMonitor.y = 0;
    2254           0 :         aNewMonitor.width = gdk_screen_get_width(pScreen);
    2255           0 :         aNewMonitor.height = gdk_screen_get_height(pScreen);
    2256             :     }
    2257             :     else
    2258             :     {
    2259             :         gint nMonitor;
    2260           0 :         bool bSameMonitor = false;
    2261             : 
    2262           0 :         if (!bSpanAllScreens)
    2263             :         {
    2264           0 :             pScreen = getDisplay()->getSystem()->getScreenMonitorFromIdx( nNewScreen, nMonitor );
    2265           0 :             if (!pScreen)
    2266             :             {
    2267             :                 g_warning ("Attempt to move GtkSalFrame to invalid screen %d => "
    2268           0 :                            "fallback to current\n", nNewScreen);
    2269             :             }
    2270             :         }
    2271             : 
    2272           0 :         if (!pScreen)
    2273             :         {
    2274           0 :             pScreen = gtk_widget_get_screen( m_pWindow );
    2275           0 :             bSameMonitor = true;
    2276             :         }
    2277             : 
    2278             :         // Heavy lifting, need to move screen ...
    2279           0 :         if( pScreen != gtk_widget_get_screen( m_pWindow ))
    2280           0 :             gtk_window_set_screen( GTK_WINDOW( m_pWindow ), pScreen );
    2281             : 
    2282             :         gint nOldMonitor = gdk_screen_get_monitor_at_window(
    2283           0 :                                 pScreen, widget_get_window( m_pWindow ) );
    2284           0 :         if (bSameMonitor)
    2285           0 :             nMonitor = nOldMonitor;
    2286             : 
    2287             :     #if OSL_DEBUG_LEVEL > 1
    2288             :         if( nMonitor == nOldMonitor )
    2289             :             g_warning( "An apparently pointless SetScreen - should we elide it ?" );
    2290             :     #endif
    2291             : 
    2292             :         GdkRectangle aOldMonitor;
    2293           0 :         gdk_screen_get_monitor_geometry( pScreen, nOldMonitor, &aOldMonitor );
    2294           0 :         gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aNewMonitor );
    2295             : 
    2296           0 :         maGeometry.nX = aNewMonitor.x + maGeometry.nX - aOldMonitor.x;
    2297           0 :         maGeometry.nY = aNewMonitor.y + maGeometry.nY - aOldMonitor.y;
    2298             :     }
    2299             : 
    2300           0 :     bool bResize = false;
    2301           0 :     bool bVisible = IS_WIDGET_MAPPED( m_pWindow );
    2302           0 :     if( bVisible )
    2303           0 :         Show( false );
    2304             : 
    2305           0 :     if( eType == SET_FULLSCREEN )
    2306             :     {
    2307           0 :         maGeometry.nX = aNewMonitor.x;
    2308           0 :         maGeometry.nY = aNewMonitor.y;
    2309           0 :         maGeometry.nWidth = aNewMonitor.width;
    2310           0 :         maGeometry.nHeight = aNewMonitor.height;
    2311           0 :         m_nStyle |= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
    2312           0 :         bResize = true;
    2313             : 
    2314             :         // #i110881# for the benefit of compiz set a max size here
    2315             :         // else setting to fullscreen fails for unknown reasons
    2316           0 :         m_aMaxSize.Width() = aNewMonitor.width;
    2317           0 :         m_aMaxSize.Height() = aNewMonitor.height;
    2318             :     }
    2319             : 
    2320           0 :     if( pSize && eType == SET_UN_FULLSCREEN )
    2321             :     {
    2322           0 :         maGeometry.nX = pSize->Left();
    2323           0 :         maGeometry.nY = pSize->Top();
    2324           0 :         maGeometry.nWidth = pSize->GetWidth();
    2325           0 :         maGeometry.nHeight = pSize->GetHeight();
    2326           0 :         m_nStyle &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
    2327           0 :         bResize = true;
    2328             :     }
    2329             : 
    2330           0 :     if (bResize)
    2331             :     {
    2332             :         // temporarily re-sizeable
    2333           0 :         if( !(m_nStyle & SAL_FRAME_STYLE_SIZEABLE) )
    2334           0 :             gtk_window_set_resizable( GTK_WINDOW(m_pWindow), TRUE );
    2335           0 :         gtk_window_resize( GTK_WINDOW( m_pWindow ), maGeometry.nWidth, maGeometry.nHeight );
    2336             :     }
    2337             : 
    2338           0 :     gtk_window_move( GTK_WINDOW( m_pWindow ), maGeometry.nX, maGeometry.nY );
    2339             : 
    2340             : #if !GTK_CHECK_VERSION(3,0,0)
    2341             :     // _NET_WM_STATE_FULLSCREEN (Metacity <-> KWin)
    2342           0 :    if( ! getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
    2343             : #endif
    2344             :     {
    2345             : #if GTK_CHECK_VERSION(3,8,0)
    2346             :         gdk_window_set_fullscreen_mode( widget_get_window(m_pWindow), m_bSpanMonitorsWhenFullscreen
    2347             :             ? GDK_FULLSCREEN_ON_ALL_MONITORS : GDK_FULLSCREEN_ON_CURRENT_MONITOR );
    2348             : #endif
    2349           0 :         if( eType == SET_FULLSCREEN )
    2350           0 :             gtk_window_fullscreen( GTK_WINDOW( m_pWindow ) );
    2351           0 :         else if( eType == SET_UN_FULLSCREEN )
    2352           0 :             gtk_window_unfullscreen( GTK_WINDOW( m_pWindow ) );
    2353             :     }
    2354             : 
    2355           0 :     if( eType == SET_UN_FULLSCREEN &&
    2356           0 :         !(m_nStyle & SAL_FRAME_STYLE_SIZEABLE) )
    2357           0 :         gtk_window_set_resizable( GTK_WINDOW( m_pWindow ), FALSE );
    2358             : 
    2359             :     // FIXME: we should really let gtk+ handle our widget hierarchy ...
    2360           0 :     if( m_pParent && gtk_widget_get_screen( m_pParent->m_pWindow ) != pScreen )
    2361           0 :         SetParent( NULL );
    2362           0 :     std::list< GtkSalFrame* > aChildren = m_aChildren;
    2363           0 :     for( std::list< GtkSalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it )
    2364           0 :         (*it)->SetScreen( nNewScreen, SET_RETAIN_SIZE );
    2365             : 
    2366           0 :     m_bDefaultPos = m_bDefaultSize = false;
    2367           0 :     updateScreenNumber();
    2368           0 :     CallCallback( SALEVENT_MOVERESIZE, NULL );
    2369             : 
    2370           0 :     if( bVisible )
    2371           0 :         Show( true );
    2372             : }
    2373             : 
    2374           0 : void GtkSalFrame::SetScreenNumber( unsigned int nNewScreen )
    2375             : {
    2376           0 :     SetScreen( nNewScreen, SET_RETAIN_SIZE );
    2377           0 : }
    2378             : 
    2379           0 : void GtkSalFrame::updateWMClass()
    2380             : {
    2381           0 :     OString aResClass = OUStringToOString(m_sWMClass, RTL_TEXTENCODING_ASCII_US);
    2382           0 :     const char *pResClass = !aResClass.isEmpty() ? aResClass.getStr() :
    2383           0 :                                                     SalGenericSystem::getFrameClassName();
    2384             :     Display *display;
    2385             : 
    2386           0 :     if (!getDisplay()->IsX11Display())
    2387           0 :         return;
    2388             : 
    2389             : #if GTK_CHECK_VERSION(3,0,0)
    2390             :     display = GDK_DISPLAY_XDISPLAY(getGdkDisplay());
    2391             : #else
    2392           0 :     display = getDisplay()->GetDisplay();
    2393             : #endif
    2394             : 
    2395           0 :     if( IS_WIDGET_REALIZED( m_pWindow ) )
    2396             :     {
    2397           0 :         XClassHint* pClass = XAllocClassHint();
    2398           0 :         OString aResName = SalGenericSystem::getFrameResName();
    2399           0 :         pClass->res_name  = const_cast<char*>(aResName.getStr());
    2400           0 :         pClass->res_class = const_cast<char*>(pResClass);
    2401             :         XSetClassHint( display,
    2402             :                        widget_get_xid(m_pWindow),
    2403           0 :                        pClass );
    2404           0 :         XFree( pClass );
    2405           0 :     }
    2406             : }
    2407             : 
    2408           0 : void GtkSalFrame::SetApplicationID( const OUString &rWMClass )
    2409             : {
    2410           0 :     if( rWMClass != m_sWMClass && ! isChild() )
    2411             :     {
    2412           0 :         m_sWMClass = rWMClass;
    2413           0 :         updateWMClass();
    2414             : 
    2415           0 :         for( std::list< GtkSalFrame* >::iterator it = m_aChildren.begin(); it != m_aChildren.end(); ++it )
    2416           0 :             (*it)->SetApplicationID(rWMClass);
    2417             :     }
    2418           0 : }
    2419             : 
    2420           0 : void GtkSalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nScreen )
    2421             : {
    2422           0 :     m_bFullscreen = bFullScreen;
    2423             : 
    2424           0 :     if( !m_pWindow || isChild() )
    2425           0 :         return;
    2426             : 
    2427           0 :     if( bFullScreen )
    2428             :     {
    2429             :         m_aRestorePosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
    2430           0 :                                        Size( maGeometry.nWidth, maGeometry.nHeight ) );
    2431           0 :         SetScreen( nScreen, SET_FULLSCREEN );
    2432             :     }
    2433             :     else
    2434             :     {
    2435             :         SetScreen( nScreen, SET_UN_FULLSCREEN,
    2436           0 :                    !m_aRestorePosSize.IsEmpty() ? &m_aRestorePosSize : NULL );
    2437           0 :         m_aRestorePosSize = Rectangle();
    2438             :     }
    2439             : }
    2440             : 
    2441             : /* definitions from xautolock.c (pl15) */
    2442             : #define XAUTOLOCK_DISABLE 1
    2443             : #define XAUTOLOCK_ENABLE  2
    2444             : 
    2445           0 : void GtkSalFrame::setAutoLock( bool bLock )
    2446             : {
    2447           0 :     if( isChild() || !getDisplay()->IsX11Display() )
    2448           0 :         return;
    2449             : 
    2450           0 :     GdkScreen  *pScreen = gtk_window_get_screen( GTK_WINDOW(m_pWindow) );
    2451           0 :     GdkDisplay *pDisplay = gdk_screen_get_display( pScreen );
    2452           0 :     GdkWindow  *pRootWin = gdk_screen_get_root_window( pScreen );
    2453             : 
    2454             :     Atom nAtom = XInternAtom( GDK_DISPLAY_XDISPLAY( pDisplay ),
    2455           0 :                               "XAUTOLOCK_MESSAGE", False );
    2456             : 
    2457           0 :     int nMessage = bLock ? XAUTOLOCK_ENABLE : XAUTOLOCK_DISABLE;
    2458             : 
    2459             :     XChangeProperty( GDK_DISPLAY_XDISPLAY( pDisplay ),
    2460             :                      GDK_WINDOW_XID( pRootWin ),
    2461             :                      nAtom, XA_INTEGER,
    2462             :                      8, PropModeReplace,
    2463             :                      (unsigned char*)&nMessage,
    2464           0 :                      sizeof( nMessage ) );
    2465             : }
    2466             : 
    2467             : #ifdef ENABLE_DBUS
    2468             : /** cookie is returned as an unsigned integer */
    2469             : static guint
    2470           0 : dbus_inhibit_gsm (const gchar *appname,
    2471             :                   const gchar *reason,
    2472             :                   guint xid)
    2473             : {
    2474             :         gboolean         res;
    2475             :         guint            cookie;
    2476           0 :         GError          *error = NULL;
    2477           0 :         DBusGProxy      *proxy = NULL;
    2478             : 
    2479             :         /* get the DBUS session connection */
    2480           0 :         DBusGConnection *session_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
    2481           0 :         if (error != NULL) {
    2482           0 :                 g_debug ("DBUS cannot connect : %s", error->message);
    2483           0 :                 g_error_free (error);
    2484           0 :                 return -1;
    2485             :         }
    2486             : 
    2487             :         /* get the proxy with gnome-session-manager */
    2488             :         proxy = dbus_g_proxy_new_for_name (session_connection,
    2489             :                                            GSM_DBUS_SERVICE,
    2490             :                                            GSM_DBUS_PATH,
    2491           0 :                                            GSM_DBUS_INTERFACE);
    2492           0 :         if (proxy == NULL) {
    2493           0 :                 g_debug ("Could not get DBUS proxy: %s", GSM_DBUS_SERVICE);
    2494           0 :                 return -1;
    2495             :         }
    2496             : 
    2497             :         res = dbus_g_proxy_call (proxy,
    2498             :                                  "Inhibit", &error,
    2499             :                                  G_TYPE_STRING, appname,
    2500             :                                  G_TYPE_UINT, xid,
    2501             :                                  G_TYPE_STRING, reason,
    2502             :                                  G_TYPE_UINT, 8, //Inhibit the session being marked as idle
    2503             :                                  G_TYPE_INVALID,
    2504             :                                  G_TYPE_UINT, &cookie,
    2505           0 :                                  G_TYPE_INVALID);
    2506             : 
    2507             :         /* check the return value */
    2508           0 :         if (! res) {
    2509           0 :                 cookie = -1;
    2510           0 :                 g_debug ("Inhibit method failed");
    2511             :         }
    2512             : 
    2513             :         /* check the error value */
    2514           0 :         if (error != NULL) {
    2515           0 :                 g_debug ("Inhibit problem : %s", error->message);
    2516           0 :                 g_error_free (error);
    2517           0 :                 cookie = -1;
    2518             :         }
    2519             : 
    2520           0 :         g_object_unref (G_OBJECT (proxy));
    2521           0 :         return cookie;
    2522             : }
    2523             : 
    2524             : static void
    2525           0 : dbus_uninhibit_gsm (guint cookie)
    2526             : {
    2527             :         gboolean         res;
    2528           0 :         GError          *error = NULL;
    2529           0 :         DBusGProxy      *proxy = NULL;
    2530           0 :         DBusGConnection *session_connection = NULL;
    2531             : 
    2532           0 :         if (cookie == guint(-1)) {
    2533           0 :                 g_debug ("Invalid cookie");
    2534           0 :                 return;
    2535             :         }
    2536             : 
    2537             :         /* get the DBUS session connection */
    2538           0 :         session_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
    2539           0 :         if (error) {
    2540           0 :                 g_debug ("DBUS cannot connect : %s", error->message);
    2541           0 :                 g_error_free (error);
    2542           0 :                 return;
    2543             :         }
    2544             : 
    2545             :         /* get the proxy with gnome-session-manager */
    2546             :         proxy = dbus_g_proxy_new_for_name (session_connection,
    2547             :                                            GSM_DBUS_SERVICE,
    2548             :                                            GSM_DBUS_PATH,
    2549           0 :                                            GSM_DBUS_INTERFACE);
    2550           0 :         if (proxy == NULL) {
    2551           0 :                 g_debug ("Could not get DBUS proxy: %s", GSM_DBUS_SERVICE);
    2552           0 :                 return;
    2553             :         }
    2554             : 
    2555             :         res = dbus_g_proxy_call (proxy,
    2556             :                                  "Uninhibit",
    2557             :                                  &error,
    2558             :                                  G_TYPE_UINT, cookie,
    2559             :                                  G_TYPE_INVALID,
    2560           0 :                                  G_TYPE_INVALID);
    2561             : 
    2562             :         /* check the return value */
    2563           0 :         if (! res) {
    2564           0 :                 g_debug ("Uninhibit method failed");
    2565             :         }
    2566             : 
    2567             :         /* check the error value */
    2568           0 :         if (error != NULL) {
    2569           0 :                 g_debug ("Uninhibit problem : %s", error->message);
    2570           0 :                 g_error_free (error);
    2571           0 :                 cookie = -1;
    2572             :         }
    2573           0 :         g_object_unref (G_OBJECT (proxy));
    2574             : }
    2575             : #endif
    2576             : 
    2577           0 : void GtkSalFrame::StartPresentation( bool bStart )
    2578             : {
    2579           0 :     setAutoLock( !bStart );
    2580             : 
    2581           0 :     if( !getDisplay()->IsX11Display() )
    2582           0 :         return;
    2583             : 
    2584             : #if !GTK_CHECK_VERSION(3,0,0)
    2585           0 :     Display *pDisplay = GDK_DISPLAY_XDISPLAY( getGdkDisplay() );
    2586             : 
    2587             :     int nTimeout, nInterval, bPreferBlanking, bAllowExposures;
    2588             :     XGetScreenSaver( pDisplay, &nTimeout, &nInterval,
    2589           0 :                      &bPreferBlanking, &bAllowExposures );
    2590             : #endif
    2591           0 :     if( bStart )
    2592             :     {
    2593             : #if !GTK_CHECK_VERSION(3,0,0)
    2594           0 :         if ( nTimeout )
    2595             :         {
    2596           0 :             m_nSavedScreenSaverTimeout = nTimeout;
    2597           0 :             XResetScreenSaver( pDisplay );
    2598             :             XSetScreenSaver( pDisplay, 0, nInterval,
    2599           0 :                              bPreferBlanking, bAllowExposures );
    2600             :         }
    2601             : #endif
    2602             : #ifdef ENABLE_DBUS
    2603             :         m_nGSMCookie = dbus_inhibit_gsm(g_get_application_name(), "presentation",
    2604           0 :                     widget_get_xid(m_pWindow));
    2605             : #endif
    2606             :     }
    2607             :     else
    2608             :     {
    2609             : #if !GTK_CHECK_VERSION(3,0,0)
    2610           0 :         if( m_nSavedScreenSaverTimeout )
    2611             :             XSetScreenSaver( pDisplay, m_nSavedScreenSaverTimeout,
    2612             :                              nInterval, bPreferBlanking,
    2613           0 :                              bAllowExposures );
    2614             : #endif
    2615           0 :         m_nSavedScreenSaverTimeout = 0;
    2616             : #ifdef ENABLE_DBUS
    2617           0 :         dbus_uninhibit_gsm(m_nGSMCookie);
    2618             : #endif
    2619             :     }
    2620             : }
    2621             : 
    2622           0 : void GtkSalFrame::SetAlwaysOnTop( bool bOnTop )
    2623             : {
    2624           0 :     if( m_pWindow )
    2625           0 :         gtk_window_set_keep_above( GTK_WINDOW( m_pWindow ), bOnTop );
    2626           0 : }
    2627             : 
    2628           0 : void GtkSalFrame::ToTop( sal_uInt16 nFlags )
    2629             : {
    2630           0 :     if( m_pWindow )
    2631             :     {
    2632           0 :         if( isChild( false, true ) )
    2633           0 :             gtk_widget_grab_focus( m_pWindow );
    2634           0 :         else if( IS_WIDGET_MAPPED( m_pWindow ) )
    2635             :         {
    2636           0 :             if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) )
    2637           0 :                 gtk_window_present( GTK_WINDOW(m_pWindow) );
    2638             :             else
    2639             :             {
    2640             :                 /* #i99360# ugly workaround an X11 library bug */
    2641           0 :                 guint32 nUserTime= getDisplay()->GetLastUserEventTime( true );
    2642           0 :                 gdk_window_focus( widget_get_window(m_pWindow), nUserTime );
    2643             :             }
    2644             : #if !GTK_CHECK_VERSION(3,0,0)
    2645             :             /*  need to do an XSetInputFocus here because
    2646             :              *  gdk_window_focus will ask a EWMH compliant WM to put the focus
    2647             :              *  to our window - which it of course won't since our input hint
    2648             :              *  is set to false.
    2649             :              */
    2650           0 :             if( (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_FLOAT_FOCUSABLE)) )
    2651             :             {
    2652             :                 // sad but true: this can cause an XError, we need to catch that
    2653             :                 // to do this we need to synchronize with the XServer
    2654           0 :                 GetGenericData()->ErrorTrapPush();
    2655           0 :                 XSetInputFocus( getDisplay()->GetDisplay(), widget_get_xid(m_pWindow), RevertToParent, CurrentTime );
    2656             :                 // fdo#46687 - an XSync should not be necessary - but for some reason it is.
    2657           0 :                 XSync( getDisplay()->GetDisplay(), False );
    2658           0 :                 GetGenericData()->ErrorTrapPop();
    2659             :             }
    2660             : #endif
    2661             :         }
    2662             :         else
    2663             :         {
    2664           0 :             if( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
    2665           0 :                 gtk_window_present( GTK_WINDOW(m_pWindow) );
    2666             :         }
    2667             :     }
    2668           0 : }
    2669             : 
    2670           0 : void GtkSalFrame::SetPointer( PointerStyle ePointerStyle )
    2671             : {
    2672           0 :     if( m_pWindow && ePointerStyle != m_ePointerStyle )
    2673             :     {
    2674           0 :         m_ePointerStyle = ePointerStyle;
    2675           0 :         GdkCursor *pCursor = getDisplay()->getCursor( ePointerStyle );
    2676           0 :         gdk_window_set_cursor( widget_get_window(m_pWindow), pCursor );
    2677           0 :         m_pCurrentCursor = pCursor;
    2678             : 
    2679             :         // #i80791# use grabPointer the same way as CaptureMouse, respective float grab
    2680           0 :         if( getDisplay()->MouseCaptured( this ) )
    2681           0 :             grabPointer( true, false );
    2682           0 :         else if( m_nFloats > 0 )
    2683           0 :             grabPointer( true, true );
    2684             :     }
    2685           0 : }
    2686             : 
    2687           0 : void GtkSalFrame::grabPointer( bool bGrab, bool bOwnerEvents )
    2688             : {
    2689             : #if !GTK_CHECK_VERSION(3,0,0)
    2690           0 :     static const char* pEnv = getenv( "SAL_NO_MOUSEGRABS" );
    2691             : 
    2692           0 :     if( m_pWindow )
    2693             :     {
    2694           0 :         if( bGrab )
    2695             :         {
    2696           0 :             bool bUseGdkGrab = true;
    2697           0 :             const std::list< SalFrame* >& rFrames = getDisplay()->getFrames();
    2698           0 :             for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
    2699             :             {
    2700           0 :                 const GtkSalFrame* pFrame = static_cast< const GtkSalFrame* >(*it);
    2701           0 :                 if( pFrame->m_bWindowIsGtkPlug )
    2702             :                 {
    2703           0 :                     bUseGdkGrab = false;
    2704           0 :                     break;
    2705             :                 }
    2706             :             }
    2707           0 :             if( bUseGdkGrab )
    2708             :             {
    2709           0 :                 const int nMask = ( GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
    2710             : 
    2711           0 :                 if( !pEnv || !*pEnv )
    2712             :                     gdk_pointer_grab( widget_get_window( m_pWindow ), bOwnerEvents,
    2713             :                                       (GdkEventMask) nMask, NULL, m_pCurrentCursor,
    2714           0 :                                       GDK_CURRENT_TIME );
    2715             :             }
    2716             :             else
    2717             :             {
    2718             :                 // FIXME: for some unknown reason gdk_pointer_grab does not
    2719             :                 // really produce owner events for GtkPlug windows
    2720             :                 // the cause is yet unknown
    2721             : 
    2722             :                 // this is of course a bad hack, especially as we cannot
    2723             :                 // set the right cursor this way
    2724           0 :                 if( !pEnv || !*pEnv )
    2725           0 :                     XGrabPointer( getDisplay()->GetDisplay(),
    2726             :                                   widget_get_xid( m_pWindow ),
    2727             :                                   bOwnerEvents,
    2728             :                                   PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
    2729             :                                   GrabModeAsync,
    2730             :                                   GrabModeAsync,
    2731             :                                   None,
    2732             :                                   None,
    2733             :                                   CurrentTime
    2734           0 :                         );
    2735             : 
    2736             :             }
    2737             :         }
    2738             :         else
    2739             :         {
    2740             :             // Two GdkDisplays may be open
    2741           0 :             if( !pEnv || !*pEnv )
    2742           0 :                 gdk_display_pointer_ungrab( getGdkDisplay(), GDK_CURRENT_TIME);
    2743             :         }
    2744             :     }
    2745             : #else
    2746             :     (void)bGrab; (void) bOwnerEvents;
    2747             :     //FIXME: No GrabPointer implementation for gtk3 ...
    2748             : #endif
    2749           0 : }
    2750             : 
    2751           0 : void GtkSalFrame::CaptureMouse( bool bCapture )
    2752             : {
    2753           0 :     getDisplay()->CaptureMouse( bCapture ? this : NULL );
    2754           0 : }
    2755             : 
    2756           0 : void GtkSalFrame::SetPointerPos( long nX, long nY )
    2757             : {
    2758           0 :     GtkSalFrame* pFrame = this;
    2759           0 :     while( pFrame && pFrame->isChild( false, true ) )
    2760           0 :         pFrame = pFrame->m_pParent;
    2761           0 :     if( ! pFrame )
    2762           0 :         return;
    2763             : 
    2764           0 :     GdkScreen *pScreen = gtk_window_get_screen( GTK_WINDOW(pFrame->m_pWindow) );
    2765           0 :     GdkDisplay *pDisplay = gdk_screen_get_display( pScreen );
    2766             : 
    2767             :     /* when the application tries to center the mouse in the dialog the
    2768             :      * window isn't mapped already. So use coordinates relative to the root window.
    2769             :      */
    2770           0 :     unsigned int nWindowLeft = maGeometry.nX + nX;
    2771           0 :     unsigned int nWindowTop  = maGeometry.nY + nY;
    2772             : 
    2773             :     XWarpPointer( GDK_DISPLAY_XDISPLAY (pDisplay), None,
    2774             :                   GDK_WINDOW_XID (gdk_screen_get_root_window( pScreen ) ),
    2775           0 :                   0, 0, 0, 0, nWindowLeft, nWindowTop);
    2776             :     // #i38648# ask for the next motion hint
    2777             :     gint x, y;
    2778             :     GdkModifierType mask;
    2779           0 :     gdk_window_get_pointer( widget_get_window(pFrame->m_pWindow) , &x, &y, &mask );
    2780             : }
    2781             : 
    2782           0 : void GtkSalFrame::Flush()
    2783             : {
    2784             : #if GTK_CHECK_VERSION(3,0,0)
    2785             :     gdk_display_flush( getGdkDisplay() );
    2786             : #else
    2787           0 :     XFlush (GDK_DISPLAY_XDISPLAY (getGdkDisplay()));
    2788             : #endif
    2789           0 : }
    2790             : 
    2791           0 : void GtkSalFrame::Sync()
    2792             : {
    2793           0 :     gdk_display_sync( getGdkDisplay() );
    2794           0 : }
    2795             : 
    2796           0 : OUString GtkSalFrame::GetKeyName( sal_uInt16 nKeyCode )
    2797             : {
    2798             : #if !GTK_CHECK_VERSION(3,0,0)
    2799           0 :     return getDisplay()->GetKeyName( nKeyCode );
    2800             : #else
    2801             :     (void)nKeyCode;
    2802             :     //FIXME: key names
    2803             :     return OUString();
    2804             : #endif
    2805             : }
    2806             : 
    2807           0 : GdkDisplay *GtkSalFrame::getGdkDisplay()
    2808             : {
    2809           0 :     return GetGtkSalData()->GetGdkDisplay();
    2810             : }
    2811             : 
    2812           0 : GtkSalDisplay *GtkSalFrame::getDisplay()
    2813             : {
    2814           0 :     return GetGtkSalData()->GetGtkDisplay();
    2815             : }
    2816             : 
    2817           0 : SalFrame::SalPointerState GtkSalFrame::GetPointerState()
    2818             : {
    2819           0 :     SalPointerState aState;
    2820             :     GdkScreen* pScreen;
    2821             :     gint x, y;
    2822             :     GdkModifierType aMask;
    2823           0 :     gdk_display_get_pointer( getGdkDisplay(), &pScreen, &x, &y, &aMask );
    2824           0 :     aState.maPos = Point( x - maGeometry.nX, y - maGeometry.nY );
    2825           0 :     aState.mnState = GetMouseModCode( aMask );
    2826           0 :     return aState;
    2827             : }
    2828             : 
    2829           0 : SalFrame::SalIndicatorState GtkSalFrame::GetIndicatorState()
    2830             : {
    2831             :     SalIndicatorState aState;
    2832             : #if !GTK_CHECK_VERSION(3,0,0)
    2833           0 :     aState.mnState = GetGtkSalData()->GetGtkDisplay()->GetIndicatorState();
    2834             : #else
    2835             :     g_warning ("missing get indicator state");
    2836             :     aState.mnState = 0;
    2837             : #endif
    2838           0 :     return aState;
    2839             : }
    2840             : 
    2841           0 : void GtkSalFrame::SimulateKeyPress( sal_uInt16 nKeyCode )
    2842             : {
    2843             : #if !GTK_CHECK_VERSION(3,0,0)
    2844           0 :     GetGtkSalData()->GetGtkDisplay()->SimulateKeyPress(nKeyCode);
    2845             : #else
    2846             :     g_warning ("missing simulate keypress %d", nKeyCode);
    2847             : #endif
    2848           0 : }
    2849             : 
    2850           0 : void GtkSalFrame::SetInputContext( SalInputContext* pContext )
    2851             : {
    2852           0 :     if( ! pContext )
    2853           0 :         return;
    2854             : 
    2855           0 :     if( ! (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) )
    2856           0 :         return;
    2857             : 
    2858             :     // create a new im context
    2859           0 :     if( ! m_pIMHandler )
    2860           0 :         m_pIMHandler = new IMHandler( this );
    2861           0 :     m_pIMHandler->setInputContext( pContext );
    2862             : }
    2863             : 
    2864           0 : void GtkSalFrame::EndExtTextInput( sal_uInt16 nFlags )
    2865             : {
    2866           0 :     if( m_pIMHandler )
    2867           0 :         m_pIMHandler->endExtTextInput( nFlags );
    2868           0 : }
    2869             : 
    2870           0 : bool GtkSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , vcl::KeyCode& )
    2871             : {
    2872             :     // not supported yet
    2873           0 :     return false;
    2874             : }
    2875             : 
    2876           0 : LanguageType GtkSalFrame::GetInputLanguage()
    2877             : {
    2878           0 :     return LANGUAGE_DONTKNOW;
    2879             : }
    2880             : 
    2881           0 : void GtkSalFrame::UpdateSettings( AllSettings& rSettings )
    2882             : {
    2883           0 :     if( ! m_pWindow )
    2884           0 :         return;
    2885             : 
    2886           0 :     GtkSalGraphics* pGraphics = static_cast<GtkSalGraphics*>(m_aGraphics[0].pGraphics);
    2887           0 :     bool bFreeGraphics = false;
    2888           0 :     if( ! pGraphics )
    2889             :     {
    2890           0 :         pGraphics = static_cast<GtkSalGraphics*>(AcquireGraphics());
    2891           0 :         if ( !pGraphics )
    2892             :         {
    2893             :             SAL_WARN("vcl", "Could not get graphics - unable to update settings");
    2894           0 :             return;
    2895             :         }
    2896           0 :         bFreeGraphics = true;
    2897             :     }
    2898             : 
    2899           0 :     pGraphics->updateSettings( rSettings );
    2900             : 
    2901           0 :     if( bFreeGraphics )
    2902           0 :         ReleaseGraphics( pGraphics );
    2903             : }
    2904             : 
    2905           0 : void GtkSalFrame::Beep()
    2906             : {
    2907           0 :     gdk_display_beep( getGdkDisplay() );
    2908           0 : }
    2909             : 
    2910           0 : const SystemEnvData* GtkSalFrame::GetSystemData() const
    2911             : {
    2912           0 :     return &m_aSystemData;
    2913             : }
    2914             : 
    2915           0 : void GtkSalFrame::SetParent( SalFrame* pNewParent )
    2916             : {
    2917           0 :     if( m_pParent )
    2918           0 :         m_pParent->m_aChildren.remove( this );
    2919           0 :     m_pParent = static_cast<GtkSalFrame*>(pNewParent);
    2920           0 :     if( m_pParent )
    2921           0 :         m_pParent->m_aChildren.push_back( this );
    2922           0 :     if( ! isChild() )
    2923           0 :         gtk_window_set_transient_for( GTK_WINDOW(m_pWindow),
    2924           0 :                                       (m_pParent && ! m_pParent->isChild(true,false)) ? GTK_WINDOW(m_pParent->m_pWindow) : NULL
    2925           0 :                                      );
    2926           0 : }
    2927             : 
    2928             : #if !GTK_CHECK_VERSION(3,0,0)
    2929             : 
    2930           0 : void GtkSalFrame::createNewWindow( ::Window aNewParent, bool bXEmbed, SalX11Screen nXScreen )
    2931             : {
    2932           0 :     bool bWasVisible = m_pWindow && IS_WIDGET_MAPPED(m_pWindow);
    2933           0 :     if( bWasVisible )
    2934           0 :         Show( false );
    2935             : 
    2936           0 :     if( (int)nXScreen.getXScreen() >= getDisplay()->GetXScreenCount() )
    2937           0 :         nXScreen = m_nXScreen;
    2938             : 
    2939             :     SystemParentData aParentData;
    2940           0 :     aParentData.aWindow = aNewParent;
    2941           0 :     aParentData.bXEmbedSupport = bXEmbed;
    2942           0 :     if( aNewParent == None )
    2943             :     {
    2944           0 :         aNewParent = getDisplay()->GetRootWindow(nXScreen);
    2945           0 :         aParentData.aWindow = None;
    2946           0 :         aParentData.bXEmbedSupport = false;
    2947             :     }
    2948             :     else
    2949             :     {
    2950             :         // is new parent a root window ?
    2951           0 :         Display* pDisp = getDisplay()->GetDisplay();
    2952           0 :         int nScreens = getDisplay()->GetXScreenCount();
    2953           0 :         for( int i = 0; i < nScreens; i++ )
    2954             :         {
    2955           0 :             if( aNewParent == RootWindow( pDisp, i ) )
    2956             :             {
    2957           0 :                 nXScreen = SalX11Screen( i );
    2958           0 :                 aParentData.aWindow = None;
    2959           0 :                 aParentData.bXEmbedSupport = false;
    2960           0 :                 break;
    2961             :             }
    2962             :         }
    2963             :     }
    2964             : 
    2965             :     // free xrender resources
    2966           0 :     for( unsigned int i = 0; i < SAL_N_ELEMENTS(m_aGraphics); i++ )
    2967           0 :         if( m_aGraphics[i].bInUse )
    2968           0 :             m_aGraphics[i].pGraphics->SetDrawable( None, m_nXScreen );
    2969             : 
    2970             :     // first deinit frame
    2971           0 :     if( m_pIMHandler )
    2972             :     {
    2973           0 :         delete m_pIMHandler;
    2974           0 :         m_pIMHandler = NULL;
    2975             :     }
    2976           0 :     if( m_pRegion )
    2977             :     {
    2978             : #if GTK_CHECK_VERSION(3,0,0)
    2979             :         cairo_region_destroy( m_pRegion );
    2980             : #else
    2981           0 :         gdk_region_destroy( m_pRegion );
    2982             : #endif
    2983             :     }
    2984           0 :     if( m_pFixedContainer )
    2985           0 :         gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer) );
    2986           0 :     if( m_pWindow )
    2987           0 :         gtk_widget_destroy( m_pWindow );
    2988           0 :     if( m_pForeignParent )
    2989           0 :         g_object_unref( G_OBJECT( m_pForeignParent ) );
    2990           0 :     if( m_pForeignTopLevel )
    2991           0 :         g_object_unref( G_OBJECT( m_pForeignTopLevel ) );
    2992             : 
    2993             :     // init new window
    2994           0 :     m_bDefaultPos = m_bDefaultSize = false;
    2995           0 :     if( aParentData.aWindow != None )
    2996             :     {
    2997           0 :         m_nStyle |= SAL_FRAME_STYLE_PLUG;
    2998           0 :         Init( &aParentData );
    2999             :     }
    3000             :     else
    3001             :     {
    3002           0 :         m_nStyle &= ~SAL_FRAME_STYLE_PLUG;
    3003           0 :         Init( (m_pParent && m_pParent->m_nXScreen == m_nXScreen) ? m_pParent : NULL, m_nStyle );
    3004             :     }
    3005             : 
    3006             :     // update graphics
    3007           0 :     for( unsigned int i = 0; i < SAL_N_ELEMENTS(m_aGraphics); i++ )
    3008             :     {
    3009           0 :         if( m_aGraphics[i].bInUse )
    3010             :         {
    3011           0 :             m_aGraphics[i].pGraphics->SetDrawable( widget_get_xid(m_pWindow), m_nXScreen );
    3012           0 :             m_aGraphics[i].pGraphics->SetWindow( m_pWindow );
    3013             :         }
    3014             :     }
    3015             : 
    3016           0 :     if( ! m_aTitle.isEmpty() )
    3017           0 :         SetTitle( m_aTitle );
    3018             : 
    3019           0 :     if( bWasVisible )
    3020           0 :         Show( true );
    3021             : 
    3022           0 :     std::list< GtkSalFrame* > aChildren = m_aChildren;
    3023           0 :     m_aChildren.clear();
    3024           0 :     for( std::list< GtkSalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it )
    3025           0 :         (*it)->createNewWindow( None, false, m_nXScreen );
    3026             : 
    3027             :     // FIXME: SalObjects
    3028           0 : }
    3029             : #endif
    3030             : 
    3031           0 : bool GtkSalFrame::SetPluginParent( SystemParentData* pSysParent )
    3032             : {
    3033             : #if !GTK_CHECK_VERSION(3,0,0)
    3034           0 :     GetGenericData()->ErrorTrapPush(); // permanantly ignore unruly children's errors
    3035           0 :     createNewWindow( pSysParent->aWindow, (pSysParent->nSize > sizeof(long)) && pSysParent->bXEmbedSupport, m_nXScreen );
    3036           0 :     return true;
    3037             : #else
    3038             :     (void)pSysParent;
    3039             :     //FIXME: no SetPluginParent impl. for gtk3
    3040             :     return false;
    3041             : #endif
    3042             : }
    3043             : 
    3044           0 : void GtkSalFrame::ResetClipRegion()
    3045             : {
    3046           0 :     if( m_pWindow )
    3047           0 :         gdk_window_shape_combine_region( widget_get_window( m_pWindow ), NULL, 0, 0 );
    3048           0 : }
    3049             : 
    3050           0 : void GtkSalFrame::BeginSetClipRegion( sal_uLong )
    3051             : {
    3052             : #if GTK_CHECK_VERSION(3,0,0)
    3053             :     if( m_pRegion )
    3054             :         cairo_region_destroy( m_pRegion );
    3055             :     m_pRegion = cairo_region_create();
    3056             : #else
    3057           0 :     if( m_pRegion )
    3058           0 :         gdk_region_destroy( m_pRegion );
    3059           0 :     m_pRegion = gdk_region_new();
    3060             : #endif
    3061           0 : }
    3062             : 
    3063           0 : void GtkSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
    3064             : {
    3065           0 :     if( m_pRegion )
    3066             :     {
    3067             :         GdkRectangle aRect;
    3068           0 :         aRect.x         = nX;
    3069           0 :         aRect.y         = nY;
    3070           0 :         aRect.width     = nWidth;
    3071           0 :         aRect.height    = nHeight;
    3072             : #if GTK_CHECK_VERSION(3,0,0)
    3073             :         cairo_region_union_rectangle( m_pRegion, &aRect );
    3074             : #else
    3075           0 :         gdk_region_union_with_rect( m_pRegion, &aRect );
    3076             : #endif
    3077             :     }
    3078           0 : }
    3079             : 
    3080           0 : void GtkSalFrame::EndSetClipRegion()
    3081             : {
    3082           0 :     if( m_pWindow && m_pRegion )
    3083           0 :         gdk_window_shape_combine_region( widget_get_window(m_pWindow), m_pRegion, 0, 0 );
    3084           0 : }
    3085             : 
    3086             : #if !GTK_CHECK_VERSION(3,0,0)
    3087           0 : bool GtkSalFrame::Dispatch( const XEvent* pEvent )
    3088             : {
    3089           0 :     bool bContinueDispatch = true;
    3090             : 
    3091           0 :     if( pEvent->type == PropertyNotify )
    3092             :     {
    3093           0 :         vcl_sal::WMAdaptor* pAdaptor = getDisplay()->getWMAdaptor();
    3094           0 :         Atom nDesktopAtom = pAdaptor->getAtom( vcl_sal::WMAdaptor::NET_WM_DESKTOP );
    3095           0 :         if( pEvent->xproperty.atom == nDesktopAtom &&
    3096           0 :             pEvent->xproperty.state == PropertyNewValue )
    3097             :         {
    3098           0 :             m_nWorkArea = pAdaptor->getWindowWorkArea( widget_get_xid(m_pWindow) );
    3099             :         }
    3100             :     }
    3101           0 :     else if( pEvent->type == ConfigureNotify )
    3102             :     {
    3103           0 :         if( m_pForeignParent && pEvent->xconfigure.window == m_aForeignParentWindow )
    3104             :         {
    3105           0 :             bContinueDispatch = false;
    3106           0 :             gtk_window_resize( GTK_WINDOW(m_pWindow), pEvent->xconfigure.width, pEvent->xconfigure.height );
    3107           0 :             if( ( sal::static_int_cast< int >(maGeometry.nWidth) !=
    3108           0 :                   pEvent->xconfigure.width ) ||
    3109           0 :                 ( sal::static_int_cast< int >(maGeometry.nHeight) !=
    3110             :                   pEvent->xconfigure.height ) )
    3111             :             {
    3112           0 :                 maGeometry.nWidth  = pEvent->xconfigure.width;
    3113           0 :                 maGeometry.nHeight = pEvent->xconfigure.height;
    3114           0 :                 setMinMaxSize();
    3115           0 :                 AllocateFrame();
    3116           0 :                 getDisplay()->SendInternalEvent( this, NULL, SALEVENT_RESIZE );
    3117             :             }
    3118             :         }
    3119           0 :         else if( m_pForeignTopLevel && pEvent->xconfigure.window == m_aForeignTopLevelWindow )
    3120             :         {
    3121           0 :             bContinueDispatch = false;
    3122             :             // update position
    3123           0 :             int x = 0, y = 0;
    3124             :             ::Window aChild;
    3125           0 :             XTranslateCoordinates( getDisplay()->GetDisplay(),
    3126             :                                    widget_get_xid(m_pWindow),
    3127           0 :                                    getDisplay()->GetRootWindow( getDisplay()->GetDefaultXScreen() ),
    3128             :                                    0, 0,
    3129             :                                    &x, &y,
    3130           0 :                                    &aChild );
    3131           0 :             if( x != maGeometry.nX || y != maGeometry.nY )
    3132             :             {
    3133           0 :                 maGeometry.nX = x;
    3134           0 :                 maGeometry.nY = y;
    3135           0 :                 getDisplay()->SendInternalEvent( this, NULL, SALEVENT_MOVE );
    3136             :             }
    3137             :         }
    3138             :     }
    3139           0 :     else if( pEvent->type == ClientMessage &&
    3140           0 :              pEvent->xclient.message_type == getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED ) &&
    3141           0 :              pEvent->xclient.window == widget_get_xid(m_pWindow) &&
    3142             :              m_bWindowIsGtkPlug
    3143             :              )
    3144             :     {
    3145             :         // FIXME: this should not be necessary, GtkPlug should do this
    3146             :         // transparently for us
    3147           0 :         if( pEvent->xclient.data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE
    3148           0 :             pEvent->xclient.data.l[1] == 2    // XEMBED_WINDOW_DEACTIVATE
    3149             :         )
    3150             :         {
    3151             :             GdkEventFocus aEvent;
    3152           0 :             aEvent.type = GDK_FOCUS_CHANGE;
    3153           0 :             aEvent.window = widget_get_window( m_pWindow );
    3154           0 :             aEvent.send_event = gint8(TRUE);
    3155           0 :             aEvent.in = gint16(pEvent->xclient.data.l[1] == 1);
    3156           0 :             signalFocus( m_pWindow, &aEvent, this );
    3157             :         }
    3158             :     }
    3159             : 
    3160           0 :     return bContinueDispatch;
    3161             : }
    3162             : #endif
    3163             : 
    3164           0 : gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer frame )
    3165             : {
    3166           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3167             :     SalMouseEvent aEvent;
    3168           0 :     sal_uInt16 nEventType = 0;
    3169           0 :     switch( pEvent->type )
    3170             :     {
    3171             :         case GDK_BUTTON_PRESS:
    3172           0 :             nEventType = SALEVENT_MOUSEBUTTONDOWN;
    3173           0 :             break;
    3174             :         case GDK_BUTTON_RELEASE:
    3175           0 :             nEventType = SALEVENT_MOUSEBUTTONUP;
    3176           0 :             break;
    3177             :         default:
    3178           0 :             return false;
    3179             :     }
    3180           0 :     switch( pEvent->button )
    3181             :     {
    3182           0 :         case 1: aEvent.mnButton = MOUSE_LEFT;   break;
    3183           0 :         case 2: aEvent.mnButton = MOUSE_MIDDLE; break;
    3184           0 :         case 3: aEvent.mnButton = MOUSE_RIGHT;  break;
    3185           0 :         default: return false;
    3186             :     }
    3187           0 :     aEvent.mnTime   = pEvent->time;
    3188           0 :     aEvent.mnX      = (long)pEvent->x_root - pThis->maGeometry.nX;
    3189           0 :     aEvent.mnY      = (long)pEvent->y_root - pThis->maGeometry.nY;
    3190           0 :     aEvent.mnCode   = GetMouseModCode( pEvent->state );
    3191             : 
    3192           0 :     bool bClosePopups = false;
    3193           0 :     if( pEvent->type == GDK_BUTTON_PRESS &&
    3194           0 :         (pThis->m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) == 0
    3195             :         )
    3196             :     {
    3197           0 :         if( m_nFloats > 0 )
    3198             :         {
    3199             :             // close popups if user clicks outside our application
    3200             :             gint x, y;
    3201           0 :             bClosePopups = (gdk_display_get_window_at_pointer( pThis->getGdkDisplay(), &x, &y ) == NULL);
    3202             :         }
    3203             :         /*  #i30306# release implicit pointer grab if no popups are open; else
    3204             :          *  Drag cannot grab the pointer and will fail.
    3205             :          */
    3206           0 :         if( m_nFloats < 1 || bClosePopups )
    3207           0 :             gdk_display_pointer_ungrab( pThis->getGdkDisplay(), GDK_CURRENT_TIME );
    3208             :     }
    3209             : 
    3210           0 :     if( pThis->m_bWindowIsGtkPlug &&
    3211           0 :         pEvent->type == GDK_BUTTON_PRESS &&
    3212           0 :         pEvent->button == 1 )
    3213             :     {
    3214           0 :         pThis->askForXEmbedFocus( pEvent->time );
    3215             :     }
    3216             : 
    3217             :     // --- RTL --- (mirror mouse pos)
    3218           0 :     if( Application::GetSettings().GetLayoutRTL() )
    3219           0 :         aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
    3220             : 
    3221           0 :     vcl::DeletionListener aDel( pThis );
    3222             : 
    3223           0 :     pThis->CallCallback( nEventType, &aEvent );
    3224             : 
    3225           0 :     if( ! aDel.isDeleted() )
    3226             :     {
    3227           0 :         if( bClosePopups )
    3228             :         {
    3229           0 :             ImplSVData* pSVData = ImplGetSVData();
    3230           0 :             if ( pSVData->maWinData.mpFirstFloat )
    3231             :             {
    3232           0 :                 static const char* pEnv = getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
    3233           0 :                 if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) && !(pEnv && *pEnv) )
    3234           0 :                     pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
    3235             :             }
    3236             :         }
    3237             : 
    3238           0 :         if( ! aDel.isDeleted() )
    3239             :         {
    3240           0 :             int frame_x = (int)(pEvent->x_root - pEvent->x);
    3241           0 :             int frame_y = (int)(pEvent->y_root - pEvent->y);
    3242           0 :             if( frame_x != pThis->maGeometry.nX || frame_y != pThis->maGeometry.nY )
    3243             :             {
    3244           0 :                 pThis->maGeometry.nX = frame_x;
    3245           0 :                 pThis->maGeometry.nY = frame_y;
    3246           0 :                 pThis->CallCallback( SALEVENT_MOVE, NULL );
    3247             :             }
    3248             :         }
    3249             :     }
    3250             : 
    3251           0 :     return false;
    3252             : }
    3253             : 
    3254           0 : gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEvent* pEvent, gpointer frame )
    3255             : {
    3256           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3257           0 :     GdkEventScroll* pSEvent = (GdkEventScroll*)pEvent;
    3258             : 
    3259             :     static sal_uLong        nLines = 0;
    3260           0 :     if( ! nLines )
    3261             :     {
    3262           0 :         char* pEnv = getenv( "SAL_WHEELLINES" );
    3263           0 :         nLines = pEnv ? atoi( pEnv ) : 3;
    3264           0 :         if( nLines > 10 )
    3265           0 :             nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
    3266             :     }
    3267             : 
    3268           0 :     bool bNeg = (pSEvent->direction == GDK_SCROLL_DOWN || pSEvent->direction == GDK_SCROLL_RIGHT );
    3269           0 :     SalWheelMouseEvent aEvent;
    3270           0 :     aEvent.mnTime           = pSEvent->time;
    3271           0 :     aEvent.mnX              = (sal_uLong)pSEvent->x;
    3272           0 :     aEvent.mnY              = (sal_uLong)pSEvent->y;
    3273           0 :     aEvent.mnDelta          = bNeg ? -120 : 120;
    3274           0 :     aEvent.mnNotchDelta     = bNeg ? -1 : 1;
    3275           0 :     aEvent.mnScrollLines    = nLines;
    3276           0 :     aEvent.mnCode           = GetMouseModCode( pSEvent->state );
    3277           0 :     aEvent.mbHorz           = (pSEvent->direction == GDK_SCROLL_LEFT || pSEvent->direction == GDK_SCROLL_RIGHT);
    3278             : 
    3279             :     // --- RTL --- (mirror mouse pos)
    3280           0 :     if( Application::GetSettings().GetLayoutRTL() )
    3281           0 :         aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
    3282             : 
    3283           0 :     pThis->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
    3284             : 
    3285           0 :     return false;
    3286             : }
    3287             : 
    3288           0 : gboolean GtkSalFrame::signalMotion( GtkWidget*, GdkEventMotion* pEvent, gpointer frame )
    3289             : {
    3290           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3291             : 
    3292             :     SalMouseEvent aEvent;
    3293           0 :     aEvent.mnTime   = pEvent->time;
    3294           0 :     aEvent.mnX      = (long)pEvent->x_root - pThis->maGeometry.nX;
    3295           0 :     aEvent.mnY      = (long)pEvent->y_root - pThis->maGeometry.nY;
    3296           0 :     aEvent.mnCode   = GetMouseModCode( pEvent->state );
    3297           0 :     aEvent.mnButton = 0;
    3298             : 
    3299             :     // --- RTL --- (mirror mouse pos)
    3300           0 :     if( Application::GetSettings().GetLayoutRTL() )
    3301           0 :         aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
    3302             : 
    3303           0 :     vcl::DeletionListener aDel( pThis );
    3304             : 
    3305           0 :     pThis->CallCallback( SALEVENT_MOUSEMOVE, &aEvent );
    3306             : 
    3307           0 :     if( ! aDel.isDeleted() )
    3308             :     {
    3309           0 :         int frame_x = (int)(pEvent->x_root - pEvent->x);
    3310           0 :         int frame_y = (int)(pEvent->y_root - pEvent->y);
    3311           0 :         if( frame_x != pThis->maGeometry.nX || frame_y != pThis->maGeometry.nY )
    3312             :         {
    3313           0 :             pThis->maGeometry.nX = frame_x;
    3314           0 :             pThis->maGeometry.nY = frame_y;
    3315           0 :             pThis->CallCallback( SALEVENT_MOVE, NULL );
    3316             :         }
    3317             : 
    3318           0 :         if( ! aDel.isDeleted() )
    3319             :         {
    3320             :             // ask for the next hint
    3321             :             gint x, y;
    3322             :             GdkModifierType mask;
    3323           0 :             gdk_window_get_pointer( widget_get_window(GTK_WIDGET(pThis->m_pWindow)), &x, &y, &mask );
    3324             :         }
    3325             :     }
    3326             : 
    3327           0 :     return true;
    3328             : }
    3329             : 
    3330           0 : gboolean GtkSalFrame::signalCrossing( GtkWidget*, GdkEventCrossing* pEvent, gpointer frame )
    3331             : {
    3332           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3333             :     SalMouseEvent aEvent;
    3334           0 :     aEvent.mnTime   = pEvent->time;
    3335           0 :     aEvent.mnX      = (long)pEvent->x_root - pThis->maGeometry.nX;
    3336           0 :     aEvent.mnY      = (long)pEvent->y_root - pThis->maGeometry.nY;
    3337           0 :     aEvent.mnCode   = GetMouseModCode( pEvent->state );
    3338           0 :     aEvent.mnButton = 0;
    3339             : 
    3340           0 :     pThis->CallCallback( (pEvent->type == GDK_ENTER_NOTIFY) ? SALEVENT_MOUSEMOVE : SALEVENT_MOUSELEAVE, &aEvent );
    3341             : 
    3342           0 :     return true;
    3343             : }
    3344             : 
    3345             : #if GTK_CHECK_VERSION(3,0,0)
    3346             : void GtkSalFrame::pushIgnoreDamage()
    3347             : {
    3348             :     m_nDuringRender++;
    3349             : }
    3350             : 
    3351             : void GtkSalFrame::popIgnoreDamage()
    3352             : {
    3353             :     m_nDuringRender--;
    3354             : }
    3355             : 
    3356             : bool GtkSalFrame::isDuringRender()
    3357             : {
    3358             :     return m_nDuringRender;
    3359             : }
    3360             : 
    3361             : #endif
    3362             : 
    3363           0 : void GtkSalFrame::damaged (const basegfx::B2IBox& rDamageRect)
    3364             : {
    3365             : #if !GTK_CHECK_VERSION(3,0,0)
    3366             :     (void)rDamageRect;
    3367             : #else
    3368             :     if ( isDuringRender() )
    3369             :         return;
    3370             : #if OSL_DEBUG_LEVEL > 1
    3371             :     long long area = rDamageRect.getWidth() * rDamageRect.getHeight();
    3372             :     if( area > 32 * 1024 )
    3373             :     {
    3374             :         fprintf( stderr, "bitmap damaged  %d %d (%dx%d) area %lld widget\n",
    3375             :                  (int) rDamageRect.getMinX(),
    3376             :                  (int) rDamageRect.getMinY(),
    3377             :                  (int) rDamageRect.getWidth(),
    3378             :                  (int) rDamageRect.getHeight(),
    3379             :                  area );
    3380             :     }
    3381             : #endif
    3382             :     /* FIXME: this is a dirty hack, to render buttons correctly, we
    3383             :      * should of course remove the -100 and + 200, but the whole area
    3384             :      * won't be rendered then.
    3385             :      */
    3386             :     gtk_widget_queue_draw_area( m_pWindow,
    3387             :                                 rDamageRect.getMinX() - 1,
    3388             :                                 rDamageRect.getMinY() - 1,
    3389             :                                 rDamageRect.getWidth() + 2,
    3390             :                                 rDamageRect.getHeight() + 2 );
    3391             : #endif
    3392           0 : }
    3393             : 
    3394             : #if GTK_CHECK_VERSION(3,0,0)
    3395             : // FIXME: This is incredibly lame ... but so is cairo's insistance on -exactly-
    3396             : // its own stride - neither more nor less - particularly not more aligned
    3397             : // we like 8byte aligned, it likes 4 - most odd.
    3398             : void GtkSalFrame::renderArea( cairo_t *cr, cairo_rectangle_t *area )
    3399             : {
    3400             :     if( !m_aFrame.get() )
    3401             :         return;
    3402             : 
    3403             :     basebmp::RawMemorySharedArray data = m_aFrame->getBuffer();
    3404             :     basegfx::B2IVector size = m_aFrame->getSize();
    3405             :     sal_Int32 nStride = m_aFrame->getScanlineStride();
    3406             : 
    3407             :     long ax = area->x;
    3408             :     long ay = area->y;
    3409             :     long awidth = area->width;
    3410             :     long aheight = area->height;
    3411             : 
    3412             :     // Sanity check bounds - we get some odd things here.
    3413             :     if( ax >= size.getX() )
    3414             :         ax = size.getX() - 1;
    3415             :     if( ay >= size.getY() )
    3416             :         ay = size.getY() - 1;
    3417             :     if( ax < 0 )
    3418             :     {
    3419             :         ax = 0;
    3420             :         awidth += ax;
    3421             :     }
    3422             :     if( ay < 0 )
    3423             :     {
    3424             :         ay = 0;
    3425             :         aheight += ay;
    3426             :     }
    3427             :     if( ax + awidth > size.getX() )
    3428             :         awidth = size.getX() - ax;
    3429             :     if( ay + aheight > size.getY() )
    3430             :         aheight = size.getY() - ay;
    3431             : 
    3432             :     cairo_save( cr );
    3433             : 
    3434             :     int cairo_stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, area->width);
    3435             :     unsigned char *p, *src, *mem = (unsigned char *)malloc (32 * cairo_stride * area->height);
    3436             :     p = mem;
    3437             :     src = data.get();
    3438             :     src += (int)ay * nStride + (int)ax * 3;
    3439             : 
    3440             :     for (int y = 0; y < aheight; ++y)
    3441             :     {
    3442             :         for (int x = 0; x < awidth; ++x)
    3443             :         {
    3444             :             p[x*4 + 0] = src[x*3 + 0]; // B
    3445             :             p[x*4 + 1] = src[x*3 + 1]; // G
    3446             :             p[x*4 + 2] = src[x*3 + 2]; // R
    3447             :             p[x*4 + 3] = 255; // A
    3448             :         }
    3449             :         src += nStride;
    3450             :         p += cairo_stride;
    3451             :     }
    3452             :     cairo_surface_t *pSurface =
    3453             :         cairo_image_surface_create_for_data( mem,
    3454             :                                              CAIRO_FORMAT_ARGB32,
    3455             :                                              awidth, aheight,
    3456             :                                              cairo_stride );
    3457             :     /*    g_warning( "Fixed cairo status %d %d strides: %d vs %d, mask %d\n",
    3458             :                (int) cairo_status( cr ),
    3459             :                (int) cairo_surface_status( pSurface ),
    3460             :                (int) nStride,
    3461             :                (int) cairo_stride,
    3462             :                (int) (cairo_stride & (sizeof (uint32_t)-1)) ); */
    3463             : 
    3464             :     cairo_set_operator( cr, CAIRO_OPERATOR_OVER );
    3465             :     cairo_set_source_surface( cr, pSurface, ax, ay );
    3466             :     cairo_paint( cr );
    3467             :     cairo_surface_destroy( pSurface );
    3468             :     free (mem);
    3469             :     cairo_restore( cr );
    3470             : 
    3471             :     // Render red rectangles to show what was re-rendered ...
    3472             :     if (debugRedboxRedraws)
    3473             :     {
    3474             :         cairo_save( cr );
    3475             :         cairo_set_line_width( cr, 1.0 );
    3476             :         cairo_set_source_rgb( cr, 1.0, 0, 0 );
    3477             :         cairo_rectangle( cr, ax + 1.0, ay + 1.0, awidth - 2.0, aheight - 2.0 );
    3478             :         cairo_stroke( cr );
    3479             :         cairo_restore( cr );
    3480             :     }
    3481             : }
    3482             : 
    3483             : gboolean GtkSalFrame::signalDraw( GtkWidget*, cairo_t *cr, gpointer frame )
    3484             : {
    3485             :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3486             : 
    3487             :     double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
    3488             :     cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
    3489             : 
    3490             :     if (debugQueuePureRedraw > 0)
    3491             :     {
    3492             :         debugQueuePureRedraw--;
    3493             :         fprintf (stderr, "skip signalDraw for debug %d\n", debugQueuePureRedraw);
    3494             :         cairo_rectangle_t rect = { x1, y1, x2 - x1, y2 - y1 };
    3495             :         pThis->renderArea( cr, &rect );
    3496             :         return FALSE;
    3497             :     }
    3498             : 
    3499             :     // FIXME: we quite probably want to stop re-rendering of pieces
    3500             :     // that we know are just damaged by us and hence already re-rendered
    3501             :     pThis->m_nDuringRender++;
    3502             : 
    3503             :     // FIXME: we need to profile whether re-rendering the entire
    3504             :     // clip region, and just pushing (with renderArea) smaller pieces
    3505             :     // is faster ...
    3506             :     cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list (cr);
    3507             :     fprintf( stderr, "paint %d regions\n", rects->num_rectangles);
    3508             :     for (int i = 0; i < rects->num_rectangles; i++) {
    3509             :         cairo_rectangle_t rect = rects->rectangles[i];
    3510             :         fprintf( stderr, "\t%d -> %g,%g %gx%g\n", i,
    3511             :                  rect.x, rect.y, rect.width, rect.height );
    3512             : 
    3513             :         struct SalPaintEvent aEvent( rect.x, rect.y, rect.width, rect.height );
    3514             :         aEvent.mbImmediateUpdate = true;
    3515             :         pThis->CallCallback( SALEVENT_PAINT, &aEvent );
    3516             :         pThis->renderArea( cr, &rect );
    3517             :     }
    3518             : 
    3519             :     pThis->m_nDuringRender--;
    3520             : 
    3521             :     return FALSE;
    3522             : }
    3523             : #endif // GTK_CHECK_VERSION(3,0,0)
    3524             : 
    3525           0 : gboolean GtkSalFrame::signalExpose( GtkWidget*, GdkEventExpose* pEvent, gpointer frame )
    3526             : {
    3527           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3528             : 
    3529           0 :     struct SalPaintEvent aEvent( pEvent->area.x, pEvent->area.y, pEvent->area.width, pEvent->area.height );
    3530             : 
    3531           0 :     pThis->CallCallback( SALEVENT_PAINT, &aEvent );
    3532             : 
    3533           0 :     return false;
    3534             : }
    3535             : 
    3536           0 : gboolean GtkSalFrame::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer frame )
    3537             : {
    3538           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3539             : 
    3540             :     X11SalInstance *pSalInstance =
    3541           0 :         static_cast< X11SalInstance* >(GetSalData()->m_pInstance);
    3542             : 
    3543             :     // check if printers have changed (analogous to salframe focus handler)
    3544           0 :     pSalInstance->updatePrinterUpdate();
    3545             : 
    3546           0 :     if( !pEvent->in )
    3547             :     {
    3548           0 :         pThis->m_nKeyModifiers = 0;
    3549           0 :         pThis->m_bSendModChangeOnRelease = false;
    3550             :     }
    3551             : 
    3552           0 :     if( pThis->m_pIMHandler )
    3553           0 :         pThis->m_pIMHandler->focusChanged( pEvent->in );
    3554             : 
    3555             :     // ask for changed printers like generic implementation
    3556           0 :     if( pEvent->in && pSalInstance->isPrinterInit() )
    3557           0 :         pSalInstance->updatePrinterUpdate();
    3558             : 
    3559             :     // FIXME: find out who the hell steals the focus from our frame
    3560             :     // while we have the pointer grabbed, this should not come from
    3561             :     // the window manager. Is this an event that was still queued ?
    3562             :     // The focus does not seem to get set inside our process
    3563             : 
    3564             :     // in the meantime do not propagate focus get/lose if floats are open
    3565           0 :     if( m_nFloats == 0 )
    3566           0 :         pThis->CallCallback( pEvent->in ? SALEVENT_GETFOCUS : SALEVENT_LOSEFOCUS, NULL );
    3567             : 
    3568           0 :     return false;
    3569             : }
    3570             : 
    3571             : #if !GTK_CHECK_VERSION(3,8,0)
    3572           0 : static OString getDisplayString()
    3573             : {
    3574           0 :     int nParams = rtl_getAppCommandArgCount();
    3575           0 :     OUString aParam;
    3576           0 :     for( int i = 0; i < nParams; i++ )
    3577             :     {
    3578           0 :         rtl_getAppCommandArg( i, &aParam.pData );
    3579           0 :         if( i < nParams-1 && (aParam == "-display" || aParam == "--display" ) )
    3580             :         {
    3581           0 :             rtl_getAppCommandArg( i+1, &aParam.pData );
    3582           0 :             return OUStringToOString( aParam, osl_getThreadTextEncoding() );
    3583             :         }
    3584             :     }
    3585           0 :     return OString();
    3586             : }
    3587             : #endif
    3588             : 
    3589           0 : gboolean GtkSalFrame::signalMap( GtkWidget *pWidget, GdkEvent*, gpointer frame )
    3590             : {
    3591           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3592             : 
    3593             : #if !GTK_CHECK_VERSION(3,8,0)
    3594             :     //Spawn off a helper program that will attempt to set this fullscreen
    3595             :     //window to span all displays.
    3596           0 :     if (pThis->m_bFullscreen && pThis->m_bSpanMonitorsWhenFullscreen)
    3597             :     {
    3598           0 :         GdkWindow* gdkwin = widget_get_window(pThis->m_pWindow);
    3599           0 :         if (gdkwin)
    3600             :         {
    3601           0 :             OUString sProgramURL( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/xid-fullscreen-on-all-monitors");
    3602           0 :             rtl::Bootstrap::expandMacros(sProgramURL);
    3603           0 :             OUString sProgram;
    3604           0 :             if (osl::FileBase::getSystemPathFromFileURL(sProgramURL, sProgram) == osl::File::E_None)
    3605             :             {
    3606           0 :                 OString sFinalProgram(OUStringToOString(sProgram, osl_getThreadTextEncoding())
    3607           0 :                     + " " + OString::number((int)GDK_WINDOW_XID(gdkwin)));
    3608           0 :                 OString sDisplay(getDisplayString());
    3609           0 :                 if (!sDisplay.isEmpty())
    3610             :                 {
    3611           0 :                     sFinalProgram += "--display " + sDisplay;
    3612             :                 }
    3613           0 :                 int returnValue = system(sFinalProgram.getStr());
    3614           0 :                 (void)returnValue;
    3615           0 :             }
    3616             :         }
    3617             :     }
    3618             : #endif
    3619             : 
    3620           0 :     bool bSetFocus = pThis->m_bSetFocusOnMap;
    3621           0 :     pThis->m_bSetFocusOnMap = false;
    3622             : 
    3623             : #if !GTK_CHECK_VERSION(3,0,0)
    3624           0 :     if( bSetFocus )
    3625             :     {
    3626           0 :         GetGenericData()->ErrorTrapPush();
    3627           0 :         XSetInputFocus( pThis->getDisplay()->GetDisplay(),
    3628             :                         widget_get_xid(pWidget),
    3629           0 :                         RevertToParent, CurrentTime );
    3630           0 :         XSync( pThis->getDisplay()->GetDisplay(), False );
    3631           0 :         GetGenericData()->ErrorTrapPop();
    3632             :     }
    3633             : #else
    3634             :     (void)pWidget; (void)bSetFocus;
    3635             :     //FIXME: no set input focus ...
    3636             : #endif
    3637             : 
    3638           0 :     pThis->CallCallback( SALEVENT_RESIZE, NULL );
    3639             : 
    3640           0 :     return false;
    3641             : }
    3642             : 
    3643           0 : gboolean GtkSalFrame::signalUnmap( GtkWidget*, GdkEvent*, gpointer frame )
    3644             : {
    3645           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3646             : 
    3647           0 :     pThis->CallCallback( SALEVENT_RESIZE, NULL );
    3648             : 
    3649           0 :     return false;
    3650             : }
    3651             : 
    3652           0 : gboolean GtkSalFrame::signalConfigure( GtkWidget*, GdkEventConfigure* pEvent, gpointer frame )
    3653             : {
    3654           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3655             : 
    3656           0 :     bool bMoved = false, bSized = false;
    3657           0 :     int x = pEvent->x, y = pEvent->y;
    3658             : 
    3659             :     /*  HACK: during sizing/moving a toolbar pThis->maGeometry is actually
    3660             :      *  already exact; even worse: due to the asynchronicity of configure
    3661             :      *  events the borderwindow which would evaluate this event
    3662             :      *  would size/move based on wrong data if we would actually evaluate
    3663             :      *  this event. So let's swallow it.
    3664             :      */
    3665           0 :     if( (pThis->m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) &&
    3666           0 :         pThis->getDisplay()->GetCaptureFrame() == pThis )
    3667           0 :         return false;
    3668             : 
    3669             :     /* #i31785# claims we cannot trust the x,y members of the event;
    3670             :      * they are e.g. not set correctly on maximize/demaximize;
    3671             :      * yet the gdkdisplay-x11.c code handling configure_events has
    3672             :      * done this XTranslateCoordinates work since the day ~zero.
    3673             :      */
    3674           0 :     if( x != pThis->maGeometry.nX || y != pThis->maGeometry.nY )
    3675             :     {
    3676           0 :         bMoved = true;
    3677           0 :         pThis->maGeometry.nX        = x;
    3678           0 :         pThis->maGeometry.nY        = y;
    3679             :     }
    3680             :     /* #i86302#
    3681             :      * for non sizeable windows we set the min and max hint for the window manager to
    3682             :      * achieve correct sizing. However this is asynchronous and e.g. on Compiz
    3683             :      * it sometimes happens that the window gets resized to another size (some default)
    3684             :      * if we update the size here, subsequent setMinMaxSize will use this wrong size
    3685             :      * - which is not good since the window manager will now size the window back to this
    3686             :      * wrong size at some point.
    3687             :      */
    3688             :     /*    fprintf (stderr, "configure %d %d %d (%d) %d, %d diff? %d\n",
    3689             :              (int)pThis->m_bFullscreen, (pThis->m_nStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_PLUG)), SAL_FRAME_STYLE_SIZEABLE,
    3690             :              !!( pThis->m_bFullscreen || (pThis->m_nStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_PLUG)) == SAL_FRAME_STYLE_SIZEABLE ),
    3691             :              pEvent->width, pEvent->height,
    3692             :              !!(pEvent->width != (int)pThis->maGeometry.nWidth || pEvent->height != (int)pThis->maGeometry.nHeight)
    3693             :              ); */
    3694           0 :     if( pThis->m_bFullscreen || (pThis->m_nStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_PLUG)) == SAL_FRAME_STYLE_SIZEABLE )
    3695             :     {
    3696           0 :         if( pEvent->width != (int)pThis->maGeometry.nWidth || pEvent->height != (int)pThis->maGeometry.nHeight )
    3697             :         {
    3698           0 :             bSized = true;
    3699           0 :             pThis->maGeometry.nWidth    = pEvent->width;
    3700           0 :             pThis->maGeometry.nHeight   = pEvent->height;
    3701             :         }
    3702             :     }
    3703             : 
    3704             :     // update decoration hints
    3705           0 :     if( ! (pThis->m_nStyle & SAL_FRAME_STYLE_PLUG) )
    3706             :     {
    3707             :         GdkRectangle aRect;
    3708           0 :         gdk_window_get_frame_extents( widget_get_window(GTK_WIDGET(pThis->m_pWindow)), &aRect );
    3709           0 :         pThis->maGeometry.nTopDecoration    = y - aRect.y;
    3710           0 :         pThis->maGeometry.nBottomDecoration = aRect.y + aRect.height - y - pEvent->height;
    3711           0 :         pThis->maGeometry.nLeftDecoration   = x - aRect.x;
    3712           0 :         pThis->maGeometry.nRightDecoration  = aRect.x + aRect.width - x - pEvent->width;
    3713             :     }
    3714             :     else
    3715             :     {
    3716             :         pThis->maGeometry.nTopDecoration =
    3717             :             pThis->maGeometry.nBottomDecoration =
    3718             :             pThis->maGeometry.nLeftDecoration =
    3719           0 :             pThis->maGeometry.nRightDecoration = 0;
    3720             :     }
    3721             : 
    3722           0 :     pThis->updateScreenNumber();
    3723           0 :     if( bSized )
    3724           0 :         pThis->AllocateFrame();
    3725             : 
    3726           0 :     if( bMoved && bSized )
    3727           0 :         pThis->CallCallback( SALEVENT_MOVERESIZE, NULL );
    3728           0 :     else if( bMoved )
    3729           0 :         pThis->CallCallback( SALEVENT_MOVE, NULL );
    3730           0 :     else if( bSized )
    3731           0 :         pThis->CallCallback( SALEVENT_RESIZE, NULL );
    3732             : 
    3733           0 :     return false;
    3734             : }
    3735             : 
    3736           0 : gboolean GtkSalFrame::signalKey( GtkWidget*, GdkEventKey* pEvent, gpointer frame )
    3737             : {
    3738           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3739             : 
    3740           0 :     vcl::DeletionListener aDel( pThis );
    3741             : 
    3742           0 :     if( pThis->m_pIMHandler )
    3743             :     {
    3744           0 :         if( pThis->m_pIMHandler->handleKeyEvent( pEvent ) )
    3745           0 :             return true;
    3746             :     }
    3747             : 
    3748             :     // handle modifiers
    3749           0 :     if( pEvent->keyval == GDK_Shift_L || pEvent->keyval == GDK_Shift_R ||
    3750           0 :         pEvent->keyval == GDK_Control_L || pEvent->keyval == GDK_Control_R ||
    3751           0 :         pEvent->keyval == GDK_Alt_L || pEvent->keyval == GDK_Alt_R ||
    3752           0 :         pEvent->keyval == GDK_Meta_L || pEvent->keyval == GDK_Meta_R ||
    3753           0 :         pEvent->keyval == GDK_Super_L || pEvent->keyval == GDK_Super_R )
    3754             :     {
    3755             :         SalKeyModEvent aModEvt;
    3756             : 
    3757           0 :         sal_uInt16 nModCode = GetKeyModCode( pEvent->state );
    3758             : 
    3759           0 :         aModEvt.mnModKeyCode = 0; // emit no MODKEYCHANGE events
    3760           0 :         if( pEvent->type == GDK_KEY_PRESS && !pThis->m_nKeyModifiers )
    3761           0 :             pThis->m_bSendModChangeOnRelease = true;
    3762             : 
    3763           0 :         else if( pEvent->type == GDK_KEY_RELEASE &&
    3764             :                  pThis->m_bSendModChangeOnRelease )
    3765             :         {
    3766           0 :             aModEvt.mnModKeyCode = pThis->m_nKeyModifiers;
    3767           0 :             pThis->m_nKeyModifiers = 0;
    3768             :         }
    3769             : 
    3770           0 :         sal_uInt16 nExtModMask = 0;
    3771           0 :         sal_uInt16 nModMask = 0;
    3772             :         // pressing just the ctrl key leads to a keysym of XK_Control but
    3773             :         // the event state does not contain ControlMask. In the release
    3774             :         // event its the other way round: it does contain the Control mask.
    3775             :         // The modifier mode therefore has to be adapted manually.
    3776           0 :         switch( pEvent->keyval )
    3777             :         {
    3778             :             case GDK_Control_L:
    3779           0 :                 nExtModMask = MODKEY_LMOD1;
    3780           0 :                 nModMask = KEY_MOD1;
    3781           0 :                 break;
    3782             :             case GDK_Control_R:
    3783           0 :                 nExtModMask = MODKEY_RMOD1;
    3784           0 :                 nModMask = KEY_MOD1;
    3785           0 :                 break;
    3786             :             case GDK_Alt_L:
    3787           0 :                 nExtModMask = MODKEY_LMOD2;
    3788           0 :                 nModMask = KEY_MOD2;
    3789           0 :                 break;
    3790             :             case GDK_Alt_R:
    3791           0 :                 nExtModMask = MODKEY_RMOD2;
    3792           0 :                 nModMask = KEY_MOD2;
    3793           0 :                 break;
    3794             :             case GDK_Shift_L:
    3795           0 :                 nExtModMask = MODKEY_LSHIFT;
    3796           0 :                 nModMask = KEY_SHIFT;
    3797           0 :                 break;
    3798             :             case GDK_Shift_R:
    3799           0 :                 nExtModMask = MODKEY_RSHIFT;
    3800           0 :                 nModMask = KEY_SHIFT;
    3801           0 :                 break;
    3802             :             // Map Meta/Super to MOD3 modifier on all Unix systems
    3803             :             // except Mac OS X
    3804             :             case GDK_Meta_L:
    3805             :             case GDK_Super_L:
    3806           0 :                 nExtModMask = MODKEY_LMOD3;
    3807           0 :                 nModMask = KEY_MOD3;
    3808           0 :                 break;
    3809             :             case GDK_Meta_R:
    3810             :             case GDK_Super_R:
    3811           0 :                 nExtModMask = MODKEY_RMOD3;
    3812           0 :                 nModMask = KEY_MOD3;
    3813           0 :                 break;
    3814             :         }
    3815           0 :         if( pEvent->type == GDK_KEY_RELEASE )
    3816             :         {
    3817           0 :             nModCode &= ~nModMask;
    3818           0 :             pThis->m_nKeyModifiers &= ~nExtModMask;
    3819             :         }
    3820             :         else
    3821             :         {
    3822           0 :             nModCode |= nModMask;
    3823           0 :             pThis->m_nKeyModifiers |= nExtModMask;
    3824             :         }
    3825             : 
    3826           0 :         aModEvt.mnCode = nModCode;
    3827           0 :         aModEvt.mnTime = pEvent->time;
    3828             : 
    3829           0 :         pThis->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
    3830             : 
    3831             :     }
    3832             :     else
    3833             :     {
    3834             :         pThis->doKeyCallback( pEvent->state,
    3835             :                               pEvent->keyval,
    3836             :                               pEvent->hardware_keycode,
    3837             :                               pEvent->group,
    3838             :                               pEvent->time,
    3839           0 :                               sal_Unicode(gdk_keyval_to_unicode( pEvent->keyval )),
    3840             :                               (pEvent->type == GDK_KEY_PRESS),
    3841           0 :                               false );
    3842           0 :         if( ! aDel.isDeleted() )
    3843           0 :             pThis->m_bSendModChangeOnRelease = false;
    3844             :     }
    3845             : 
    3846           0 :     if( !aDel.isDeleted() && pThis->m_pIMHandler )
    3847           0 :         pThis->m_pIMHandler->updateIMSpotLocation();
    3848             : 
    3849           0 :     return true;
    3850             : }
    3851             : 
    3852           0 : gboolean GtkSalFrame::signalDelete( GtkWidget*, GdkEvent*, gpointer frame )
    3853             : {
    3854           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3855             : 
    3856           0 :     pThis->CallCallback( SALEVENT_CLOSE, NULL );
    3857             : 
    3858           0 :     return true;
    3859             : }
    3860             : 
    3861           0 : void GtkSalFrame::signalStyleSet( GtkWidget*, GtkStyle* pPrevious, gpointer frame )
    3862             : {
    3863           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3864             : 
    3865             :     // every frame gets an initial style set on creation
    3866             :     // do not post these as the whole application tends to
    3867             :     // redraw itself to adjust to the new style
    3868             :     // where there IS no new style resulting in tremendous unnecessary flickering
    3869           0 :     if( pPrevious != NULL )
    3870             :     {
    3871             :         // signalStyleSet does NOT usually have the gdk lock
    3872             :         // so post user event to safely dispatch the SALEVENT_SETTINGSCHANGED
    3873             :         // note: settings changed for multiple frames is avoided in winproc.cxx ImplHandleSettings
    3874           0 :         pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_SETTINGSCHANGED );
    3875           0 :         pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_FONTCHANGED );
    3876             :     }
    3877             : 
    3878             : #if !GTK_CHECK_VERSION(3,0,0)
    3879             :     /* #i64117# gtk sets a nice background pixmap
    3880             :     *  but we actually don't really want that, so save
    3881             :     *  some time on the Xserver as well as prevent
    3882             :     *  some paint issues
    3883             :     */
    3884           0 :     GdkWindow* pWin = widget_get_window(GTK_WIDGET(pThis->getWindow()));
    3885           0 :     if( pWin )
    3886             :     {
    3887           0 :         ::Window aWin = GDK_WINDOW_XWINDOW(pWin);
    3888           0 :         if( aWin != None )
    3889           0 :             XSetWindowBackgroundPixmap( pThis->getDisplay()->GetDisplay(),
    3890             :                                         aWin,
    3891           0 :                                         pThis->m_hBackgroundPixmap );
    3892             :     }
    3893           0 :     if( ! pThis->m_pParent )
    3894             :     {
    3895             :         // signalize theme changed for NWF caches
    3896             :         // FIXME: should be called only once for a style change
    3897           0 :         GtkSalGraphics::bThemeChanged = true;
    3898             :     }
    3899             : #endif
    3900           0 : }
    3901             : 
    3902           0 : gboolean GtkSalFrame::signalState( GtkWidget*, GdkEvent* pEvent, gpointer frame )
    3903             : {
    3904           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3905           0 :     if( (pThis->m_nState & GDK_WINDOW_STATE_ICONIFIED) != (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED ) )
    3906           0 :         pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_RESIZE );
    3907             : 
    3908           0 :     if(   (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_MAXIMIZED) &&
    3909           0 :         ! (pThis->m_nState & GDK_WINDOW_STATE_MAXIMIZED) )
    3910             :     {
    3911             :         pThis->m_aRestorePosSize =
    3912             :             Rectangle( Point( pThis->maGeometry.nX, pThis->maGeometry.nY ),
    3913           0 :                        Size( pThis->maGeometry.nWidth, pThis->maGeometry.nHeight ) );
    3914             :     }
    3915           0 :     pThis->m_nState = pEvent->window_state.new_window_state;
    3916             : 
    3917             :     #if OSL_DEBUG_LEVEL > 1
    3918             :     if( (pEvent->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN) )
    3919             :     {
    3920             :         fprintf( stderr, "window %p %s full screen state\n",
    3921             :             pThis,
    3922             :             (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ? "enters" : "leaves");
    3923             :     }
    3924             :     #endif
    3925             : 
    3926           0 :     return false;
    3927             : }
    3928             : 
    3929           0 : gboolean GtkSalFrame::signalVisibility( GtkWidget*, GdkEventVisibility* pEvent, gpointer frame )
    3930             : {
    3931           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3932           0 :     pThis->m_nVisibility = pEvent->state;
    3933             : 
    3934           0 :     return false;
    3935             : }
    3936             : 
    3937           0 : void GtkSalFrame::signalDestroy( GtkWidget* pObj, gpointer frame )
    3938             : {
    3939           0 :     GtkSalFrame* pThis = (GtkSalFrame*)frame;
    3940           0 :     if( pObj == pThis->m_pWindow )
    3941             :     {
    3942           0 :         pThis->m_pFixedContainer = NULL;
    3943           0 :         pThis->m_pWindow = NULL;
    3944             :     }
    3945           0 : }
    3946             : 
    3947             : // GtkSalFrame::IMHandler
    3948             : 
    3949           0 : GtkSalFrame::IMHandler::IMHandler( GtkSalFrame* pFrame )
    3950             : : m_pFrame(pFrame),
    3951             :   m_nPrevKeyPresses( 0 ),
    3952             :   m_pIMContext( NULL ),
    3953             :   m_bFocused( true ),
    3954           0 :   m_bPreeditJustChanged( false )
    3955             : {
    3956           0 :     m_aInputEvent.mpTextAttr = NULL;
    3957           0 :     createIMContext();
    3958           0 : }
    3959             : 
    3960           0 : GtkSalFrame::IMHandler::~IMHandler()
    3961             : {
    3962             :     // cancel an eventual event posted to begin preedit again
    3963           0 :     m_pFrame->getDisplay()->CancelInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
    3964           0 :     deleteIMContext();
    3965           0 : }
    3966             : 
    3967           0 : void GtkSalFrame::IMHandler::createIMContext()
    3968             : {
    3969           0 :     if( ! m_pIMContext )
    3970             :     {
    3971           0 :         m_pIMContext = gtk_im_multicontext_new ();
    3972           0 :         g_signal_connect( m_pIMContext, "commit",
    3973           0 :                           G_CALLBACK (signalIMCommit), this );
    3974           0 :         g_signal_connect( m_pIMContext, "preedit_changed",
    3975           0 :                           G_CALLBACK (signalIMPreeditChanged), this );
    3976           0 :         g_signal_connect( m_pIMContext, "retrieve_surrounding",
    3977           0 :                           G_CALLBACK (signalIMRetrieveSurrounding), this );
    3978           0 :         g_signal_connect( m_pIMContext, "delete_surrounding",
    3979           0 :                           G_CALLBACK (signalIMDeleteSurrounding), this );
    3980           0 :         g_signal_connect( m_pIMContext, "preedit_start",
    3981           0 :                           G_CALLBACK (signalIMPreeditStart), this );
    3982           0 :         g_signal_connect( m_pIMContext, "preedit_end",
    3983           0 :                           G_CALLBACK (signalIMPreeditEnd), this );
    3984             : 
    3985           0 :         GetGenericData()->ErrorTrapPush();
    3986           0 :         gtk_im_context_set_client_window( m_pIMContext, widget_get_window(GTK_WIDGET(m_pFrame->m_pWindow)) );
    3987           0 :         gtk_im_context_focus_in( m_pIMContext );
    3988           0 :         GetGenericData()->ErrorTrapPop();
    3989           0 :         m_bFocused = true;
    3990             :    }
    3991           0 : }
    3992             : 
    3993           0 : void GtkSalFrame::IMHandler::deleteIMContext()
    3994             : {
    3995           0 :     if( m_pIMContext )
    3996             :     {
    3997             :         // first give IC a chance to deinitialize
    3998           0 :         GetGenericData()->ErrorTrapPush();
    3999           0 :         gtk_im_context_set_client_window( m_pIMContext, NULL );
    4000           0 :         GetGenericData()->ErrorTrapPop();
    4001             :         // destroy old IC
    4002           0 :         g_object_unref( m_pIMContext );
    4003           0 :         m_pIMContext = NULL;
    4004             :     }
    4005           0 : }
    4006             : 
    4007           0 : void GtkSalFrame::IMHandler::doCallEndExtTextInput()
    4008             : {
    4009           0 :     m_aInputEvent.mpTextAttr = NULL;
    4010           0 :     m_pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL );
    4011           0 : }
    4012             : 
    4013           0 : void GtkSalFrame::IMHandler::updateIMSpotLocation()
    4014             : {
    4015           0 :     SalExtTextInputPosEvent aPosEvent;
    4016           0 :     m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent );
    4017             :     GdkRectangle aArea;
    4018           0 :     aArea.x = aPosEvent.mnX;
    4019           0 :     aArea.y = aPosEvent.mnY;
    4020           0 :     aArea.width = aPosEvent.mnWidth;
    4021           0 :     aArea.height = aPosEvent.mnHeight;
    4022           0 :     GetGenericData()->ErrorTrapPush();
    4023           0 :     gtk_im_context_set_cursor_location( m_pIMContext, &aArea );
    4024           0 :     GetGenericData()->ErrorTrapPop();
    4025           0 : }
    4026             : 
    4027           0 : void GtkSalFrame::IMHandler::setInputContext( SalInputContext* )
    4028             : {
    4029           0 : }
    4030             : 
    4031           0 : void GtkSalFrame::IMHandler::sendEmptyCommit()
    4032             : {
    4033           0 :     vcl::DeletionListener aDel( m_pFrame );
    4034             : 
    4035           0 :     SalExtTextInputEvent aEmptyEv;
    4036           0 :     aEmptyEv.mnTime             = 0;
    4037           0 :     aEmptyEv.mpTextAttr         = 0;
    4038           0 :     aEmptyEv.maText             = "";
    4039           0 :     aEmptyEv.mnCursorPos        = 0;
    4040           0 :     aEmptyEv.mnCursorFlags      = 0;
    4041           0 :     aEmptyEv.mbOnlyCursor       = False;
    4042           0 :     m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEmptyEv );
    4043           0 :     if( ! aDel.isDeleted() )
    4044           0 :         m_pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL );
    4045           0 : }
    4046             : 
    4047           0 : void GtkSalFrame::IMHandler::endExtTextInput( sal_uInt16 /*nFlags*/ )
    4048             : {
    4049           0 :     gtk_im_context_reset ( m_pIMContext );
    4050             : 
    4051           0 :     if( m_aInputEvent.mpTextAttr )
    4052             :     {
    4053           0 :         vcl::DeletionListener aDel( m_pFrame );
    4054             :         // delete preedit in sal (commit an empty string)
    4055           0 :         sendEmptyCommit();
    4056           0 :         if( ! aDel.isDeleted() )
    4057             :         {
    4058             :             // mark previous preedit state again (will e.g. be sent at focus gain)
    4059           0 :             m_aInputEvent.mpTextAttr = &m_aInputFlags[0];
    4060           0 :             if( m_bFocused )
    4061             :             {
    4062             :                 // begin preedit again
    4063           0 :                 m_pFrame->getDisplay()->SendInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
    4064             :             }
    4065           0 :         }
    4066             :     }
    4067           0 : }
    4068             : 
    4069           0 : void GtkSalFrame::IMHandler::focusChanged( bool bFocusIn )
    4070             : {
    4071           0 :     m_bFocused = bFocusIn;
    4072           0 :     if( bFocusIn )
    4073             :     {
    4074           0 :         GetGenericData()->ErrorTrapPush();
    4075           0 :         gtk_im_context_focus_in( m_pIMContext );
    4076           0 :         GetGenericData()->ErrorTrapPop();
    4077           0 :         if( m_aInputEvent.mpTextAttr )
    4078             :         {
    4079           0 :             sendEmptyCommit();
    4080             :             // begin preedit again
    4081           0 :             m_pFrame->getDisplay()->SendInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
    4082             :         }
    4083             :     }
    4084             :     else
    4085             :     {
    4086           0 :         GetGenericData()->ErrorTrapPush();
    4087           0 :         gtk_im_context_focus_out( m_pIMContext );
    4088           0 :         GetGenericData()->ErrorTrapPop();
    4089             :         // cancel an eventual event posted to begin preedit again
    4090           0 :         m_pFrame->getDisplay()->CancelInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
    4091             :     }
    4092           0 : }
    4093             : 
    4094           0 : bool GtkSalFrame::IMHandler::handleKeyEvent( GdkEventKey* pEvent )
    4095             : {
    4096           0 :     vcl::DeletionListener aDel( m_pFrame );
    4097             : 
    4098           0 :     if( pEvent->type == GDK_KEY_PRESS )
    4099             :     {
    4100             :         // Add this key press event to the list of previous key presses
    4101             :         // to which we compare key release events.  If a later key release
    4102             :         // event has a matching key press event in this list, we swallow
    4103             :         // the key release because some GTK Input Methods don't swallow it
    4104             :         // for us.
    4105           0 :         m_aPrevKeyPresses.push_back( PreviousKeyPress(pEvent) );
    4106           0 :         m_nPrevKeyPresses++;
    4107             : 
    4108             :         // Also pop off the earliest key press event if there are more than 10
    4109             :         // already.
    4110           0 :         while (m_nPrevKeyPresses > 10)
    4111             :         {
    4112           0 :             m_aPrevKeyPresses.pop_front();
    4113           0 :             m_nPrevKeyPresses--;
    4114             :         }
    4115             : 
    4116           0 :         GObject* pRef = G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext ) ) );
    4117             : 
    4118             :         // #i51353# update spot location on every key input since we cannot
    4119             :         // know which key may activate a preedit choice window
    4120           0 :         updateIMSpotLocation();
    4121           0 :         if( aDel.isDeleted() )
    4122           0 :             return true;
    4123             : 
    4124           0 :         gboolean bResult = gtk_im_context_filter_keypress( m_pIMContext, pEvent );
    4125           0 :         g_object_unref( pRef );
    4126             : 
    4127           0 :         if( aDel.isDeleted() )
    4128           0 :             return true;
    4129             : 
    4130           0 :         m_bPreeditJustChanged = false;
    4131             : 
    4132           0 :         if( bResult )
    4133           0 :             return true;
    4134             :         else
    4135             :         {
    4136             :             DBG_ASSERT( m_nPrevKeyPresses > 0, "key press has vanished !" );
    4137           0 :             if( ! m_aPrevKeyPresses.empty() ) // sanity check
    4138             :             {
    4139             :                 // event was not swallowed, do not filter a following
    4140             :                 // key release event
    4141             :                 // note: this relies on gtk_im_context_filter_keypress
    4142             :                 // returning without calling a handler (in the "not swallowed"
    4143             :                 // case ) which might change the previous key press list so
    4144             :                 // we would pop the wrong event here
    4145           0 :                 m_aPrevKeyPresses.pop_back();
    4146           0 :                 m_nPrevKeyPresses--;
    4147             :             }
    4148             :         }
    4149             :     }
    4150             : 
    4151             :     // Determine if we got an earlier key press event corresponding to this key release
    4152           0 :     if (pEvent->type == GDK_KEY_RELEASE)
    4153             :     {
    4154           0 :         GObject* pRef = G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext ) ) );
    4155           0 :         gboolean bResult = gtk_im_context_filter_keypress( m_pIMContext, pEvent );
    4156           0 :         g_object_unref( pRef );
    4157             : 
    4158           0 :         if( aDel.isDeleted() )
    4159           0 :             return true;
    4160             : 
    4161           0 :         m_bPreeditJustChanged = false;
    4162             : 
    4163           0 :         std::list<PreviousKeyPress>::iterator    iter     = m_aPrevKeyPresses.begin();
    4164           0 :         std::list<PreviousKeyPress>::iterator    iter_end = m_aPrevKeyPresses.end();
    4165           0 :         while (iter != iter_end)
    4166             :         {
    4167             :             // If we found a corresponding previous key press event, swallow the release
    4168             :             // and remove the earlier key press from our list
    4169           0 :             if (*iter == pEvent)
    4170             :             {
    4171           0 :                 m_aPrevKeyPresses.erase(iter);
    4172           0 :                 m_nPrevKeyPresses--;
    4173           0 :                 return true;
    4174             :             }
    4175           0 :             ++iter;
    4176             :         }
    4177             : 
    4178           0 :         if( bResult )
    4179           0 :             return true;
    4180             :     }
    4181             : 
    4182           0 :     return false;
    4183             : }
    4184             : 
    4185             : /* FIXME:
    4186             : * #122282# still more hacking: some IMEs never start a preedit but simply commit
    4187             : * in this case we cannot commit a single character. Workaround: do not do the
    4188             : * single key hack for enter or space if the unicode committed does not match
    4189             : */
    4190             : 
    4191           0 : static bool checkSingleKeyCommitHack( guint keyval, sal_Unicode cCode )
    4192             : {
    4193           0 :     bool bRet = true;
    4194           0 :     switch( keyval )
    4195             :     {
    4196             :         case GDK_KP_Enter:
    4197             :         case GDK_Return:
    4198           0 :             if( cCode != '\n' && cCode != '\r' )
    4199           0 :                 bRet = false;
    4200           0 :             break;
    4201             :         case GDK_space:
    4202             :         case GDK_KP_Space:
    4203           0 :             if( cCode != ' ' )
    4204           0 :                 bRet = false;
    4205           0 :             break;
    4206             :         default:
    4207           0 :             break;
    4208             :     }
    4209           0 :     return bRet;
    4210             : }
    4211             : 
    4212             : #ifdef SOLARIS
    4213             : #define CONTEXT_ARG pContext
    4214             : #else
    4215             : #define CONTEXT_ARG EMPTYARG
    4216             : #endif
    4217           0 : void GtkSalFrame::IMHandler::signalIMCommit( GtkIMContext* CONTEXT_ARG, gchar* pText, gpointer im_handler )
    4218             : {
    4219           0 :     GtkSalFrame::IMHandler* pThis = (GtkSalFrame::IMHandler*)im_handler;
    4220             : 
    4221           0 :     SolarMutexGuard aGuard;
    4222           0 :     vcl::DeletionListener aDel( pThis->m_pFrame );
    4223             :     {
    4224             :         const bool bWasPreedit =
    4225           0 :             (pThis->m_aInputEvent.mpTextAttr != 0) ||
    4226           0 :             pThis->m_bPreeditJustChanged;
    4227             : 
    4228           0 :         pThis->m_aInputEvent.mnTime             = 0;
    4229           0 :         pThis->m_aInputEvent.mpTextAttr         = 0;
    4230           0 :         pThis->m_aInputEvent.maText             = OUString( pText, strlen(pText), RTL_TEXTENCODING_UTF8 );
    4231           0 :         pThis->m_aInputEvent.mnCursorPos        = pThis->m_aInputEvent.maText.getLength();
    4232           0 :         pThis->m_aInputEvent.mnCursorFlags      = 0;
    4233           0 :         pThis->m_aInputEvent.mbOnlyCursor       = False;
    4234             : 
    4235           0 :         pThis->m_aInputFlags.clear();
    4236             : 
    4237             :         /* necessary HACK: all keyboard input comes in here as soon as a IMContext is set
    4238             :          *  which is logical and consequent. But since even simple input like
    4239             :          *  <space> comes through the commit signal instead of signalKey
    4240             :          *  and all kinds of windows only implement KeyInput (e.g. PushButtons,
    4241             :          *  RadioButtons and a lot of other Controls), will send a single
    4242             :          *  KeyInput/KeyUp sequence instead of an ExtText event if there
    4243             :          *  never was a preedit and the text is only one character.
    4244             :          *
    4245             :          *  In this case there the last ExtText event must have been
    4246             :          *  SALEVENT_ENDEXTTEXTINPUT, either because of a regular commit
    4247             :          *  or because there never was a preedit.
    4248             :          */
    4249           0 :         bool bSingleCommit = false;
    4250           0 :         if( ! bWasPreedit
    4251           0 :             && pThis->m_aInputEvent.maText.getLength() == 1
    4252           0 :             && ! pThis->m_aPrevKeyPresses.empty()
    4253             :             )
    4254             :         {
    4255           0 :             const PreviousKeyPress& rKP = pThis->m_aPrevKeyPresses.back();
    4256           0 :             sal_Unicode aOrigCode = pThis->m_aInputEvent.maText[0];
    4257             : 
    4258           0 :             if( checkSingleKeyCommitHack( rKP.keyval, aOrigCode ) )
    4259             :             {
    4260           0 :                 pThis->m_pFrame->doKeyCallback( rKP.state, rKP.keyval, rKP.hardware_keycode, rKP.group, rKP.time, aOrigCode, true, true );
    4261           0 :                 bSingleCommit = true;
    4262             :             }
    4263             :         }
    4264           0 :         if( ! bSingleCommit )
    4265             :         {
    4266           0 :             pThis->m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&pThis->m_aInputEvent);
    4267           0 :             if( ! aDel.isDeleted() )
    4268           0 :                 pThis->doCallEndExtTextInput();
    4269             :         }
    4270           0 :         if( ! aDel.isDeleted() )
    4271             :         {
    4272             :             // reset input event
    4273           0 :             pThis->m_aInputEvent.maText = "";
    4274           0 :             pThis->m_aInputEvent.mnCursorPos = 0;
    4275           0 :             pThis->updateIMSpotLocation();
    4276             :         }
    4277           0 :     }
    4278             :     #ifdef SOLARIS
    4279             :     // #i51356# workaround a solaris IIIMP bug
    4280             :     // in case of partial commits the preedit changed signal
    4281             :     // and commit signal come in wrong order
    4282             :     if( ! aDel.isDeleted() )
    4283             :         signalIMPreeditChanged( pContext, im_handler );
    4284             :     #endif
    4285           0 : }
    4286             : 
    4287           0 : void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext*, gpointer im_handler )
    4288             : {
    4289           0 :     GtkSalFrame::IMHandler* pThis = (GtkSalFrame::IMHandler*)im_handler;
    4290             : 
    4291           0 :     char*           pText           = NULL;
    4292           0 :     PangoAttrList*  pAttrs          = NULL;
    4293           0 :     gint            nCursorPos      = 0;
    4294             : 
    4295             :     gtk_im_context_get_preedit_string( pThis->m_pIMContext,
    4296             :                                        &pText,
    4297             :                                        &pAttrs,
    4298           0 :                                        &nCursorPos );
    4299           0 :     if( pText && ! *pText ) // empty string
    4300             :     {
    4301             :         // change from nothing to nothing -> do not start preedit
    4302             :         // e.g. this will activate input into a calc cell without
    4303             :         // user input
    4304           0 :         if( pThis->m_aInputEvent.maText.getLength() == 0 )
    4305             :         {
    4306           0 :             g_free( pText );
    4307           0 :             pango_attr_list_unref( pAttrs );
    4308           0 :             return;
    4309             :         }
    4310             :     }
    4311             : 
    4312           0 :     pThis->m_bPreeditJustChanged = true;
    4313             : 
    4314           0 :     bool bEndPreedit = (!pText || !*pText) && pThis->m_aInputEvent.mpTextAttr != NULL;
    4315           0 :     pThis->m_aInputEvent.mnTime             = 0;
    4316           0 :     pThis->m_aInputEvent.maText             = pText ? OUString( pText, strlen(pText), RTL_TEXTENCODING_UTF8 ) : OUString();
    4317           0 :     pThis->m_aInputEvent.mnCursorPos        = nCursorPos;
    4318           0 :     pThis->m_aInputEvent.mnCursorFlags      = 0;
    4319           0 :     pThis->m_aInputEvent.mbOnlyCursor       = False;
    4320             : 
    4321           0 :     pThis->m_aInputFlags = std::vector<sal_uInt16>( std::max( 1, (int)pThis->m_aInputEvent.maText.getLength() ), 0 );
    4322             : 
    4323           0 :     PangoAttrIterator *iter = pango_attr_list_get_iterator(pAttrs);
    4324           0 :     do
    4325             :     {
    4326           0 :         GSList *attr_list = NULL;
    4327           0 :         GSList *tmp_list = NULL;
    4328             :         gint start, end;
    4329           0 :         guint sal_attr = 0;
    4330             : 
    4331           0 :         pango_attr_iterator_range (iter, &start, &end);
    4332           0 :         if (end == G_MAXINT)
    4333           0 :             end = pText ? strlen (pText) : 0;
    4334           0 :         if (end == start)
    4335           0 :             continue;
    4336             : 
    4337           0 :         start = g_utf8_pointer_to_offset (pText, pText + start);
    4338           0 :         end = g_utf8_pointer_to_offset (pText, pText + end);
    4339             : 
    4340           0 :         tmp_list = attr_list = pango_attr_iterator_get_attrs (iter);
    4341           0 :         while (tmp_list)
    4342             :         {
    4343           0 :             PangoAttribute *pango_attr = (PangoAttribute *)(tmp_list->data);
    4344             : 
    4345           0 :             switch (pango_attr->klass->type)
    4346             :             {
    4347             :                 case PANGO_ATTR_BACKGROUND:
    4348           0 :                     sal_attr |= (EXTTEXTINPUT_ATTR_HIGHLIGHT | EXTTEXTINPUT_CURSOR_INVISIBLE);
    4349           0 :                     break;
    4350             :                 case PANGO_ATTR_UNDERLINE:
    4351           0 :                     sal_attr |= EXTTEXTINPUT_ATTR_UNDERLINE;
    4352           0 :                     break;
    4353             :                 case PANGO_ATTR_STRIKETHROUGH:
    4354           0 :                     sal_attr |= EXTTEXTINPUT_ATTR_REDTEXT;
    4355           0 :                     break;
    4356             :                 default:
    4357           0 :                     break;
    4358             :             }
    4359           0 :             pango_attribute_destroy (pango_attr);
    4360           0 :             tmp_list = tmp_list->next;
    4361             :         }
    4362           0 :         if (sal_attr == 0)
    4363           0 :             sal_attr |= EXTTEXTINPUT_ATTR_UNDERLINE;
    4364           0 :         g_slist_free (attr_list);
    4365             : 
    4366             :         // Set the sal attributes on our text
    4367           0 :         for (int i = start; i < end; ++i)
    4368             :         {
    4369             :             SAL_WARN_IF(i >= static_cast<int>(pThis->m_aInputFlags.size()),
    4370             :                 "vcl.gtk", "pango attrib out of range. Broken range: "
    4371             :                 << start << "," << end << " Legal range: 0,"
    4372             :                 << pThis->m_aInputFlags.size());
    4373           0 :             if (i >= static_cast<int>(pThis->m_aInputFlags.size()))
    4374           0 :                 continue;
    4375           0 :             pThis->m_aInputFlags[i] |= sal_attr;
    4376             :         }
    4377           0 :     } while (pango_attr_iterator_next (iter));
    4378           0 :     pango_attr_iterator_destroy(iter);
    4379             : 
    4380           0 :     pThis->m_aInputEvent.mpTextAttr = &pThis->m_aInputFlags[0];
    4381             : 
    4382           0 :     g_free( pText );
    4383           0 :     pango_attr_list_unref( pAttrs );
    4384             : 
    4385           0 :     SolarMutexGuard aGuard;
    4386           0 :     vcl::DeletionListener aDel( pThis->m_pFrame );
    4387             : 
    4388           0 :     pThis->m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&pThis->m_aInputEvent);
    4389           0 :     if( bEndPreedit && ! aDel.isDeleted() )
    4390           0 :         pThis->doCallEndExtTextInput();
    4391           0 :     if( ! aDel.isDeleted() )
    4392           0 :         pThis->updateIMSpotLocation();
    4393             : }
    4394             : 
    4395           0 : void GtkSalFrame::IMHandler::signalIMPreeditStart( GtkIMContext*, gpointer /*im_handler*/ )
    4396             : {
    4397           0 : }
    4398             : 
    4399           0 : void GtkSalFrame::IMHandler::signalIMPreeditEnd( GtkIMContext*, gpointer im_handler )
    4400             : {
    4401           0 :     GtkSalFrame::IMHandler* pThis = (GtkSalFrame::IMHandler*)im_handler;
    4402             : 
    4403           0 :     pThis->m_bPreeditJustChanged = true;
    4404             : 
    4405           0 :     SolarMutexGuard aGuard;
    4406           0 :     vcl::DeletionListener aDel( pThis->m_pFrame );
    4407           0 :     pThis->doCallEndExtTextInput();
    4408           0 :     if( ! aDel.isDeleted() )
    4409           0 :         pThis->updateIMSpotLocation();
    4410           0 : }
    4411             : 
    4412             : uno::Reference<accessibility::XAccessibleEditableText>
    4413           0 :     FindFocus(uno::Reference< accessibility::XAccessibleContext > xContext)
    4414             : {
    4415           0 :     if (!xContext.is())
    4416           0 :         uno::Reference< accessibility::XAccessibleEditableText >();
    4417             : 
    4418           0 :     uno::Reference<accessibility::XAccessibleStateSet> xState = xContext->getAccessibleStateSet();
    4419           0 :     if (xState.is())
    4420             :     {
    4421           0 :         if (xState->contains(accessibility::AccessibleStateType::FOCUSED))
    4422           0 :             return uno::Reference<accessibility::XAccessibleEditableText>(xContext, uno::UNO_QUERY);
    4423             :     }
    4424             : 
    4425           0 :     for (sal_Int32 i = 0; i < xContext->getAccessibleChildCount(); ++i)
    4426             :     {
    4427           0 :         uno::Reference< accessibility::XAccessible > xChild = xContext->getAccessibleChild(i);
    4428           0 :         if (!xChild.is())
    4429           0 :             continue;
    4430           0 :         uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
    4431           0 :         if (!xChildContext.is())
    4432           0 :             continue;
    4433           0 :         uno::Reference< accessibility::XAccessibleEditableText > xText = FindFocus(xChildContext);
    4434           0 :         if (xText.is())
    4435           0 :             return xText;
    4436           0 :     }
    4437           0 :     return uno::Reference< accessibility::XAccessibleEditableText >();
    4438             : }
    4439             : 
    4440           0 : static uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText(vcl::Window *pFocusWin)
    4441             : {
    4442           0 :     uno::Reference<accessibility::XAccessibleEditableText> xText;
    4443             :     try
    4444             :     {
    4445           0 :         uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible( true ) );
    4446           0 :         if (xAccessible.is())
    4447           0 :             xText = FindFocus(xAccessible->getAccessibleContext());
    4448             :     }
    4449           0 :     catch(const uno::Exception& e)
    4450             :     {
    4451             :         SAL_WARN( "vcl.gtk", "Exception in getting input method surrounding text: " << e.Message);
    4452             :     }
    4453           0 :     return xText;
    4454             : }
    4455             : 
    4456           0 : gboolean GtkSalFrame::IMHandler::signalIMRetrieveSurrounding( GtkIMContext* pContext, gpointer /*im_handler*/ )
    4457             : {
    4458           0 :     vcl::Window *pFocusWin = Application::GetFocusWindow();
    4459           0 :     if (!pFocusWin)
    4460           0 :         return true;
    4461             : 
    4462           0 :     uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(pFocusWin);
    4463           0 :     if (xText.is())
    4464             :     {
    4465           0 :         sal_uInt32 nPosition = xText->getCaretPosition();
    4466           0 :         OUString sAllText = xText->getText();
    4467           0 :         OString sUTF = OUStringToOString(sAllText, RTL_TEXTENCODING_UTF8);
    4468           0 :         OUString sCursorText(sAllText.copy(0, nPosition));
    4469             :         gtk_im_context_set_surrounding(pContext, sUTF.getStr(), sUTF.getLength(),
    4470           0 :             OUStringToOString(sCursorText, RTL_TEXTENCODING_UTF8).getLength());
    4471           0 :         return true;
    4472             :     }
    4473             : 
    4474           0 :     return false;
    4475             : }
    4476             : 
    4477           0 : gboolean GtkSalFrame::IMHandler::signalIMDeleteSurrounding( GtkIMContext*, gint offset, gint nchars,
    4478             :     gpointer /*im_handler*/ )
    4479             : {
    4480           0 :     vcl::Window *pFocusWin = Application::GetFocusWindow();
    4481           0 :     if (!pFocusWin)
    4482           0 :         return true;
    4483             : 
    4484           0 :     uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(pFocusWin);
    4485           0 :     if (xText.is())
    4486             :     {
    4487           0 :         sal_uInt32 nPosition = xText->getCaretPosition();
    4488             :         // #i111768# range checking
    4489           0 :         sal_Int32 nDeletePos = nPosition + offset;
    4490           0 :         sal_Int32 nDeleteEnd = nDeletePos + nchars;
    4491           0 :         if (nDeletePos < 0)
    4492           0 :             nDeletePos = 0;
    4493           0 :         if (nDeleteEnd < 0)
    4494           0 :             nDeleteEnd = 0;
    4495           0 :         if (nDeleteEnd > xText->getCharacterCount())
    4496           0 :             nDeleteEnd = xText->getCharacterCount();
    4497             : 
    4498           0 :         xText->deleteText(nDeletePos, nDeleteEnd);
    4499           0 :         return true;
    4500             :     }
    4501             : 
    4502           0 :     return false;
    4503             : }
    4504             : 
    4505           0 : Size GtkSalDisplay::GetScreenSize( int nDisplayScreen )
    4506             : {
    4507           0 :     Rectangle aRect = m_pSys->GetDisplayScreenPosSizePixel( nDisplayScreen );
    4508           0 :     return Size( aRect.GetWidth(), aRect.GetHeight() );
    4509           0 : }
    4510             : 
    4511             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10