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

Generated by: LCOV version 1.10