LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/unx/gtk/window - gtksalframe.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1938 0.0 %
Date: 2013-07-09 Functions: 0 135 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10