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