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

Generated by: LCOV version 1.11