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

Generated by: LCOV version 1.10