summaryrefslogtreecommitdiff
path: root/vcl/unx/gtk/window/gtkframe.cxx
diff options
context:
space:
mode:
authorBjoern Michaelsen <bjoern.michaelsen@canonical.com>2013-04-05 13:45:48 +0200
committerBjoern Michaelsen <bjoern.michaelsen@canonical.com>2013-04-17 16:25:57 +0200
commit58b7dd8aee242062f1ef75b310a39ff4a3fbe1ae (patch)
tree64681c9eb8b929b1a5614cc2177a912b0b384dac /vcl/unx/gtk/window/gtkframe.cxx
parenta029b55d9f8a7b6040fdc27f0b5fde86e71d94a0 (diff)
move gtkframe to gtksalframe to match class name
Diffstat (limited to 'vcl/unx/gtk/window/gtkframe.cxx')
-rw-r--r--vcl/unx/gtk/window/gtkframe.cxx4222
1 files changed, 0 insertions, 4222 deletions
diff --git a/vcl/unx/gtk/window/gtkframe.cxx b/vcl/unx/gtk/window/gtkframe.cxx
deleted file mode 100644
index edb37a39388c..000000000000
--- a/vcl/unx/gtk/window/gtkframe.cxx
+++ /dev/null
@@ -1,4222 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include <unx/gtk/gtkframe.hxx>
-#include <unx/gtk/gtkdata.hxx>
-#include <unx/gtk/gtkinst.hxx>
-#include <unx/gtk/gtkgdi.hxx>
-#include <vcl/keycodes.hxx>
-#include <vcl/layout.hxx>
-#include <unx/wmadaptor.hxx>
-#include <unx/sm.hxx>
-#include <unx/salbmp.h>
-#include <generic/genprn.h>
-#include <generic/geninst.h>
-#include <headless/svpgdi.hxx>
-#include <vcl/floatwin.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/window.hxx>
-#if !GTK_CHECK_VERSION(3,0,0)
-# include <unx/x11/xlimits.hxx>
-#endif
-#if defined(ENABLE_DBUS) && defined(ENABLE_GIO)
-# include <unx/gtk/gtksalmenu.hxx>
-#endif
-#if defined ENABLE_GMENU_INTEGRATION // defined in gtksalmenu.hxx above
-# include <unx/gtk/hudawareness.h>
-#endif
-
-#include <gtk/gtk.h>
-#include <prex.h>
-#include <X11/Xatom.h>
-#include <gdk/gdkx.h>
-#include <postx.h>
-
-#include <dlfcn.h>
-#include <vcl/salbtype.hxx>
-#include <vcl/bitmapex.hxx>
-#include <impbmp.hxx>
-#include <svids.hrc>
-#include <sal/macros.h>
-
-#include <basegfx/range/b2ibox.hxx>
-#include <basegfx/vector/b2ivector.hxx>
-
-#include <algorithm>
-#include <glib/gprintf.h>
-
-#if OSL_DEBUG_LEVEL > 1
-# include <cstdio>
-#endif
-
-#include <com/sun/star/accessibility/XAccessibleContext.hpp>
-#include <com/sun/star/accessibility/AccessibleRole.hpp>
-#include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
-#include <com/sun/star/accessibility/AccessibleStateType.hpp>
-#include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
-
-#if GTK_CHECK_VERSION(3,0,0)
-# include <gdk/gdkkeysyms-compat.h>
-#endif
-
-#ifdef ENABLE_DBUS
-#include <dbus/dbus-glib.h>
-
-#define GSM_DBUS_SERVICE "org.gnome.SessionManager"
-#define GSM_DBUS_PATH "/org/gnome/SessionManager"
-#define GSM_DBUS_INTERFACE "org.gnome.SessionManager"
-#endif
-
-// make compile on gtk older than 2.10
-#if GTK_MINOR_VERSION < 10
-#define GDK_SUPER_MASK (1 << 26)
-#define GDK_HYPER_MASK (1 << 27)
-#define GDK_META_MASK (1 << 28)
-#endif
-
-#if GTK_CHECK_VERSION(3,0,0)
-#define IS_WIDGET_REALIZED gtk_widget_get_realized
-#define IS_WIDGET_MAPPED gtk_widget_get_mapped
-#else
-#define IS_WIDGET_REALIZED GTK_WIDGET_REALIZED
-#define IS_WIDGET_MAPPED GTK_WIDGET_MAPPED
-#endif
-
-using namespace com::sun::star;
-
-int GtkSalFrame::m_nFloats = 0;
-
-#if defined ENABLE_GMENU_INTEGRATION
-static GDBusConnection* pSessionBus = NULL;
-#endif
-
-static sal_uInt16 GetKeyModCode( guint state )
-{
- sal_uInt16 nCode = 0;
- if( (state & GDK_SHIFT_MASK) )
- nCode |= KEY_SHIFT;
- if( (state & GDK_CONTROL_MASK) )
- nCode |= KEY_MOD1;
- if( (state & GDK_MOD1_MASK) )
- nCode |= KEY_MOD2;
-
- // Map Meta/Super keys to MOD3 modifier on all Unix systems
- // except Mac OS X
- if ( (state & GDK_META_MASK ) || ( state & GDK_SUPER_MASK ) )
- nCode |= KEY_MOD3;
- return nCode;
-}
-
-static sal_uInt16 GetMouseModCode( guint state )
-{
- sal_uInt16 nCode = GetKeyModCode( state );
- if( (state & GDK_BUTTON1_MASK) )
- nCode |= MOUSE_LEFT;
- if( (state & GDK_BUTTON2_MASK) )
- nCode |= MOUSE_MIDDLE;
- if( (state & GDK_BUTTON3_MASK) )
- nCode |= MOUSE_RIGHT;
-
- return nCode;
-}
-
-static sal_uInt16 GetKeyCode( guint keyval )
-{
- sal_uInt16 nCode = 0;
- if( keyval >= GDK_0 && keyval <= GDK_9 )
- nCode = KEY_0 + (keyval-GDK_0);
- else if( keyval >= GDK_KP_0 && keyval <= GDK_KP_9 )
- nCode = KEY_0 + (keyval-GDK_KP_0);
- else if( keyval >= GDK_A && keyval <= GDK_Z )
- nCode = KEY_A + (keyval-GDK_A );
- else if( keyval >= GDK_a && keyval <= GDK_z )
- nCode = KEY_A + (keyval-GDK_a );
- else if( keyval >= GDK_F1 && keyval <= GDK_F26 )
- {
-#if !GTK_CHECK_VERSION(3,0,0)
- if( GetGtkSalData()->GetGtkDisplay()->IsNumLockFromXS() )
- {
- nCode = KEY_F1 + (keyval-GDK_F1);
- }
- else
-#endif
- {
- switch( keyval )
- {
- // - - - - - Sun keyboard, see vcl/unx/source/app/saldisp.cxx
- case GDK_L2:
-#if !GTK_CHECK_VERSION(3,0,0)
- if( GetGtkSalData()->GetGtkDisplay()->GetServerVendor() == vendor_sun )
- nCode = KEY_REPEAT;
- else
-#endif
- nCode = KEY_F12;
- break;
- case GDK_L3: nCode = KEY_PROPERTIES; break;
- case GDK_L4: nCode = KEY_UNDO; break;
- case GDK_L6: nCode = KEY_COPY; break; // KEY_F16
- case GDK_L8: nCode = KEY_PASTE; break; // KEY_F18
- case GDK_L10: nCode = KEY_CUT; break; // KEY_F20
- default:
- nCode = KEY_F1 + (keyval-GDK_F1); break;
- }
- }
- }
- else
- {
- switch( keyval )
- {
- case GDK_KP_Down:
- case GDK_Down: nCode = KEY_DOWN; break;
- case GDK_KP_Up:
- case GDK_Up: nCode = KEY_UP; break;
- case GDK_KP_Left:
- case GDK_Left: nCode = KEY_LEFT; break;
- case GDK_KP_Right:
- case GDK_Right: nCode = KEY_RIGHT; break;
- case GDK_KP_Begin:
- case GDK_KP_Home:
- case GDK_Begin:
- case GDK_Home: nCode = KEY_HOME; break;
- case GDK_KP_End:
- case GDK_End: nCode = KEY_END; break;
- case GDK_KP_Page_Up:
- case GDK_Page_Up: nCode = KEY_PAGEUP; break;
- case GDK_KP_Page_Down:
- case GDK_Page_Down: nCode = KEY_PAGEDOWN; break;
- case GDK_KP_Enter:
- case GDK_Return: nCode = KEY_RETURN; break;
- case GDK_Escape: nCode = KEY_ESCAPE; break;
- case GDK_ISO_Left_Tab:
- case GDK_KP_Tab:
- case GDK_Tab: nCode = KEY_TAB; break;
- case GDK_BackSpace: nCode = KEY_BACKSPACE; break;
- case GDK_KP_Space:
- case GDK_space: nCode = KEY_SPACE; break;
- case GDK_KP_Insert:
- case GDK_Insert: nCode = KEY_INSERT; break;
- case GDK_KP_Delete:
- case GDK_Delete: nCode = KEY_DELETE; break;
- case GDK_plus:
- case GDK_KP_Add: nCode = KEY_ADD; break;
- case GDK_minus:
- case GDK_KP_Subtract: nCode = KEY_SUBTRACT; break;
- case GDK_asterisk:
- case GDK_KP_Multiply: nCode = KEY_MULTIPLY; break;
- case GDK_slash:
- case GDK_KP_Divide: nCode = KEY_DIVIDE; break;
- case GDK_period: nCode = KEY_POINT; break;
- case GDK_decimalpoint: nCode = KEY_POINT; break;
- case GDK_comma: nCode = KEY_COMMA; break;
- case GDK_less: nCode = KEY_LESS; break;
- case GDK_greater: nCode = KEY_GREATER; break;
- case GDK_KP_Equal:
- case GDK_equal: nCode = KEY_EQUAL; break;
- case GDK_Find: nCode = KEY_FIND; break;
- case GDK_Menu: nCode = KEY_CONTEXTMENU;break;
- case GDK_Help: nCode = KEY_HELP; break;
- case GDK_Undo: nCode = KEY_UNDO; break;
- case GDK_Redo: nCode = KEY_REPEAT; break;
- case GDK_KP_Decimal:
- case GDK_KP_Separator: nCode = KEY_DECIMAL; break;
- case GDK_asciitilde: nCode = KEY_TILDE; break;
- case GDK_leftsinglequotemark:
- case GDK_quoteleft: nCode = KEY_QUOTELEFT; break;
- case GDK_bracketleft: nCode = KEY_BRACKETLEFT; break;
- case GDK_bracketright: nCode = KEY_BRACKETRIGHT; break;
- case GDK_semicolon: nCode = KEY_SEMICOLON; break;
- // some special cases, also see saldisp.cxx
- // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000
- case 0x1000FF02: // apXK_Copy
- nCode = KEY_COPY;
- break;
- case 0x1000FF03: // apXK_Cut
- nCode = KEY_CUT;
- break;
- case 0x1000FF04: // apXK_Paste
- nCode = KEY_PASTE;
- break;
- case 0x1000FF14: // apXK_Repeat
- nCode = KEY_REPEAT;
- break;
- // Exit, Save
- // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000
- case 0x1000FF00:
- nCode = KEY_DELETE;
- break;
- // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000
- case 0x1000FF73: // hpXK_DeleteChar
- nCode = KEY_DELETE;
- break;
- case 0x1000FF74: // hpXK_BackTab
- case 0x1000FF75: // hpXK_KP_BackTab
- nCode = KEY_TAB;
- break;
- // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - -
- // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004
- case 0x1004FF02: // osfXK_Copy
- nCode = KEY_COPY;
- break;
- case 0x1004FF03: // osfXK_Cut
- nCode = KEY_CUT;
- break;
- case 0x1004FF04: // osfXK_Paste
- nCode = KEY_PASTE;
- break;
- case 0x1004FF07: // osfXK_BackTab
- nCode = KEY_TAB;
- break;
- case 0x1004FF08: // osfXK_BackSpace
- nCode = KEY_BACKSPACE;
- break;
- case 0x1004FF1B: // osfXK_Escape
- nCode = KEY_ESCAPE;
- break;
- // Up, Down, Left, Right, PageUp, PageDown
- // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - -
- // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007
- // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - -
- // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005
- case 0x1005FF10: // SunXK_F36
- nCode = KEY_F11;
- break;
- case 0x1005FF11: // SunXK_F37
- nCode = KEY_F12;
- break;
- case 0x1005FF70: // SunXK_Props
- nCode = KEY_PROPERTIES;
- break;
- case 0x1005FF71: // SunXK_Front
- nCode = KEY_FRONT;
- break;
- case 0x1005FF72: // SunXK_Copy
- nCode = KEY_COPY;
- break;
- case 0x1005FF73: // SunXK_Open
- nCode = KEY_OPEN;
- break;
- case 0x1005FF74: // SunXK_Paste
- nCode = KEY_PASTE;
- break;
- case 0x1005FF75: // SunXK_Cut
- nCode = KEY_CUT;
- break;
- }
- }
-
- return nCode;
-}
-
-// F10 means either KEY_F10 or KEY_MENU, which has to be decided
-// in the independent part.
-struct KeyAlternate
-{
- sal_uInt16 nKeyCode;
- sal_Unicode nCharCode;
- KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
- KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
-};
-
-inline KeyAlternate
-GetAlternateKeyCode( const sal_uInt16 nKeyCode )
-{
- KeyAlternate aAlternate;
-
- switch( nKeyCode )
- {
- case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break;
- case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break;
- }
-
- return aAlternate;
-}
-
-#if GTK_CHECK_VERSION(3,0,0)
-static int debugQueuePureRedraw = 0;
-static int debugRedboxRedraws = 0;
-
-namespace {
-/// Decouple SalFrame lifetime from damagetracker lifetime
-struct DamageTracker : public basebmp::IBitmapDeviceDamageTracker
-{
- DamageTracker(GtkSalFrame& rFrame) : m_rFrame(rFrame)
- {}
-
- virtual ~DamageTracker() {}
-
- virtual void damaged(const basegfx::B2IBox& rDamageRect) const
- {
- m_rFrame.damaged(rDamageRect);
- }
-
- GtkSalFrame& m_rFrame;
-};
-}
-#endif
-
-void GtkSalFrame::doKeyCallback( guint state,
- guint keyval,
- guint16 hardware_keycode,
- guint8 /*group*/,
- guint32 time,
- sal_Unicode aOrigCode,
- bool bDown,
- bool bSendRelease
- )
-{
- SalKeyEvent aEvent;
-
- aEvent.mnTime = time;
- aEvent.mnCharCode = aOrigCode;
- aEvent.mnRepeat = 0;
-
- vcl::DeletionListener aDel( this );
-
-#if GTK_CHECK_VERSION(3,0,0)
- // shift-zero forces a re-draw and event is swallowed
- if (keyval == GDK_0)
- {
- debugQueuePureRedraw += 2;
- fprintf( stderr, "force re-draw %d\n", debugQueuePureRedraw );
- gtk_widget_queue_draw (m_pWindow);
- return;
- }
- if (keyval == GDK_9)
- {
- debugRedboxRedraws = !debugRedboxRedraws;
- fprintf( stderr, "set redboxing to %d\n", debugRedboxRedraws );
- return;
- }
-#endif
-
- /* #i42122# translate all keys with Ctrl and/or Alt to group 0
- * else shortcuts (e.g. Ctrl-o) will not work but be inserted by
- * the application
- */
- /* #i52338# do this for all keys that the independent part has no key code for
- */
- aEvent.mnCode = GetKeyCode( keyval );
- if( aEvent.mnCode == 0 )
- {
- // check other mapping
- gint eff_group, level;
- GdkModifierType consumed;
- guint updated_keyval = 0;
- // use gdk_keymap_get_default instead of NULL;
- // workaround a crahs fixed in gtk 2.4
- if( gdk_keymap_translate_keyboard_state( gdk_keymap_get_default(),
- hardware_keycode,
- (GdkModifierType)0,
- 0,
- &updated_keyval,
- &eff_group,
- &level,
- &consumed ) )
- {
- aEvent.mnCode = GetKeyCode( updated_keyval );
- }
- }
- aEvent.mnCode |= GetKeyModCode( state );
-
- if( bDown )
- {
- bool bHandled = CallCallback( SALEVENT_KEYINPUT, &aEvent );
- // #i46889# copy AlternatKeyCode handling from generic plugin
- if( ! bHandled )
- {
- KeyAlternate aAlternate = GetAlternateKeyCode( aEvent.mnCode );
- if( aAlternate.nKeyCode )
- {
- aEvent.mnCode = aAlternate.nKeyCode;
- if( aAlternate.nCharCode )
- aEvent.mnCharCode = aAlternate.nCharCode;
- bHandled = CallCallback( SALEVENT_KEYINPUT, &aEvent );
- }
- }
- if( bSendRelease && ! aDel.isDeleted() )
- {
- CallCallback( SALEVENT_KEYUP, &aEvent );
- }
- }
- else
- CallCallback( SALEVENT_KEYUP, &aEvent );
-}
-
-GtkSalFrame::GraphicsHolder::~GraphicsHolder()
-{
- delete pGraphics;
-}
-
-GtkSalFrame::GtkSalFrame( SalFrame* pParent, sal_uLong nStyle )
- : m_nXScreen( getDisplay()->GetDefaultXScreen() )
-{
- getDisplay()->registerFrame( this );
- m_nDuringRender = 0;
- m_bDefaultPos = true;
- m_bDefaultSize = ( (nStyle & SAL_FRAME_STYLE_SIZEABLE) && ! pParent );
- m_bWindowIsGtkPlug = false;
- Init( pParent, nStyle );
-}
-
-GtkSalFrame::GtkSalFrame( SystemParentData* pSysData )
- : m_nXScreen( getDisplay()->GetDefaultXScreen() )
-{
- getDisplay()->registerFrame( this );
- // permanently ignore errors from our unruly children ...
- GetGenericData()->ErrorTrapPush();
- m_bDefaultPos = true;
- m_bDefaultSize = true;
- Init( pSysData );
-}
-
-#ifdef ENABLE_GMENU_INTEGRATION
-
-static void
-gdk_x11_window_set_utf8_property (GdkWindow *window,
- const gchar *name,
- const gchar *value)
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- GdkDisplay* display = gdk_window_get_display (window);
-
- if (value != NULL)
- {
- XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XID (window),
- gdk_x11_get_xatom_by_name_for_display (display, name),
- gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
- PropModeReplace, (guchar *)value, strlen (value));
- }
- else
- {
- XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
- GDK_WINDOW_XID (window),
- gdk_x11_get_xatom_by_name_for_display (display, name));
- }
-#endif
-}
-
-// AppMenu watch functions.
-
-static void ObjectDestroyedNotify( gpointer data )
-{
- if ( data ) {
- g_object_unref( data );
- }
-}
-
-static void hud_activated( gboolean hud_active, gpointer user_data )
-{
- if ( hud_active )
- {
- SolarMutexGuard aGuard;
- GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( user_data );
- GtkSalMenu* pSalMenu = reinterpret_cast< GtkSalMenu* >( pSalFrame->GetMenu() );
-
- if ( pSalMenu )
- pSalMenu->UpdateFull();
- }
-}
-
-gboolean ensure_dbus_setup( gpointer data )
-{
- GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( data );
- GdkWindow* gdkWindow = gtk_widget_get_window( pSalFrame->getWindow() );
-
- if ( gdkWindow != NULL && g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) == NULL )
- {
- // Get a DBus session connection.
- if(!pSessionBus)
- pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
- if( !pSessionBus )
- return FALSE;
-
- // Create menu model and action group attached to this frame.
- GMenuModel* pMenuModel = G_MENU_MODEL( g_lo_menu_new() );
- GActionGroup* pActionGroup = ( ( GActionGroup* ) g_lo_action_group_new( reinterpret_cast< gpointer >( pSalFrame ) ) );
-
- // Generate menu paths.
- XLIB_Window windowId = GDK_WINDOW_XID( gdkWindow );
- gchar* aDBusPath = g_strdup_printf("/window/%lu", windowId);
- gchar* aDBusWindowPath = g_strdup_printf( "/window/%lu", windowId );
- gchar* aDBusMenubarPath = g_strdup_printf( "/window/%lu/menus/menubar", windowId );
-
- // Set window properties.
- g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-menubar", pMenuModel, ObjectDestroyedNotify );
- g_object_set_data_full( G_OBJECT( gdkWindow ), "g-lo-action-group", pActionGroup, ObjectDestroyedNotify );
-
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_UNIQUE_BUS_NAME", g_dbus_connection_get_unique_name( pSessionBus ) );
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_APPLICATION_OBJECT_PATH", "" );
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_WINDOW_OBJECT_PATH", aDBusWindowPath );
- gdk_x11_window_set_utf8_property( gdkWindow, "_GTK_MENUBAR_OBJECT_PATH", aDBusMenubarPath );
-
- // Publish the menu model and the action group.
- SAL_INFO("vcl.unity", "exporting menu model at " << pMenuModel << " for window " << windowId);
- pSalFrame->m_nMenuExportId = g_dbus_connection_export_menu_model (pSessionBus, aDBusMenubarPath, pMenuModel, NULL);
- pSalFrame->m_nActionGroupExportId = g_dbus_connection_export_action_group( pSessionBus, aDBusPath, pActionGroup, NULL);
- pSalFrame->m_nHudAwarenessId = hud_awareness_register( pSessionBus, aDBusMenubarPath, hud_activated, pSalFrame, NULL, NULL );
-
- g_free( aDBusPath );
- g_free( aDBusWindowPath );
- g_free( aDBusMenubarPath );
- }
-
- return FALSE;
-}
-
-void on_registrar_available( GDBusConnection * /*connection*/,
- const gchar * /*name*/,
- const gchar * /*name_owner*/,
- gpointer user_data )
-{
- SolarMutexGuard aGuard;
-
- GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( user_data );
-
- SalMenu* pSalMenu = pSalFrame->GetMenu();
-
- if ( pSalMenu != NULL )
- {
- GtkSalMenu* pGtkSalMenu = static_cast<GtkSalMenu*>(pSalMenu);
- pGtkSalMenu->Display( sal_True );
- pGtkSalMenu->UpdateFull();
- }
-}
-
-// This is called when the registrar becomes unavailable. It shows the menubar.
-void on_registrar_unavailable( GDBusConnection * /*connection*/,
- const gchar * /*name*/,
- gpointer user_data )
-{
- SolarMutexGuard aGuard;
-
- SAL_INFO("vcl.unity", "on_registrar_unavailable");
-
- //pSessionBus = NULL;
- GtkSalFrame* pSalFrame = reinterpret_cast< GtkSalFrame* >( user_data );
-
- SalMenu* pSalMenu = pSalFrame->GetMenu();
-
- if ( pSalMenu ) {
- GtkSalMenu* pGtkSalMenu = static_cast< GtkSalMenu* >( pSalMenu );
- pGtkSalMenu->Display( sal_False );
- }
-}
-#endif
-
-void GtkSalFrame::EnsureAppMenuWatch()
-{
-#ifdef ENABLE_GMENU_INTEGRATION
- if ( !m_nWatcherId )
- {
- // Get a DBus session connection.
- if ( pSessionBus == NULL )
- {
- pSessionBus = g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, NULL );
-
- if ( pSessionBus == NULL )
- return;
- }
-
- // Publish the menu only if AppMenu registrar is available.
- m_nWatcherId = g_bus_watch_name_on_connection( pSessionBus,
- "com.canonical.AppMenu.Registrar",
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- on_registrar_available,
- on_registrar_unavailable,
- static_cast<GtkSalFrame*>(this),
- NULL );
- }
-
- //ensure_dbus_setup( this );
-#endif
-}
-
-GtkSalFrame::~GtkSalFrame()
-{
- for( unsigned int i = 0; i < SAL_N_ELEMENTS(m_aGraphics); ++i )
- {
- if( !m_aGraphics[i].pGraphics )
- continue;
-#if !GTK_CHECK_VERSION(3,0,0)
- m_aGraphics[i].pGraphics->SetDrawable( None, m_nXScreen );
-#endif
- m_aGraphics[i].bInUse = false;
- }
-
- if( m_pParent )
- m_pParent->m_aChildren.remove( this );
-
- getDisplay()->deregisterFrame( this );
-
- if( m_pRegion )
- {
-#if GTK_CHECK_VERSION(3,0,0)
- cairo_region_destroy( m_pRegion );
-#else
- gdk_region_destroy( m_pRegion );
-#endif
- }
-
-#if !GTK_CHECK_VERSION(3,0,0)
- if( m_hBackgroundPixmap )
- {
- XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
- widget_get_xid(m_pWindow),
- None );
- XFreePixmap( getDisplay()->GetDisplay(), m_hBackgroundPixmap );
- }
-#endif
-
- if( m_pIMHandler )
- delete m_pIMHandler;
-
- if( m_pFixedContainer )
- gtk_widget_destroy( GTK_WIDGET( m_pFixedContainer ) );
- {
- SolarMutexGuard aGuard;
-#if defined ENABLE_GMENU_INTEGRATION
- if(m_nWatcherId)
- g_bus_unwatch_name(m_nWatcherId);
-#endif
- if( m_pWindow )
- {
- g_object_set_data( G_OBJECT( m_pWindow ), "SalFrame", NULL );
-
-#if defined ENABLE_GMENU_INTEGRATION
- if ( pSessionBus )
- {
- if ( m_nHudAwarenessId )
- hud_awareness_unregister( pSessionBus, m_nHudAwarenessId );
- if ( m_nMenuExportId )
- g_dbus_connection_unexport_menu_model( pSessionBus, m_nMenuExportId );
- if ( m_nActionGroupExportId )
- g_dbus_connection_unexport_action_group( pSessionBus, m_nActionGroupExportId );
- }
-#endif
- gtk_widget_destroy( m_pWindow );
- }
- }
- if( m_pForeignParent )
- g_object_unref( G_OBJECT( m_pForeignParent ) );
- if( m_pForeignTopLevel )
- g_object_unref( G_OBJECT( m_pForeignTopLevel) );
-}
-
-void GtkSalFrame::moveWindow( long nX, long nY )
-{
- if( isChild( false, true ) )
- {
- if( m_pParent )
- gtk_fixed_move( m_pParent->getFixedContainer(),
- m_pWindow,
- nX - m_pParent->maGeometry.nX, nY - m_pParent->maGeometry.nY );
- }
- else
- gtk_window_move( GTK_WINDOW(m_pWindow), nX, nY );
-}
-
-void GtkSalFrame::resizeWindow( long nWidth, long nHeight )
-{
- if( isChild( false, true ) )
- gtk_widget_set_size_request( m_pWindow, nWidth, nHeight );
- else if( ! isChild( true, false ) )
- gtk_window_resize( GTK_WINDOW(m_pWindow), nWidth, nHeight );
-}
-
-/*
- * Always use a sub-class of GtkFixed we can tag for a11y. This allows us to
- * utilize GAIL for the toplevel window and toolkit implementation incl.
- * key event listener support ..
- */
-
-GType
-ooo_fixed_get_type()
-{
- static GType type = 0;
-
- if (!type) {
- static const GTypeInfo tinfo =
- {
- sizeof (GtkFixedClass),
- (GBaseInitFunc) NULL, /* base init */
- (GBaseFinalizeFunc) NULL, /* base finalize */
- (GClassInitFunc) NULL, /* class init */
- (GClassFinalizeFunc) NULL, /* class finalize */
- NULL, /* class data */
- sizeof (GtkFixed), /* instance size */
- 0, /* nb preallocs */
- (GInstanceInitFunc) NULL, /* instance init */
- NULL /* value table */
- };
-
- type = g_type_register_static( GTK_TYPE_FIXED, "OOoFixed",
- &tinfo, (GTypeFlags) 0);
- }
-
- return type;
-}
-
-void GtkSalFrame::updateScreenNumber()
-{
- int nScreen = 0;
- GdkScreen *pScreen = gtk_widget_get_screen( m_pWindow );
- if( pScreen )
- nScreen = getDisplay()->getSystem()->getScreenMonitorIdx( pScreen, maGeometry.nX, maGeometry.nY );
- maGeometry.nDisplayScreenNumber = nScreen;
-}
-
-void GtkSalFrame::InitCommon()
-{
- // connect signals
- g_signal_connect( G_OBJECT(m_pWindow), "style-set", G_CALLBACK(signalStyleSet), this );
- g_signal_connect( G_OBJECT(m_pWindow), "button-press-event", G_CALLBACK(signalButton), this );
- g_signal_connect( G_OBJECT(m_pWindow), "button-release-event", G_CALLBACK(signalButton), this );
-#if GTK_CHECK_VERSION(3,0,0)
- g_signal_connect( G_OBJECT(m_pWindow), "draw", G_CALLBACK(signalDraw), this );
-#else
- g_signal_connect( G_OBJECT(m_pWindow), "expose-event", G_CALLBACK(signalExpose), this );
-#endif
- g_signal_connect( G_OBJECT(m_pWindow), "focus-in-event", G_CALLBACK(signalFocus), this );
- g_signal_connect( G_OBJECT(m_pWindow), "focus-out-event", G_CALLBACK(signalFocus), this );
- g_signal_connect( G_OBJECT(m_pWindow), "map-event", G_CALLBACK(signalMap), this );
- g_signal_connect( G_OBJECT(m_pWindow), "unmap-event", G_CALLBACK(signalUnmap), this );
- g_signal_connect( G_OBJECT(m_pWindow), "configure-event", G_CALLBACK(signalConfigure), this );
- g_signal_connect( G_OBJECT(m_pWindow), "motion-notify-event", G_CALLBACK(signalMotion), this );
- g_signal_connect( G_OBJECT(m_pWindow), "key-press-event", G_CALLBACK(signalKey), this );
- g_signal_connect( G_OBJECT(m_pWindow), "key-release-event", G_CALLBACK(signalKey), this );
- g_signal_connect( G_OBJECT(m_pWindow), "delete-event", G_CALLBACK(signalDelete), this );
- g_signal_connect( G_OBJECT(m_pWindow), "window-state-event", G_CALLBACK(signalState), this );
- g_signal_connect( G_OBJECT(m_pWindow), "scroll-event", G_CALLBACK(signalScroll), this );
- g_signal_connect( G_OBJECT(m_pWindow), "leave-notify-event", G_CALLBACK(signalCrossing), this );
- g_signal_connect( G_OBJECT(m_pWindow), "enter-notify-event", G_CALLBACK(signalCrossing), this );
- g_signal_connect( G_OBJECT(m_pWindow), "visibility-notify-event", G_CALLBACK(signalVisibility), this );
- g_signal_connect( G_OBJECT(m_pWindow), "destroy", G_CALLBACK(signalDestroy), this );
-
- // init members
- m_pCurrentCursor = NULL;
- m_nKeyModifiers = 0;
- m_bFullscreen = false;
- m_nState = GDK_WINDOW_STATE_WITHDRAWN;
- m_nVisibility = GDK_VISIBILITY_FULLY_OBSCURED;
- m_bSendModChangeOnRelease = false;
- m_pIMHandler = NULL;
- m_hBackgroundPixmap = None;
- m_nSavedScreenSaverTimeout = 0;
- m_nGSMCookie = 0;
- m_nExtStyle = 0;
- m_pRegion = NULL;
- m_ePointerStyle = 0xffff;
- m_bSetFocusOnMap = false;
- m_pSalMenu = NULL;
- m_nWatcherId = 0;
- m_nMenuExportId = 0;
- m_nActionGroupExportId = 0;
- m_nHudAwarenessId = 0;
-
- gtk_widget_set_app_paintable( m_pWindow, TRUE );
- gtk_widget_set_double_buffered( m_pWindow, FALSE );
- gtk_widget_set_redraw_on_allocate( m_pWindow, FALSE );
-
- gtk_widget_add_events( m_pWindow,
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
- GDK_VISIBILITY_NOTIFY_MASK
- );
-
- // add the fixed container child,
- // fixed is needed since we have to position plugin windows
- m_pFixedContainer = GTK_FIXED(g_object_new( ooo_fixed_get_type(), NULL ));
- gtk_container_add( GTK_CONTAINER(m_pWindow), GTK_WIDGET(m_pFixedContainer) );
-
- // show the widgets
- gtk_widget_show( GTK_WIDGET(m_pFixedContainer) );
-
- // realize the window, we need an XWindow id
- gtk_widget_realize( m_pWindow );
-
- //system data
- m_aSystemData.nSize = sizeof( SystemChildData );
-#if !GTK_CHECK_VERSION(3,0,0)
- GtkSalDisplay* pDisp = GetGtkSalData()->GetGtkDisplay();
- m_aSystemData.pDisplay = pDisp->GetDisplay();
- m_aSystemData.pVisual = pDisp->GetVisual( m_nXScreen ).GetVisual();
- m_aSystemData.nDepth = pDisp->GetVisual( m_nXScreen ).GetDepth();
- m_aSystemData.aColormap = pDisp->GetColormap( m_nXScreen ).GetXColormap();
- m_aSystemData.aWindow = widget_get_xid(m_pWindow);
-#else
- static int nWindow = 0;
- m_aSystemData.aWindow = nWindow++;
-#endif
- m_aSystemData.pSalFrame = this;
- m_aSystemData.pWidget = m_pWindow;
- m_aSystemData.nScreen = m_nXScreen.getXScreen();
- m_aSystemData.pAppContext = NULL;
- m_aSystemData.aShellWindow = m_aSystemData.aWindow;
- m_aSystemData.pShellWidget = m_aSystemData.pWidget;
-
- // fake an initial geometry, gets updated via configure event or SetPosSize
- if( m_bDefaultPos || m_bDefaultSize )
- {
- Size aDefSize = calcDefaultSize();
- maGeometry.nX = -1;
- maGeometry.nY = -1;
- maGeometry.nWidth = aDefSize.Width();
- maGeometry.nHeight = aDefSize.Height();
- if( m_pParent )
- {
- // approximation
- maGeometry.nTopDecoration = m_pParent->maGeometry.nTopDecoration;
- maGeometry.nBottomDecoration = m_pParent->maGeometry.nBottomDecoration;
- maGeometry.nLeftDecoration = m_pParent->maGeometry.nLeftDecoration;
- maGeometry.nRightDecoration = m_pParent->maGeometry.nRightDecoration;
- }
- else
- {
- maGeometry.nTopDecoration = 0;
- maGeometry.nBottomDecoration = 0;
- maGeometry.nLeftDecoration = 0;
- maGeometry.nRightDecoration = 0;
- }
- }
- else
- {
- resizeWindow( maGeometry.nWidth, maGeometry.nHeight );
- moveWindow( maGeometry.nX, maGeometry.nY );
- }
- updateScreenNumber();
-
- SetIcon(1);
-
-#if !GTK_CHECK_VERSION(3,0,0)
- m_nWorkArea = pDisp->getWMAdaptor()->getCurrentWorkArea();
- /* #i64117# gtk sets a nice background pixmap
- * but we actually don't really want that, so save
- * some time on the Xserver as well as prevent
- * some paint issues
- */
- XSetWindowBackgroundPixmap( getDisplay()->GetDisplay(),
- widget_get_xid(m_pWindow),
- m_hBackgroundPixmap );
-#endif
-}
-
-/* Sadly gtk_window_set_accept_focus exists only since gtk 2.4
- * for achieving the same effect we will remove the WM_TAKE_FOCUS
- * protocol from the window and set the input hint to false.
- * But gtk_window_set_accept_focus needs to be called before
- * window realization whereas the removal obviously can only happen
- * after realization.
- */
-
-#if !GTK_CHECK_VERSION(3,0,0)
-extern "C" {
- typedef void(*setAcceptFn)( GtkWindow*, gboolean );
- static setAcceptFn p_gtk_window_set_accept_focus = NULL;
- static bool bGetAcceptFocusFn = true;
-
- typedef void(*setUserTimeFn)( GdkWindow*, guint32 );
- static setUserTimeFn p_gdk_x11_window_set_user_time = NULL;
- static bool bGetSetUserTimeFn = true;
-}
-#endif
-
-static void lcl_set_accept_focus( GtkWindow* pWindow, gboolean bAccept, bool bBeforeRealize )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- if( bGetAcceptFocusFn )
- {
- bGetAcceptFocusFn = false;
- p_gtk_window_set_accept_focus = (setAcceptFn)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gtk_window_set_accept_focus" );
- }
- if( p_gtk_window_set_accept_focus && bBeforeRealize )
- p_gtk_window_set_accept_focus( pWindow, bAccept );
- else if( ! bBeforeRealize )
- {
- Display* pDisplay = GetGtkSalData()->GetGtkDisplay()->GetDisplay();
- XLIB_Window aWindow = widget_get_xid(GTK_WIDGET(pWindow));
- XWMHints* pHints = XGetWMHints( pDisplay, aWindow );
- if( ! pHints )
- {
- pHints = XAllocWMHints();
- pHints->flags = 0;
- }
- pHints->flags |= InputHint;
- pHints->input = bAccept ? True : False;
- XSetWMHints( pDisplay, aWindow, pHints );
- XFree( pHints );
-
- if (GetGtkSalData()->GetGtkDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii("compiz"))
- return;
-
- /* remove WM_TAKE_FOCUS protocol; this would usually be the
- * right thing, but gtk handles it internally whereas we
- * want to handle it ourselves (as to sometimes not get
- * the focus)
- */
- Atom* pProtocols = NULL;
- int nProtocols = 0;
- XGetWMProtocols( pDisplay,
- aWindow,
- &pProtocols, &nProtocols );
- if( pProtocols )
- {
- bool bSet = false;
- Atom nTakeFocus = XInternAtom( pDisplay, "WM_TAKE_FOCUS", True );
- if( nTakeFocus )
- {
- for( int i = 0; i < nProtocols; i++ )
- {
- if( pProtocols[i] == nTakeFocus )
- {
- for( int n = i; n < nProtocols-1; n++ )
- pProtocols[n] = pProtocols[n+1];
- nProtocols--;
- i--;
- bSet = true;
- }
- }
- }
- if( bSet )
- XSetWMProtocols( pDisplay, aWindow, pProtocols, nProtocols );
- XFree( pProtocols );
- }
- }
-#else
- (void)pWindow; (void)bAccept; (void)bBeforeRealize;
-# warning FIXME: No set_accept_focus impl
-#endif
-}
-
-static void lcl_set_user_time( GtkWindow* i_pWindow, guint32 i_nTime )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- if( bGetSetUserTimeFn )
- {
- bGetSetUserTimeFn = false;
- p_gdk_x11_window_set_user_time = (setUserTimeFn)osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_x11_window_set_user_time" );
- }
- if( p_gdk_x11_window_set_user_time )
- p_gdk_x11_window_set_user_time( widget_get_window(GTK_WIDGET(i_pWindow)), i_nTime );
- else
- {
- Display* pDisplay = GetGtkSalData()->GetGtkDisplay()->GetDisplay();
- Atom nUserTime = XInternAtom( pDisplay, "_NET_WM_USER_TIME", True );
- if( nUserTime )
- {
- XChangeProperty( pDisplay, widget_get_xid(GTK_WIDGET(i_pWindow)),
- nUserTime, XA_CARDINAL, 32,
- PropModeReplace, (unsigned char*)&i_nTime, 1 );
- }
- }
-#else
- (void)i_pWindow; (void)i_nTime;
-# warning FIXME: no lcl_set_user_time impl.
-#endif
-};
-
-GtkSalFrame *GtkSalFrame::getFromWindow( GtkWindow *pWindow )
-{
- return (GtkSalFrame *) g_object_get_data( G_OBJECT( pWindow ), "SalFrame" );
-}
-
-void GtkSalFrame::Init( SalFrame* pParent, sal_uLong nStyle )
-{
- if( nStyle & SAL_FRAME_STYLE_DEFAULT ) // ensure default style
- {
- nStyle |= SAL_FRAME_STYLE_MOVEABLE | SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_CLOSEABLE;
- nStyle &= ~SAL_FRAME_STYLE_FLOAT;
- }
-
- m_pParent = static_cast<GtkSalFrame*>(pParent);
- m_pForeignParent = NULL;
- m_aForeignParentWindow = None;
- m_pForeignTopLevel = NULL;
- m_aForeignTopLevelWindow = None;
- m_nStyle = nStyle;
-
- GtkWindowType eWinType = ( (nStyle & SAL_FRAME_STYLE_FLOAT) &&
- ! (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|
- SAL_FRAME_STYLE_FLOAT_FOCUSABLE))
- )
- ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL;
-
- if( nStyle & SAL_FRAME_STYLE_SYSTEMCHILD )
- {
- m_pWindow = gtk_event_box_new();
- if( m_pParent )
- {
- // insert into container
- gtk_fixed_put( m_pParent->getFixedContainer(),
- m_pWindow, 0, 0 );
-
- }
- }
- else
- m_pWindow = gtk_widget_new( GTK_TYPE_WINDOW, "type", eWinType,
- "visible", FALSE, NULL );
- g_object_set_data( G_OBJECT( m_pWindow ), "SalFrame", this );
- g_object_set_data( G_OBJECT( m_pWindow ), "libo-version", (gpointer)LIBO_VERSION_DOTTED);
-
- // force wm class hint
- m_nExtStyle = ~0;
- if (m_pParent)
- m_sWMClass = m_pParent->m_sWMClass;
- SetExtendedFrameStyle( 0 );
-
- if( m_pParent && m_pParent->m_pWindow && ! isChild() )
- gtk_window_set_screen( GTK_WINDOW(m_pWindow), gtk_window_get_screen( GTK_WINDOW(m_pParent->m_pWindow) ) );
-
- // set window type
- bool bDecoHandling =
- ! isChild() &&
- ( ! (nStyle & SAL_FRAME_STYLE_FLOAT) ||
- (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_FLOAT_FOCUSABLE) ) );
-
- if( bDecoHandling )
- {
- GdkWindowTypeHint eType = GDK_WINDOW_TYPE_HINT_NORMAL;
- if( (nStyle & SAL_FRAME_STYLE_DIALOG) && m_pParent != 0 )
- eType = GDK_WINDOW_TYPE_HINT_DIALOG;
- if( (nStyle & SAL_FRAME_STYLE_INTRO) )
- {
- gtk_window_set_role( GTK_WINDOW(m_pWindow), "splashscreen" );
- eType = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
- }
- else if( (nStyle & SAL_FRAME_STYLE_TOOLWINDOW ) )
- {
- eType = GDK_WINDOW_TYPE_HINT_UTILITY;
- gtk_window_set_skip_taskbar_hint( GTK_WINDOW(m_pWindow), true );
- }
- else if( (nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
- {
- eType = GDK_WINDOW_TYPE_HINT_TOOLBAR;
- lcl_set_accept_focus( GTK_WINDOW(m_pWindow), sal_False, true );
- }
- else if( (nStyle & SAL_FRAME_STYLE_FLOAT_FOCUSABLE) )
- {
- eType = GDK_WINDOW_TYPE_HINT_UTILITY;
- }
-#if !GTK_CHECK_VERSION(3,0,0)
- if( (nStyle & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN )
- && getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
- {
- eType = GDK_WINDOW_TYPE_HINT_TOOLBAR;
- gtk_window_set_keep_above( GTK_WINDOW(m_pWindow), true );
- }
-#endif
- gtk_window_set_type_hint( GTK_WINDOW(m_pWindow), eType );
- gtk_window_set_gravity( GTK_WINDOW(m_pWindow), GDK_GRAVITY_STATIC );
- if( m_pParent && ! (m_pParent->m_nStyle & SAL_FRAME_STYLE_PLUG) )
- gtk_window_set_transient_for( GTK_WINDOW(m_pWindow), GTK_WINDOW(m_pParent->m_pWindow) );
- }
- else if( (nStyle & SAL_FRAME_STYLE_FLOAT) )
- {
- gtk_window_set_type_hint( GTK_WINDOW(m_pWindow), GDK_WINDOW_TYPE_HINT_UTILITY );
- }
- if( m_pParent )
- m_pParent->m_aChildren.push_back( this );
-
- InitCommon();
-
-#if !GTK_CHECK_VERSION(3,0,0)
- if( eWinType == GTK_WINDOW_TOPLEVEL )
- {
-#ifdef ENABLE_GMENU_INTEGRATION
- // Enable DBus native menu if available.
- ensure_dbus_setup( this );
-#endif
-
- guint32 nUserTime = 0;
- if( (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 )
- {
- /* #i99360# ugly workaround an X11 library bug */
- nUserTime= getDisplay()->GetLastUserEventTime( true );
- }
- lcl_set_user_time(GTK_WINDOW(m_pWindow), nUserTime);
- }
-#endif
-
- if( bDecoHandling )
- {
- gtk_window_set_resizable( GTK_WINDOW(m_pWindow), (nStyle & SAL_FRAME_STYLE_SIZEABLE) ? sal_True : FALSE );
- if( ( (nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION)) ) )
- lcl_set_accept_focus( GTK_WINDOW(m_pWindow), sal_False, false );
- }
-}
-
-GdkNativeWindow GtkSalFrame::findTopLevelSystemWindow( GdkNativeWindow aWindow )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- XLIB_Window aRoot, aParent;
- XLIB_Window* pChildren;
- unsigned int nChildren;
- bool bBreak = false;
- do
- {
- pChildren = NULL;
- nChildren = 0;
- aParent = aRoot = None;
- XQueryTree( getDisplay()->GetDisplay(), aWindow,
- &aRoot, &aParent, &pChildren, &nChildren );
- XFree( pChildren );
- if( aParent != aRoot )
- aWindow = aParent;
- int nCount = 0;
- Atom* pProps = XListProperties( getDisplay()->GetDisplay(),
- aWindow,
- &nCount );
- for( int i = 0; i < nCount && ! bBreak; ++i )
- bBreak = (pProps[i] == XA_WM_HINTS);
- if( pProps )
- XFree( pProps );
- } while( aParent != aRoot && ! bBreak );
-
- return aWindow;
-#else
- (void)aWindow;
-# warning FIXME: no findToplevelSystemWindow
- return 0;
-#endif
-}
-
-void GtkSalFrame::Init( SystemParentData* pSysData )
-{
- m_pParent = NULL;
- m_aForeignParentWindow = (GdkNativeWindow)pSysData->aWindow;
- m_pForeignParent = NULL;
- m_aForeignTopLevelWindow = findTopLevelSystemWindow( (GdkNativeWindow)pSysData->aWindow );
- m_pForeignTopLevel = gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignTopLevelWindow );
- gdk_window_set_events( m_pForeignTopLevel, GDK_STRUCTURE_MASK );
-
- if( pSysData->nSize > sizeof(pSysData->nSize)+sizeof(pSysData->aWindow) && pSysData->bXEmbedSupport )
- {
-#if GTK_CHECK_VERSION(3,0,0)
- m_pWindow = gtk_plug_new_for_display( getGdkDisplay(), pSysData->aWindow );
-#else
- m_pWindow = gtk_plug_new( pSysData->aWindow );
-#endif
- m_bWindowIsGtkPlug = true;
- widget_set_can_default( m_pWindow, true );
- widget_set_can_focus( m_pWindow, true );
- gtk_widget_set_sensitive( m_pWindow, true );
- }
- else
- {
- m_pWindow = gtk_window_new( GTK_WINDOW_POPUP );
- m_bWindowIsGtkPlug = false;
- }
- m_nStyle = SAL_FRAME_STYLE_PLUG;
- InitCommon();
-
- m_pForeignParent = gdk_window_foreign_new_for_display( getGdkDisplay(), m_aForeignParentWindow );
- gdk_window_set_events( m_pForeignParent, GDK_STRUCTURE_MASK );
-
-#if !GTK_CHECK_VERSION(3,0,0)
- int x_ret, y_ret;
- unsigned int w, h, bw, d;
- XLIB_Window aRoot;
- XGetGeometry( getDisplay()->GetDisplay(), pSysData->aWindow,
- &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d );
- maGeometry.nWidth = w;
- maGeometry.nHeight = h;
- gtk_window_resize( GTK_WINDOW(m_pWindow), w, h );
- gtk_window_move( GTK_WINDOW(m_pWindow), 0, 0 );
- if( ! m_bWindowIsGtkPlug )
- {
- XReparentWindow( getDisplay()->GetDisplay(),
- widget_get_xid(m_pWindow),
- (XLIB_Window)pSysData->aWindow,
- 0, 0 );
- }
-#else
-#warning Handling embedded windows, is going to be fun ...
-#endif
-}
-
-void GtkSalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- XEvent aEvent;
-
- memset( &aEvent, 0, sizeof(aEvent) );
- aEvent.xclient.window = m_aForeignParentWindow;
- aEvent.xclient.type = ClientMessage;
- aEvent.xclient.message_type = getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED );
- aEvent.xclient.format = 32;
- aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime;
- aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS
- aEvent.xclient.data.l[2] = 0;
- aEvent.xclient.data.l[3] = 0;
- aEvent.xclient.data.l[4] = 0;
-
- GetGenericData()->ErrorTrapPush();
- XSendEvent( getDisplay()->GetDisplay(),
- m_aForeignParentWindow,
- False, NoEventMask, &aEvent );
- GetGenericData()->ErrorTrapPop();
-#else
- (void)i_nTimeCode;
-#warning FIXME: no askForXEmbedFocus for gtk3 yet
-#endif
-}
-
-void GtkSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
-{
- if( nStyle != m_nExtStyle && ! isChild() )
- {
- m_nExtStyle = nStyle;
- updateWMClass();
- }
-}
-
-SalGraphics* GtkSalFrame::GetGraphics()
-{
- if( m_pWindow )
- {
- for( int i = 0; i < nMaxGraphics; i++ )
- {
- if( ! m_aGraphics[i].bInUse )
- {
- m_aGraphics[i].bInUse = true;
- if( ! m_aGraphics[i].pGraphics )
- {
- m_aGraphics[i].pGraphics = new GtkSalGraphics( this, m_pWindow );
-#if GTK_CHECK_VERSION(3,0,0)
- if( !m_aFrame.get() )
- AllocateFrame();
- m_aGraphics[i].pGraphics->setDevice( m_aFrame );
-#else // common case:
- m_aGraphics[i].pGraphics->Init( this, widget_get_xid(m_pWindow),
- m_nXScreen );
-#endif
- }
- return m_aGraphics[i].pGraphics;
- }
- }
- }
-
- return NULL;
-}
-
-void GtkSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
-{
- for( int i = 0; i < nMaxGraphics; i++ )
- {
- if( m_aGraphics[i].pGraphics == pGraphics )
- {
- m_aGraphics[i].bInUse = false;
- break;
- }
- }
-}
-
-sal_Bool GtkSalFrame::PostEvent( void* pData )
-{
- getDisplay()->SendInternalEvent( this, pData );
- return sal_True;
-}
-
-void GtkSalFrame::SetTitle( const OUString& rTitle )
-{
- m_aTitle = rTitle;
- if( m_pWindow && ! isChild() )
- gtk_window_set_title( GTK_WINDOW(m_pWindow), OUStringToOString( rTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
-}
-
-static inline sal_uInt8 *
-getRow( BitmapBuffer *pBuffer, sal_uLong nRow )
-{
- if( BMP_SCANLINE_ADJUSTMENT( pBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
- return pBuffer->mpBits + nRow * pBuffer->mnScanlineSize;
- else
- return pBuffer->mpBits + ( pBuffer->mnHeight - nRow - 1 ) * pBuffer->mnScanlineSize;
-}
-
-static GdkPixbuf *
-bitmapToPixbuf( SalBitmap *pSalBitmap, SalBitmap *pSalAlpha )
-{
- g_return_val_if_fail( pSalBitmap != NULL, NULL );
- g_return_val_if_fail( pSalAlpha != NULL, NULL );
-
- BitmapBuffer *pBitmap = pSalBitmap->AcquireBuffer( sal_True );
- g_return_val_if_fail( pBitmap != NULL, NULL );
- g_return_val_if_fail( pBitmap->mnBitCount == 24, NULL );
-
- BitmapBuffer *pAlpha = pSalAlpha->AcquireBuffer( sal_True );
- g_return_val_if_fail( pAlpha != NULL, NULL );
- g_return_val_if_fail( pAlpha->mnBitCount == 8, NULL );
-
- Size aSize = pSalBitmap->GetSize();
- g_return_val_if_fail( pSalAlpha->GetSize() == aSize, NULL );
-
- int nX, nY;
- guchar *pPixbufData = (guchar *)g_malloc (4 * aSize.Width() * aSize.Height() );
- guchar *pDestData = pPixbufData;
-
- for( nY = 0; nY < pBitmap->mnHeight; nY++ )
- {
- sal_uInt8 *pData = getRow( pBitmap, nY );
- sal_uInt8 *pAlphaData = getRow( pAlpha, nY );
-
- for( nX = 0; nX < pBitmap->mnWidth; nX++ )
- {
- if( pBitmap->mnFormat == BMP_FORMAT_24BIT_TC_BGR )
- {
- pDestData[2] = *pData++;
- pDestData[1] = *pData++;
- pDestData[0] = *pData++;
- }
- else // BMP_FORMAT_24BIT_TC_RGB
- {
- pDestData[0] = *pData++;
- pDestData[1] = *pData++;
- pDestData[2] = *pData++;
- }
- pDestData += 3;
- *pDestData++ = 255 - *pAlphaData++;
- }
- }
-
- pSalBitmap->ReleaseBuffer( pBitmap, sal_True );
- pSalAlpha->ReleaseBuffer( pAlpha, sal_True );
-
- return gdk_pixbuf_new_from_data( pPixbufData,
- GDK_COLORSPACE_RGB, sal_True, 8,
- aSize.Width(), aSize.Height(),
- aSize.Width() * 4,
- (GdkPixbufDestroyNotify) g_free,
- NULL );
-}
-
-void GtkSalFrame::SetIcon( sal_uInt16 nIcon )
-{
- if( (m_nStyle & (SAL_FRAME_STYLE_PLUG|SAL_FRAME_STYLE_SYSTEMCHILD|SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_INTRO|SAL_FRAME_STYLE_OWNERDRAWDECORATION))
- || ! m_pWindow )
- return;
-
- if( !ImplGetResMgr() )
- return;
-
- GdkPixbuf *pBuf;
- GList *pIcons = NULL;
-
- sal_uInt16 nOffsets[2] = { SV_ICON_SMALL_START, SV_ICON_LARGE_START };
- sal_uInt16 nIndex;
-
- for( nIndex = 0; nIndex < sizeof(nOffsets)/ sizeof(sal_uInt16); nIndex++ )
- {
- // #i44723# workaround gcc temporary problem
- ResId aResId( nOffsets[nIndex] + nIcon, *ImplGetResMgr() );
- BitmapEx aIcon( aResId );
-
- // #i81083# convert to 24bit/8bit alpha bitmap
- Bitmap aBmp = aIcon.GetBitmap();
- if( aBmp.GetBitCount() != 24 || ! aIcon.IsAlpha() )
- {
- if( aBmp.GetBitCount() != 24 )
- aBmp.Convert( BMP_CONVERSION_24BIT );
- AlphaMask aMask;
- if( ! aIcon.IsAlpha() )
- {
- switch( aIcon.GetTransparentType() )
- {
- case TRANSPARENT_NONE:
- {
- sal_uInt8 nTrans = 0;
- aMask = AlphaMask( aBmp.GetSizePixel(), &nTrans );
- }
- break;
- case TRANSPARENT_COLOR:
- aMask = AlphaMask( aBmp.CreateMask( aIcon.GetTransparentColor() ) );
- break;
- case TRANSPARENT_BITMAP:
- aMask = AlphaMask( aIcon.GetMask() );
- break;
- default:
- OSL_FAIL( "unhandled transparent type" );
- break;
- }
- }
- else
- aMask = aIcon.GetAlpha();
- aIcon = BitmapEx( aBmp, aMask );
- }
-
- ImpBitmap *pIconImpBitmap = aIcon.ImplGetBitmapImpBitmap();
- ImpBitmap *pIconImpMask = aIcon.ImplGetMaskImpBitmap();
-
-
- if( pIconImpBitmap && pIconImpMask )
- {
- SalBitmap *pIconBitmap =
- pIconImpBitmap->ImplGetSalBitmap();
- SalBitmap *pIconMask =
- pIconImpMask->ImplGetSalBitmap();
-
- if( ( pBuf = bitmapToPixbuf( pIconBitmap, pIconMask ) ) )
- pIcons = g_list_prepend( pIcons, pBuf );
- }
- }
-
- gtk_window_set_icon_list( GTK_WINDOW(m_pWindow), pIcons );
-
- g_list_foreach( pIcons, (GFunc) g_object_unref, NULL );
- g_list_free( pIcons );
-}
-
-void GtkSalFrame::SetMenu( SalMenu* pSalMenu )
-{
-// if(m_pSalMenu)
-// {
-// static_cast<GtkSalMenu*>(m_pSalMenu)->DisconnectFrame();
-// }
- m_pSalMenu = pSalMenu;
-}
-
-SalMenu* GtkSalFrame::GetMenu( void )
-{
- return m_pSalMenu;
-}
-
-void GtkSalFrame::DrawMenuBar()
-{
-}
-
-void GtkSalFrame::Center()
-{
- long nX, nY;
-
- if( m_pParent )
- {
- nX = ((long)m_pParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2;
- nY = ((long)m_pParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2;
- }
- else
- {
- GdkScreen *pScreen = NULL;
- gint px, py;
- GdkModifierType nMask;
- gdk_display_get_pointer( getGdkDisplay(), &pScreen, &px, &py, &nMask );
- if( !pScreen )
- pScreen = gtk_widget_get_screen( m_pWindow );
-
- gint nMonitor;
- nMonitor = gdk_screen_get_monitor_at_point( pScreen, px, py );
-
- GdkRectangle aMonitor;
- gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aMonitor );
-
- nX = aMonitor.x + (aMonitor.width - (long)maGeometry.nWidth)/2;
- nY = aMonitor.y + (aMonitor.height - (long)maGeometry.nHeight)/2;
- }
- SetPosSize( nX, nY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y );
-}
-
-Size GtkSalFrame::calcDefaultSize()
-{
- return bestmaxFrameSizeForScreenSize(getDisplay()->GetScreenSize(GetDisplayScreen()));
-}
-
-void GtkSalFrame::SetDefaultSize()
-{
- Size aDefSize = calcDefaultSize();
-
- SetPosSize( 0, 0, aDefSize.Width(), aDefSize.Height(),
- SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
-
- if( (m_nStyle & SAL_FRAME_STYLE_DEFAULT) && m_pWindow )
- gtk_window_maximize( GTK_WINDOW(m_pWindow) );
-}
-
-static void initClientId()
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- static bool bOnce = false;
- if (!bOnce)
- {
- bOnce = true;
- const OString& rID = SessionManagerClient::getSessionID();
- if (!rID.isEmpty())
- gdk_set_sm_client_id(rID.getStr());
- }
-#else
- // No session management support for gtk3+ - this is now legacy.
-#endif
-}
-
-void GtkSalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate )
-{
- if( m_pWindow )
- {
-#if !GTK_CHECK_VERSION(3,0,0)
- if( m_pParent && (m_pParent->m_nStyle & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN)
- && getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
- gtk_window_set_keep_above( GTK_WINDOW(m_pWindow), bVisible );
-#endif
- if( bVisible )
- {
- initClientId();
- getDisplay()->startupNotificationCompleted();
-
- if( m_bDefaultPos )
- Center();
- if( m_bDefaultSize )
- SetDefaultSize();
- setMinMaxSize();
-
-#if !GTK_CHECK_VERSION(3,0,0)
- // #i45160# switch to desktop where a dialog with parent will appear
- if( m_pParent && m_pParent->m_nWorkArea != m_nWorkArea && IS_WIDGET_MAPPED(m_pParent->m_pWindow) )
- getDisplay()->getWMAdaptor()->switchToWorkArea( m_pParent->m_nWorkArea );
-#endif
-
- if( isFloatGrabWindow() &&
- m_pParent &&
- m_nFloats == 0 &&
- ! getDisplay()->GetCaptureFrame() )
- {
- /* #i63086#
- * outsmart Metacity's "focus:mouse" mode
- * which insists on taking the focus from the document
- * to the new float. Grab focus to parent frame BEFORE
- * showing the float (cannot grab it to the float
- * before show).
- */
- m_pParent->grabPointer( sal_True, sal_True );
- }
-
- guint32 nUserTime = 0;
- if( ! bNoActivate && (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_TOOLWINDOW)) == 0 )
- /* #i99360# ugly workaround an X11 library bug */
- nUserTime= getDisplay()->GetLastUserEventTime( true );
- //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
-
- //For these floating windows we don't want the main window to lose focus, and metacity has...
- // metacity-2.24.0/src/core/window.c
- //
- // if ((focus_window != NULL) && XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time))
- // "compare" window focus prevented by other activity
- //
- // where "compare" is this window
-
- // which leads to...
-
- // /* This happens for error dialogs or alerts; these need to remain on
- // * top, but it would be confusing to have its ancestor remain
- // * focused.
- // */
- // if (meta_window_is_ancestor_of_transient (focus_window, window))
- // "The focus window %s is an ancestor of the newly mapped "
- // "window %s which isn't being focused. Unfocusing the "
- // "ancestor.\n",
- //
- // i.e. having a time < that of the toplevel frame means that the toplevel frame gets unfocused.
- // awesome.
- if( nUserTime == 0 )
- {
- /* #i99360# ugly workaround an X11 library bug */
- nUserTime= getDisplay()->GetLastUserEventTime( true );
- //nUserTime = gdk_x11_get_server_time(GTK_WIDGET (m_pWindow)->window);
- }
- lcl_set_user_time(GTK_WINDOW(m_pWindow), nUserTime );
-
- if( ! bNoActivate && (m_nStyle & SAL_FRAME_STYLE_TOOLWINDOW) )
- m_bSetFocusOnMap = true;
-
- gtk_widget_show( m_pWindow );
-
- if( isFloatGrabWindow() )
- {
- m_nFloats++;
- if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 1 )
- grabPointer( sal_True, sal_True );
- // #i44068# reset parent's IM context
- if( m_pParent )
- m_pParent->EndExtTextInput(0);
- }
- if( m_bWindowIsGtkPlug )
- askForXEmbedFocus( 0 );
- }
- else
- {
- if( isFloatGrabWindow() )
- {
- m_nFloats--;
- if( ! getDisplay()->GetCaptureFrame() && m_nFloats == 0)
- grabPointer( sal_False );
- }
- gtk_widget_hide( m_pWindow );
- if( m_pIMHandler )
- m_pIMHandler->focusChanged( false );
- // flush here; there may be a very seldom race between
- // the display connection used for clipboard and our connection
- Flush();
- }
- CallCallback( SALEVENT_RESIZE, NULL );
- }
-}
-
-void GtkSalFrame::Enable( sal_Bool /*bEnable*/ )
-{
- // Not implemented by X11SalFrame either
-}
-
-void GtkSalFrame::setMinMaxSize()
-{
- /* #i34504# metacity (and possibly others) do not treat
- * _NET_WM_STATE_FULLSCREEN and max_width/height independently;
- * whether they should is undefined. So don't set the max size hint
- * for a full screen window.
- */
- if( m_pWindow && ! isChild() )
- {
- GdkGeometry aGeo;
- int aHints = 0;
- if( m_nStyle & SAL_FRAME_STYLE_SIZEABLE )
- {
- if( m_aMinSize.Width() && m_aMinSize.Height() && ! m_bFullscreen )
- {
- aGeo.min_width = m_aMinSize.Width();
- aGeo.min_height = m_aMinSize.Height();
- aHints |= GDK_HINT_MIN_SIZE;
- }
- if( m_aMaxSize.Width() && m_aMaxSize.Height() && ! m_bFullscreen )
- {
- aGeo.max_width = m_aMaxSize.Width();
- aGeo.max_height = m_aMaxSize.Height();
- aHints |= GDK_HINT_MAX_SIZE;
- }
- }
- else
- {
- if( ! m_bFullscreen )
- {
- aGeo.min_width = maGeometry.nWidth;
- aGeo.min_height = maGeometry.nHeight;
- aHints |= GDK_HINT_MIN_SIZE;
-
- aGeo.max_width = maGeometry.nWidth;
- aGeo.max_height = maGeometry.nHeight;
- aHints |= GDK_HINT_MAX_SIZE;
- }
- }
- if( m_bFullscreen && m_aMaxSize.Width() && m_aMaxSize.Height() )
- {
- aGeo.max_width = m_aMaxSize.Width();
- aGeo.max_height = m_aMaxSize.Height();
- aHints |= GDK_HINT_MAX_SIZE;
- }
- if( aHints )
- gtk_window_set_geometry_hints( GTK_WINDOW(m_pWindow),
- NULL,
- &aGeo,
- GdkWindowHints( aHints ) );
- }
-}
-
-void GtkSalFrame::SetMaxClientSize( long nWidth, long nHeight )
-{
- if( ! isChild() )
- {
- m_aMaxSize = Size( nWidth, nHeight );
- // Show does a setMinMaxSize
- if( IS_WIDGET_MAPPED( m_pWindow ) )
- setMinMaxSize();
- }
-}
-void GtkSalFrame::SetMinClientSize( long nWidth, long nHeight )
-{
- if( ! isChild() )
- {
- m_aMinSize = Size( nWidth, nHeight );
- if( m_pWindow )
- {
- gtk_widget_set_size_request( m_pWindow, nWidth, nHeight );
- // Show does a setMinMaxSize
- if( IS_WIDGET_MAPPED( m_pWindow ) )
- setMinMaxSize();
- }
- }
-}
-
-// FIXME: we should really be an SvpSalFrame sub-class, and
-// share their AllocateFrame !
-void GtkSalFrame::AllocateFrame()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- basegfx::B2IVector aFrameSize( maGeometry.nWidth, maGeometry.nHeight );
- if( ! m_aFrame.get() || m_aFrame->getSize() != aFrameSize )
- {
- if( aFrameSize.getX() == 0 )
- aFrameSize.setX( 1 );
- if( aFrameSize.getY() == 0 )
- aFrameSize.setY( 1 );
- m_aFrame = basebmp::createBitmapDevice( aFrameSize, true,
- basebmp::Format::TWENTYFOUR_BIT_TC_MASK );
- m_aFrame->setDamageTracker(
- basebmp::IBitmapDeviceDamageTrackerSharedPtr(new DamageTracker(*this)) );
- fprintf( stderr, "allocated m_aFrame size of %dx%d \n",
- (int)maGeometry.nWidth, (int)maGeometry.nHeight );
-
-#if OSL_DEBUG_LEVEL > 0 // set background to orange
- m_aFrame->clear( basebmp::Color( 255, 127, 0 ) );
-#endif
-
- // update device in existing graphics
- for( unsigned int i = 0; i < SAL_N_ELEMENTS( m_aGraphics ); ++i )
- {
- if( !m_aGraphics[i].pGraphics )
- continue;
- m_aGraphics[i].pGraphics->setDevice( m_aFrame );
- }
- }
-#endif
-}
-
-void GtkSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
-{
- if( !m_pWindow || isChild( true, false ) )
- return;
-
- bool bSized = false, bMoved = false;
-
- if( (nFlags & ( SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT )) &&
- (nWidth > 0 && nHeight > 0 ) // sometimes stupid things happen
- )
- {
- m_bDefaultSize = false;
-
- if( (unsigned long)nWidth != maGeometry.nWidth || (unsigned long)nHeight != maGeometry.nHeight )
- bSized = true;
- maGeometry.nWidth = nWidth;
- maGeometry.nHeight = nHeight;
-
- if( isChild( false, true ) )
- gtk_widget_set_size_request( m_pWindow, nWidth, nHeight );
- else if( ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) )
- gtk_window_resize( GTK_WINDOW(m_pWindow), nWidth, nHeight );
- setMinMaxSize();
- }
- else if( m_bDefaultSize )
- SetDefaultSize();
-
- m_bDefaultSize = false;
-
- if( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) )
- {
- if( m_pParent )
- {
- if( Application::GetSettings().GetLayoutRTL() )
- nX = m_pParent->maGeometry.nWidth-maGeometry.nWidth-1-nX;
- nX += m_pParent->maGeometry.nX;
- nY += m_pParent->maGeometry.nY;
- }
-
-#if GTK_CHECK_VERSION(3,0,0)
- // adjust position to avoid off screen windows
- // but allow toolbars to be positioned partly off screen by the user
- Size aScreenSize = getDisplay()->GetScreenSize( GetDisplayScreen() );
- if( ! (m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) )
- {
- if( nX < (long)maGeometry.nLeftDecoration )
- nX = maGeometry.nLeftDecoration;
- if( nY < (long)maGeometry.nTopDecoration )
- nY = maGeometry.nTopDecoration;
- if( (nX + (long)maGeometry.nWidth + (long)maGeometry.nRightDecoration) > (long)aScreenSize.Width() )
- nX = aScreenSize.Width() - maGeometry.nWidth - maGeometry.nRightDecoration;
- if( (nY + (long)maGeometry.nHeight + (long)maGeometry.nBottomDecoration) > (long)aScreenSize.Height() )
- nY = aScreenSize.Height() - maGeometry.nHeight - maGeometry.nBottomDecoration;
- }
- else
- {
- if( nX + (long)maGeometry.nWidth < 10 )
- nX = 10 - (long)maGeometry.nWidth;
- if( nY + (long)maGeometry.nHeight < 10 )
- nY = 10 - (long)maGeometry.nHeight;
- if( nX > (long)aScreenSize.Width() - 10 )
- nX = (long)aScreenSize.Width() - 10;
- if( nY > (long)aScreenSize.Height() - 10 )
- nY = (long)aScreenSize.Height() - 10;
- }
-#endif
-
- if( nX != maGeometry.nX || nY != maGeometry.nY )
- bMoved = true;
- maGeometry.nX = nX;
- maGeometry.nY = nY;
-
- m_bDefaultPos = false;
-
- moveWindow( maGeometry.nX, maGeometry.nY );
-
- updateScreenNumber();
- }
- else if( m_bDefaultPos )
- Center();
-
- m_bDefaultPos = false;
-
- if( bSized )
- AllocateFrame();
-
- if( bSized && ! bMoved )
- CallCallback( SALEVENT_RESIZE, NULL );
- else if( bMoved && ! bSized )
- CallCallback( SALEVENT_MOVE, NULL );
- else if( bMoved && bSized )
- CallCallback( SALEVENT_MOVERESIZE, NULL );
-}
-
-void GtkSalFrame::GetClientSize( long& rWidth, long& rHeight )
-{
- if( m_pWindow && !(m_nState & GDK_WINDOW_STATE_ICONIFIED) )
- {
- rWidth = maGeometry.nWidth;
- rHeight = maGeometry.nHeight;
- }
- else
- rWidth = rHeight = 0;
-}
-
-void GtkSalFrame::GetWorkArea( Rectangle& rRect )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- rRect = GetGtkSalData()->GetGtkDisplay()->getWMAdaptor()->getWorkArea( 0 );
-#else
- g_warning ("no get work area");
- rRect = Rectangle( 0, 0, 1024, 768 );
-#endif
-}
-
-SalFrame* GtkSalFrame::GetParent() const
-{
- return m_pParent;
-}
-
-void GtkSalFrame::SetWindowState( const SalFrameState* pState )
-{
- if( ! m_pWindow || ! pState || isChild( true, false ) )
- return;
-
- const sal_uLong nMaxGeometryMask =
- WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y |
- WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT |
- WINDOWSTATE_MASK_MAXIMIZED_X | WINDOWSTATE_MASK_MAXIMIZED_Y |
- WINDOWSTATE_MASK_MAXIMIZED_WIDTH | WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
-
- if( (pState->mnMask & WINDOWSTATE_MASK_STATE) &&
- ! ( m_nState & GDK_WINDOW_STATE_MAXIMIZED ) &&
- (pState->mnState & WINDOWSTATE_STATE_MAXIMIZED) &&
- (pState->mnMask & nMaxGeometryMask) == nMaxGeometryMask )
- {
- resizeWindow( pState->mnWidth, pState->mnHeight );
- moveWindow( pState->mnX, pState->mnY );
- m_bDefaultPos = m_bDefaultSize = false;
-
- maGeometry.nX = pState->mnMaximizedX;
- maGeometry.nY = pState->mnMaximizedY;
- maGeometry.nWidth = pState->mnMaximizedWidth;
- maGeometry.nHeight = pState->mnMaximizedHeight;
- updateScreenNumber();
- AllocateFrame();
-
- m_nState = GdkWindowState( m_nState | GDK_WINDOW_STATE_MAXIMIZED );
- m_aRestorePosSize = Rectangle( Point( pState->mnX, pState->mnY ),
- Size( pState->mnWidth, pState->mnHeight ) );
- CallCallback( SALEVENT_RESIZE, NULL );
- }
- else if( pState->mnMask & (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y |
- WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT ) )
- {
- sal_uInt16 nPosSizeFlags = 0;
- long nX = pState->mnX - (m_pParent ? m_pParent->maGeometry.nX : 0);
- long nY = pState->mnY - (m_pParent ? m_pParent->maGeometry.nY : 0);
- if( pState->mnMask & WINDOWSTATE_MASK_X )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_X;
- else
- nX = maGeometry.nX - (m_pParent ? m_pParent->maGeometry.nX : 0);
- if( pState->mnMask & WINDOWSTATE_MASK_Y )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_Y;
- else
- nY = maGeometry.nY - (m_pParent ? m_pParent->maGeometry.nY : 0);
- if( pState->mnMask & WINDOWSTATE_MASK_WIDTH )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_WIDTH;
- if( pState->mnMask & WINDOWSTATE_MASK_HEIGHT )
- nPosSizeFlags |= SAL_FRAME_POSSIZE_HEIGHT;
- SetPosSize( nX, nY, pState->mnWidth, pState->mnHeight, nPosSizeFlags );
- }
- if( pState->mnMask & WINDOWSTATE_MASK_STATE && ! isChild() )
- {
- if( pState->mnState & WINDOWSTATE_STATE_MAXIMIZED )
- gtk_window_maximize( GTK_WINDOW(m_pWindow) );
- else
- gtk_window_unmaximize( GTK_WINDOW(m_pWindow) );
- /* #i42379# there is no rollup state in GDK; and rolled up windows are
- * (probably depending on the WM) reported as iconified. If we iconify a
- * window here that was e.g. a dialog, then it will be unmapped but still
- * not be displayed in the task list, so it's an iconified window that
- * the user cannot get out of this state. So do not set the iconified state
- * on windows with a parent (that is transient frames) since these tend
- * to not be represented in an icon task list.
- */
- if( (pState->mnState & WINDOWSTATE_STATE_MINIMIZED)
- && ! m_pParent )
- gtk_window_iconify( GTK_WINDOW(m_pWindow) );
- else
- gtk_window_deiconify( GTK_WINDOW(m_pWindow) );
- }
-}
-
-sal_Bool GtkSalFrame::GetWindowState( SalFrameState* pState )
-{
- pState->mnState = WINDOWSTATE_STATE_NORMAL;
- pState->mnMask = WINDOWSTATE_MASK_STATE;
- // rollup ? gtk 2.2 does not seem to support the shaded state
- if( (m_nState & GDK_WINDOW_STATE_ICONIFIED) )
- pState->mnState |= WINDOWSTATE_STATE_MINIMIZED;
- if( m_nState & GDK_WINDOW_STATE_MAXIMIZED )
- {
- pState->mnState |= WINDOWSTATE_STATE_MAXIMIZED;
- pState->mnX = m_aRestorePosSize.Left();
- pState->mnY = m_aRestorePosSize.Top();
- pState->mnWidth = m_aRestorePosSize.GetWidth();
- pState->mnHeight = m_aRestorePosSize.GetHeight();
- pState->mnMaximizedX = maGeometry.nX;
- pState->mnMaximizedY = maGeometry.nY;
- pState->mnMaximizedWidth = maGeometry.nWidth;
- pState->mnMaximizedHeight = maGeometry.nHeight;
- pState->mnMask |= WINDOWSTATE_MASK_MAXIMIZED_X |
- WINDOWSTATE_MASK_MAXIMIZED_Y |
- WINDOWSTATE_MASK_MAXIMIZED_WIDTH |
- WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
- }
- else
- {
- pState->mnX = maGeometry.nX;
- pState->mnY = maGeometry.nY;
- pState->mnWidth = maGeometry.nWidth;
- pState->mnHeight = maGeometry.nHeight;
- }
- pState->mnMask |= WINDOWSTATE_MASK_X |
- WINDOWSTATE_MASK_Y |
- WINDOWSTATE_MASK_WIDTH |
- WINDOWSTATE_MASK_HEIGHT;
-
- return sal_True;
-}
-
-typedef enum {
- SET_RETAIN_SIZE,
- SET_FULLSCREEN,
- SET_UN_FULLSCREEN
-} SetType;
-
-void GtkSalFrame::SetScreen( unsigned int nNewScreen, int eType, Rectangle *pSize )
-{
- if( !m_pWindow )
- return;
-
- if (maGeometry.nDisplayScreenNumber == nNewScreen && eType == SET_RETAIN_SIZE)
- return;
-
- gint nMonitor;
- GdkScreen *pScreen = getDisplay()->getSystem()->getScreenMonitorFromIdx( nNewScreen, nMonitor );
-
- // Heavy lifting, need to move screen ...
- if( pScreen != gtk_widget_get_screen( m_pWindow ))
- gtk_window_set_screen( GTK_WINDOW( m_pWindow ), pScreen );
-
- gint nOldMonitor = gdk_screen_get_monitor_at_window(
- pScreen, widget_get_window( m_pWindow ) );
-#if OSL_DEBUG_LEVEL > 1
- if( nMonitor == nOldMonitor )
- g_warning( "An apparently pointless SetScreen - should we elide it ?" );
-#endif
-
- GdkRectangle aOldMonitor, aNewMonitor;
- gdk_screen_get_monitor_geometry( pScreen, nOldMonitor, &aOldMonitor );
- gdk_screen_get_monitor_geometry( pScreen, nMonitor, &aNewMonitor );
-
- bool bResize = false;
- bool bVisible = IS_WIDGET_MAPPED( m_pWindow );
- if( bVisible )
- Show( sal_False );
-
- maGeometry.nX = aNewMonitor.x + maGeometry.nX - aOldMonitor.x;
- maGeometry.nY = aNewMonitor.y + maGeometry.nY - aOldMonitor.y;
-
- if( eType == SET_FULLSCREEN )
- {
- maGeometry.nX = aNewMonitor.x;
- maGeometry.nY = aNewMonitor.y;
- maGeometry.nWidth = aNewMonitor.width;
- maGeometry.nHeight = aNewMonitor.height;
- m_nStyle |= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
- bResize = true;
-
- // #i110881# for the benefit of compiz set a max size here
- // else setting to fullscreen fails for unknown reasons
- m_aMaxSize.Width() = aNewMonitor.width+100;
- m_aMaxSize.Height() = aNewMonitor.height+100;
- }
-
- if( pSize && eType == SET_UN_FULLSCREEN )
- {
- maGeometry.nX = pSize->Left();
- maGeometry.nY = pSize->Top();
- maGeometry.nWidth = pSize->GetWidth();
- maGeometry.nHeight = pSize->GetHeight();
- m_nStyle &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
- bResize = true;
- }
-
- if (bResize)
- {
- // temporarily re-sizeable
- if( !(m_nStyle & SAL_FRAME_STYLE_SIZEABLE) )
- gtk_window_set_resizable( GTK_WINDOW(m_pWindow), TRUE );
- gtk_window_resize( GTK_WINDOW( m_pWindow ), maGeometry.nWidth, maGeometry.nHeight );
- }
-
- gtk_window_move( GTK_WINDOW( m_pWindow ), maGeometry.nX, maGeometry.nY );
-
-#if !GTK_CHECK_VERSION(3,0,0)
- // _NET_WM_STATE_FULLSCREEN (Metacity <-> KWin)
- if( ! getDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
-#endif
- {
- if( eType == SET_FULLSCREEN )
- gtk_window_fullscreen( GTK_WINDOW( m_pWindow ) );
- else if( eType == SET_UN_FULLSCREEN )
- gtk_window_unfullscreen( GTK_WINDOW( m_pWindow ) );
- }
- if( eType == SET_UN_FULLSCREEN &&
- !(m_nStyle & SAL_FRAME_STYLE_SIZEABLE) )
- gtk_window_set_resizable( GTK_WINDOW( m_pWindow ), FALSE );
-
- // FIXME: we should really let gtk+ handle our widget hierarchy ...
- if( m_pParent && gtk_widget_get_screen( m_pParent->m_pWindow ) != pScreen )
- SetParent( NULL );
- std::list< GtkSalFrame* > aChildren = m_aChildren;
- for( std::list< GtkSalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it )
- (*it)->SetScreen( nNewScreen, SET_RETAIN_SIZE );
-
- m_bDefaultPos = m_bDefaultSize = false;
- updateScreenNumber();
- CallCallback( SALEVENT_MOVERESIZE, NULL );
-
- if( bVisible )
- Show( sal_True );
-}
-
-void GtkSalFrame::SetScreenNumber( unsigned int nNewScreen )
-{
- SetScreen( nNewScreen, SET_RETAIN_SIZE );
-}
-
-void GtkSalFrame::updateWMClass()
-{
- OString aResClass = OUStringToOString(m_sWMClass, RTL_TEXTENCODING_ASCII_US);
- const char *pResClass = !aResClass.isEmpty() ? aResClass.getStr() :
- SalGenericSystem::getFrameClassName();
- Display *display;
-
- if (!getDisplay()->IsX11Display())
- return;
-
-#if GTK_CHECK_VERSION(3,0,0)
- display = GDK_DISPLAY_XDISPLAY(getGdkDisplay());
-#else
- display = getDisplay()->GetDisplay();
-#endif
-
- if( IS_WIDGET_REALIZED( m_pWindow ) )
- {
- XClassHint* pClass = XAllocClassHint();
- OString aResName = SalGenericSystem::getFrameResName( m_nExtStyle );
- pClass->res_name = const_cast<char*>(aResName.getStr());
- pClass->res_class = const_cast<char*>(pResClass);
- XSetClassHint( display,
- widget_get_xid(m_pWindow),
- pClass );
- XFree( pClass );
- }
-}
-
-void GtkSalFrame::SetApplicationID( const OUString &rWMClass )
-{
- if( rWMClass != m_sWMClass && ! isChild() )
- {
- m_sWMClass = rWMClass;
- updateWMClass();
-
- for( std::list< GtkSalFrame* >::iterator it = m_aChildren.begin(); it != m_aChildren.end(); ++it )
- (*it)->SetApplicationID(rWMClass);
- }
-}
-
-void GtkSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nScreen )
-{
- m_bFullscreen = bFullScreen;
-
- if( !m_pWindow || isChild() )
- return;
-
- if( bFullScreen )
- {
- m_aRestorePosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ),
- Size( maGeometry.nWidth, maGeometry.nHeight ) );
- SetScreen( nScreen, SET_FULLSCREEN );
- }
- else
- {
- SetScreen( nScreen, SET_UN_FULLSCREEN,
- !m_aRestorePosSize.IsEmpty() ? &m_aRestorePosSize : NULL );
- m_aRestorePosSize = Rectangle();
- }
-}
-
-/* definitions from xautolock.c (pl15) */
-#define XAUTOLOCK_DISABLE 1
-#define XAUTOLOCK_ENABLE 2
-
-void GtkSalFrame::setAutoLock( bool bLock )
-{
- if( isChild() || !getDisplay()->IsX11Display() )
- return;
-
- GdkScreen *pScreen = gtk_window_get_screen( GTK_WINDOW(m_pWindow) );
- GdkDisplay *pDisplay = gdk_screen_get_display( pScreen );
- GdkWindow *pRootWin = gdk_screen_get_root_window( pScreen );
-
- Atom nAtom = XInternAtom( GDK_DISPLAY_XDISPLAY( pDisplay ),
- "XAUTOLOCK_MESSAGE", False );
-
- int nMessage = bLock ? XAUTOLOCK_ENABLE : XAUTOLOCK_DISABLE;
-
- XChangeProperty( GDK_DISPLAY_XDISPLAY( pDisplay ),
- GDK_WINDOW_XID( pRootWin ),
- nAtom, XA_INTEGER,
- 8, PropModeReplace,
- (unsigned char*)&nMessage,
- sizeof( nMessage ) );
-}
-
-#ifdef ENABLE_DBUS
-/** cookie is returned as an unsigned integer */
-static guint
-dbus_inhibit_gsm (const gchar *appname,
- const gchar *reason,
- guint xid)
-{
- gboolean res;
- guint cookie;
- GError *error = NULL;
- DBusGProxy *proxy = NULL;
-
- /* get the DBUS session connection */
- DBusGConnection *session_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
- if (error != NULL) {
- g_debug ("DBUS cannot connect : %s", error->message);
- g_error_free (error);
- return -1;
- }
-
- /* get the proxy with gnome-session-manager */
- proxy = dbus_g_proxy_new_for_name (session_connection,
- GSM_DBUS_SERVICE,
- GSM_DBUS_PATH,
- GSM_DBUS_INTERFACE);
- if (proxy == NULL) {
- g_debug ("Could not get DBUS proxy: %s", GSM_DBUS_SERVICE);
- return -1;
- }
-
- res = dbus_g_proxy_call (proxy,
- "Inhibit", &error,
- G_TYPE_STRING, appname,
- G_TYPE_UINT, xid,
- G_TYPE_STRING, reason,
- G_TYPE_UINT, 8, //Inhibit the session being marked as idle
- G_TYPE_INVALID,
- G_TYPE_UINT, &cookie,
- G_TYPE_INVALID);
-
- /* check the return value */
- if (! res) {
- cookie = -1;
- g_debug ("Inhibit method failed");
- }
-
- /* check the error value */
- if (error != NULL) {
- g_debug ("Inhibit problem : %s", error->message);
- g_error_free (error);
- cookie = -1;
- }
-
- g_object_unref (G_OBJECT (proxy));
- return cookie;
-}
-
-static void
-dbus_uninhibit_gsm (guint cookie)
-{
- gboolean res;
- GError *error = NULL;
- DBusGProxy *proxy = NULL;
- DBusGConnection *session_connection = NULL;
-
- if (cookie == guint(-1)) {
- g_debug ("Invalid cookie");
- return;
- }
-
- /* get the DBUS session connection */
- session_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
- if (error) {
- g_debug ("DBUS cannot connect : %s", error->message);
- g_error_free (error);
- return;
- }
-
- /* get the proxy with gnome-session-manager */
- proxy = dbus_g_proxy_new_for_name (session_connection,
- GSM_DBUS_SERVICE,
- GSM_DBUS_PATH,
- GSM_DBUS_INTERFACE);
- if (proxy == NULL) {
- g_debug ("Could not get DBUS proxy: %s", GSM_DBUS_SERVICE);
- return;
- }
-
- res = dbus_g_proxy_call (proxy,
- "Uninhibit",
- &error,
- G_TYPE_UINT, cookie,
- G_TYPE_INVALID,
- G_TYPE_INVALID);
-
- /* check the return value */
- if (! res) {
- g_debug ("Uninhibit method failed");
- }
-
- /* check the error value */
- if (error != NULL) {
- g_debug ("Uninhibit problem : %s", error->message);
- g_error_free (error);
- cookie = -1;
- }
- g_object_unref (G_OBJECT (proxy));
-}
-#endif
-
-void GtkSalFrame::StartPresentation( sal_Bool bStart )
-{
- setAutoLock( !bStart );
-
- if( !getDisplay()->IsX11Display() )
- return;
-
-#if !GTK_CHECK_VERSION(3,0,0)
- Display *pDisplay = GDK_DISPLAY_XDISPLAY( getGdkDisplay() );
-
- int nTimeout, nInterval, bPreferBlanking, bAllowExposures;
- XGetScreenSaver( pDisplay, &nTimeout, &nInterval,
- &bPreferBlanking, &bAllowExposures );
-#endif
- if( bStart )
- {
-#if !GTK_CHECK_VERSION(3,0,0)
- if ( nTimeout )
- {
- m_nSavedScreenSaverTimeout = nTimeout;
- XResetScreenSaver( pDisplay );
- XSetScreenSaver( pDisplay, 0, nInterval,
- bPreferBlanking, bAllowExposures );
- }
-#endif
-#ifdef ENABLE_DBUS
- m_nGSMCookie = dbus_inhibit_gsm(g_get_application_name(), "presentation",
- widget_get_xid(m_pWindow));
-#endif
- }
- else
- {
-#if !GTK_CHECK_VERSION(3,0,0)
- if( m_nSavedScreenSaverTimeout )
- XSetScreenSaver( pDisplay, m_nSavedScreenSaverTimeout,
- nInterval, bPreferBlanking,
- bAllowExposures );
-#endif
- m_nSavedScreenSaverTimeout = 0;
-#ifdef ENABLE_DBUS
- dbus_uninhibit_gsm(m_nGSMCookie);
-#endif
- }
-}
-
-void GtkSalFrame::SetAlwaysOnTop( sal_Bool bOnTop )
-{
- if( m_pWindow )
- gtk_window_set_keep_above( GTK_WINDOW( m_pWindow ), bOnTop );
-}
-
-void GtkSalFrame::ToTop( sal_uInt16 nFlags )
-{
- if( m_pWindow )
- {
- if( isChild( false, true ) )
- gtk_widget_grab_focus( m_pWindow );
- else if( IS_WIDGET_MAPPED( m_pWindow ) )
- {
- if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) )
- gtk_window_present( GTK_WINDOW(m_pWindow) );
- else
- {
- /* #i99360# ugly workaround an X11 library bug */
- guint32 nUserTime= getDisplay()->GetLastUserEventTime( true );
- gdk_window_focus( widget_get_window(m_pWindow), nUserTime );
- }
-#if !GTK_CHECK_VERSION(3,0,0)
- /* need to do an XSetInputFocus here because
- * gdk_window_focus will ask a EWMH compliant WM to put the focus
- * to our window - which it of course won't since our input hint
- * is set to false.
- */
- if( (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION|SAL_FRAME_STYLE_FLOAT_FOCUSABLE)) )
- {
- // sad but true: this can cause an XError, we need to catch that
- // to do this we need to synchronize with the XServer
- GetGenericData()->ErrorTrapPush();
- XSetInputFocus( getDisplay()->GetDisplay(), widget_get_xid(m_pWindow), RevertToParent, CurrentTime );
- // fdo#46687 - an XSync should not be necessary - but for some reason it is.
- XSync( getDisplay()->GetDisplay(), False );
- GetGenericData()->ErrorTrapPop();
- }
-#endif
- }
- else
- {
- if( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN )
- gtk_window_present( GTK_WINDOW(m_pWindow) );
- }
- }
-}
-
-void GtkSalFrame::SetPointer( PointerStyle ePointerStyle )
-{
- if( m_pWindow && ePointerStyle != m_ePointerStyle )
- {
- m_ePointerStyle = ePointerStyle;
- GdkCursor *pCursor = getDisplay()->getCursor( ePointerStyle );
- gdk_window_set_cursor( widget_get_window(m_pWindow), pCursor );
- m_pCurrentCursor = pCursor;
-
- // #i80791# use grabPointer the same way as CaptureMouse, respective float grab
- if( getDisplay()->MouseCaptured( this ) )
- grabPointer( sal_True, sal_False );
- else if( m_nFloats > 0 )
- grabPointer( sal_True, sal_True );
- }
-}
-
-void GtkSalFrame::grabPointer( sal_Bool bGrab, sal_Bool bOwnerEvents )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- static const char* pEnv = getenv( "SAL_NO_MOUSEGRABS" );
-
- if( m_pWindow )
- {
- if( bGrab )
- {
- bool bUseGdkGrab = true;
- const std::list< SalFrame* >& rFrames = getDisplay()->getFrames();
- for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
- {
- const GtkSalFrame* pFrame = static_cast< const GtkSalFrame* >(*it);
- if( pFrame->m_bWindowIsGtkPlug )
- {
- bUseGdkGrab = false;
- break;
- }
- }
- if( bUseGdkGrab )
- {
- const int nMask = ( GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
-
- if( !pEnv || !*pEnv )
- gdk_pointer_grab( widget_get_window( m_pWindow ), bOwnerEvents,
- (GdkEventMask) nMask, NULL, m_pCurrentCursor,
- GDK_CURRENT_TIME );
- }
- else
- {
- // FIXME: for some unknown reason gdk_pointer_grab does not
- // really produce owner events for GtkPlug windows
- // the cause is yet unknown
- //
- // this is of course a bad hack, especially as we cannot
- // set the right cursor this way
- if( !pEnv || !*pEnv )
- XGrabPointer( getDisplay()->GetDisplay(),
- widget_get_xid( m_pWindow ),
- bOwnerEvents,
- PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
- GrabModeAsync,
- GrabModeAsync,
- None,
- None,
- CurrentTime
- );
-
- }
- }
- else
- {
- // Two GdkDisplays may be open
- if( !pEnv || !*pEnv )
- gdk_display_pointer_ungrab( getGdkDisplay(), GDK_CURRENT_TIME);
- }
- }
-#else
- (void)bGrab; (void) bOwnerEvents;
-#warning FIXME: No GrabPointer implementation for gtk3 ...
-#endif
-}
-
-void GtkSalFrame::CaptureMouse( sal_Bool bCapture )
-{
- getDisplay()->CaptureMouse( bCapture ? this : NULL );
-}
-
-void GtkSalFrame::SetPointerPos( long nX, long nY )
-{
- GtkSalFrame* pFrame = this;
- while( pFrame && pFrame->isChild( false, true ) )
- pFrame = pFrame->m_pParent;
- if( ! pFrame )
- return;
-
- GdkScreen *pScreen = gtk_window_get_screen( GTK_WINDOW(pFrame->m_pWindow) );
- GdkDisplay *pDisplay = gdk_screen_get_display( pScreen );
-
- /* when the application tries to center the mouse in the dialog the
- * window isn't mapped already. So use coordinates relative to the root window.
- */
- unsigned int nWindowLeft = maGeometry.nX + nX;
- unsigned int nWindowTop = maGeometry.nY + nY;
-
- XWarpPointer( GDK_DISPLAY_XDISPLAY (pDisplay), None,
- GDK_WINDOW_XID (gdk_screen_get_root_window( pScreen ) ),
- 0, 0, 0, 0, nWindowLeft, nWindowTop);
- // #i38648# ask for the next motion hint
- gint x, y;
- GdkModifierType mask;
- gdk_window_get_pointer( widget_get_window(pFrame->m_pWindow) , &x, &y, &mask );
-}
-
-void GtkSalFrame::Flush()
-{
-#if GTK_CHECK_VERSION(3,0,0)
- gdk_display_flush( getGdkDisplay() );
-#else
- XFlush (GDK_DISPLAY_XDISPLAY (getGdkDisplay()));
-#endif
-}
-
-void GtkSalFrame::Sync()
-{
- gdk_display_sync( getGdkDisplay() );
-}
-
-OUString GtkSalFrame::GetKeyName( sal_uInt16 nKeyCode )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- return getDisplay()->GetKeyName( nKeyCode );
-#else
- (void)nKeyCode;
-# warning FIXME - key names
- return OUString();
-#endif
-}
-
-GdkDisplay *GtkSalFrame::getGdkDisplay()
-{
- return GetGtkSalData()->GetGdkDisplay();
-}
-
-GtkSalDisplay *GtkSalFrame::getDisplay()
-{
- return GetGtkSalData()->GetGtkDisplay();
-}
-
-SalFrame::SalPointerState GtkSalFrame::GetPointerState()
-{
- SalPointerState aState;
- GdkScreen* pScreen;
- gint x, y;
- GdkModifierType aMask;
- gdk_display_get_pointer( getGdkDisplay(), &pScreen, &x, &y, &aMask );
- aState.maPos = Point( x - maGeometry.nX, y - maGeometry.nY );
- aState.mnState = GetMouseModCode( aMask );
- return aState;
-}
-
-SalFrame::SalIndicatorState GtkSalFrame::GetIndicatorState()
-{
- SalIndicatorState aState;
-#if !GTK_CHECK_VERSION(3,0,0)
- aState.mnState = GetGtkSalData()->GetGtkDisplay()->GetIndicatorState();
-#else
- g_warning ("missing get indicator state");
-#endif
- return aState;
-}
-
-void GtkSalFrame::SimulateKeyPress( sal_uInt16 nKeyCode )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- GetGtkSalData()->GetGtkDisplay()->SimulateKeyPress(nKeyCode);
-#else
- g_warning ("missing simulate keypress %d", nKeyCode);
-#endif
-}
-
-void GtkSalFrame::SetInputContext( SalInputContext* pContext )
-{
- if( ! pContext )
- return;
-
- if( ! (pContext->mnOptions & SAL_INPUTCONTEXT_TEXT) )
- return;
-
- // create a new im context
- if( ! m_pIMHandler )
- m_pIMHandler = new IMHandler( this );
- m_pIMHandler->setInputContext( pContext );
-}
-
-void GtkSalFrame::EndExtTextInput( sal_uInt16 nFlags )
-{
- if( m_pIMHandler )
- m_pIMHandler->endExtTextInput( nFlags );
-}
-
-sal_Bool GtkSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
-{
- // not supported yet
- return sal_False;
-}
-
-LanguageType GtkSalFrame::GetInputLanguage()
-{
- return LANGUAGE_DONTKNOW;
-}
-
-void GtkSalFrame::UpdateSettings( AllSettings& rSettings )
-{
- if( ! m_pWindow )
- return;
-
- GtkSalGraphics* pGraphics = static_cast<GtkSalGraphics*>(m_aGraphics[0].pGraphics);
- bool bFreeGraphics = false;
- if( ! pGraphics )
- {
- pGraphics = static_cast<GtkSalGraphics*>(GetGraphics());
- bFreeGraphics = true;
- }
-
- pGraphics->updateSettings( rSettings );
-
- if( bFreeGraphics )
- ReleaseGraphics( pGraphics );
-}
-
-void GtkSalFrame::Beep()
-{
- gdk_display_beep( getGdkDisplay() );
-}
-
-const SystemEnvData* GtkSalFrame::GetSystemData() const
-{
- return &m_aSystemData;
-}
-
-void GtkSalFrame::SetParent( SalFrame* pNewParent )
-{
- if( m_pParent )
- m_pParent->m_aChildren.remove( this );
- m_pParent = static_cast<GtkSalFrame*>(pNewParent);
- if( m_pParent )
- m_pParent->m_aChildren.push_back( this );
- if( ! isChild() )
- gtk_window_set_transient_for( GTK_WINDOW(m_pWindow),
- (m_pParent && ! m_pParent->isChild(true,false)) ? GTK_WINDOW(m_pParent->m_pWindow) : NULL
- );
-}
-
-#if !GTK_CHECK_VERSION(3,0,0)
-
-void GtkSalFrame::createNewWindow( XLIB_Window aNewParent, bool bXEmbed, SalX11Screen nXScreen )
-{
- bool bWasVisible = IS_WIDGET_MAPPED(m_pWindow);
- if( bWasVisible )
- Show( sal_False );
-
- if( (int)nXScreen.getXScreen() >= getDisplay()->GetXScreenCount() )
- nXScreen = m_nXScreen;
-
- SystemParentData aParentData;
- aParentData.aWindow = aNewParent;
- aParentData.bXEmbedSupport = bXEmbed;
- if( aNewParent == None )
- {
- aNewParent = getDisplay()->GetRootWindow(nXScreen);
- aParentData.aWindow = None;
- aParentData.bXEmbedSupport = false;
- }
- else
- {
- // is new parent a root window ?
- Display* pDisp = getDisplay()->GetDisplay();
- int nScreens = getDisplay()->GetXScreenCount();
- for( int i = 0; i < nScreens; i++ )
- {
- if( aNewParent == RootWindow( pDisp, i ) )
- {
- nXScreen = SalX11Screen( i );
- aParentData.aWindow = None;
- aParentData.bXEmbedSupport = false;
- break;
- }
- }
- }
-
- // free xrender resources
- for( unsigned int i = 0; i < SAL_N_ELEMENTS(m_aGraphics); i++ )
- if( m_aGraphics[i].bInUse )
- m_aGraphics[i].pGraphics->SetDrawable( None, m_nXScreen );
-
- // first deinit frame
- if( m_pIMHandler )
- {
- delete m_pIMHandler;
- m_pIMHandler = NULL;
- }
- if( m_pRegion )
- {
-#if GTK_CHECK_VERSION(3,0,0)
- cairo_region_destroy( m_pRegion );
-#else
- gdk_region_destroy( m_pRegion );
-#endif
- }
- if( m_pFixedContainer )
- gtk_widget_destroy( GTK_WIDGET(m_pFixedContainer) );
- if( m_pWindow )
- gtk_widget_destroy( m_pWindow );
- if( m_pForeignParent )
- g_object_unref( G_OBJECT( m_pForeignParent ) );
- if( m_pForeignTopLevel )
- g_object_unref( G_OBJECT( m_pForeignTopLevel ) );
-
- // init new window
- m_bDefaultPos = m_bDefaultSize = false;
- if( aParentData.aWindow != None )
- {
- m_nStyle |= SAL_FRAME_STYLE_PLUG;
- Init( &aParentData );
- }
- else
- {
- m_nStyle &= ~SAL_FRAME_STYLE_PLUG;
- Init( (m_pParent && m_pParent->m_nXScreen == m_nXScreen) ? m_pParent : NULL, m_nStyle );
- }
-
- // update graphics
- for( unsigned int i = 0; i < SAL_N_ELEMENTS(m_aGraphics); i++ )
- {
- if( m_aGraphics[i].bInUse )
- {
- m_aGraphics[i].pGraphics->SetDrawable( widget_get_xid(m_pWindow), m_nXScreen );
- m_aGraphics[i].pGraphics->SetWindow( m_pWindow );
- }
- }
-
- if( ! m_aTitle.isEmpty() )
- SetTitle( m_aTitle );
-
- if( bWasVisible )
- Show( sal_True );
-
- std::list< GtkSalFrame* > aChildren = m_aChildren;
- m_aChildren.clear();
- for( std::list< GtkSalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it )
- (*it)->createNewWindow( None, false, m_nXScreen );
-
- // FIXME: SalObjects
-}
-#endif
-
-bool GtkSalFrame::SetPluginParent( SystemParentData* pSysParent )
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- if( pSysParent ) // this may be the first system child frame now
- GetGenericData()->ErrorTrapPush(); // permanantly ignore unruly children's errors
- createNewWindow( pSysParent->aWindow, (pSysParent->nSize > sizeof(long)) ? pSysParent->bXEmbedSupport : false, m_nXScreen );
- return true;
-#else
- (void)pSysParent;
-#warning FIXME: no SetPluginParent impl. for gtk3
- return false;
-#endif
-}
-
-void GtkSalFrame::ResetClipRegion()
-{
- if( m_pWindow )
- gdk_window_shape_combine_region( widget_get_window( m_pWindow ), NULL, 0, 0 );
-}
-
-void GtkSalFrame::BeginSetClipRegion( sal_uLong )
-{
-#if GTK_CHECK_VERSION(3,0,0)
- if( m_pRegion )
- cairo_region_destroy( m_pRegion );
- m_pRegion = cairo_region_create();
-#else
- if( m_pRegion )
- gdk_region_destroy( m_pRegion );
- m_pRegion = gdk_region_new();
-#endif
-}
-
-void GtkSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
-{
- if( m_pRegion )
- {
- GdkRectangle aRect;
- aRect.x = nX;
- aRect.y = nY;
- aRect.width = nWidth;
- aRect.height = nHeight;
-#if GTK_CHECK_VERSION(3,0,0)
- cairo_region_union_rectangle( m_pRegion, &aRect );
-#else
- gdk_region_union_with_rect( m_pRegion, &aRect );
-#endif
- }
-}
-
-void GtkSalFrame::EndSetClipRegion()
-{
- if( m_pWindow && m_pRegion )
- gdk_window_shape_combine_region( widget_get_window(m_pWindow), m_pRegion, 0, 0 );
-}
-
-#if !GTK_CHECK_VERSION(3,0,0)
-bool GtkSalFrame::Dispatch( const XEvent* pEvent )
-{
- bool bContinueDispatch = true;
-
- if( pEvent->type == PropertyNotify )
- {
- vcl_sal::WMAdaptor* pAdaptor = getDisplay()->getWMAdaptor();
- Atom nDesktopAtom = pAdaptor->getAtom( vcl_sal::WMAdaptor::NET_WM_DESKTOP );
- if( pEvent->xproperty.atom == nDesktopAtom &&
- pEvent->xproperty.state == PropertyNewValue )
- {
- m_nWorkArea = pAdaptor->getWindowWorkArea( widget_get_xid(m_pWindow) );
- }
- }
- else if( pEvent->type == ConfigureNotify )
- {
- if( m_pForeignParent && pEvent->xconfigure.window == m_aForeignParentWindow )
- {
- bContinueDispatch = false;
- gtk_window_resize( GTK_WINDOW(m_pWindow), pEvent->xconfigure.width, pEvent->xconfigure.height );
- if( ( sal::static_int_cast< int >(maGeometry.nWidth) !=
- pEvent->xconfigure.width ) ||
- ( sal::static_int_cast< int >(maGeometry.nHeight) !=
- pEvent->xconfigure.height ) )
- {
- maGeometry.nWidth = pEvent->xconfigure.width;
- maGeometry.nHeight = pEvent->xconfigure.height;
- setMinMaxSize();
- AllocateFrame();
- getDisplay()->SendInternalEvent( this, NULL, SALEVENT_RESIZE );
- }
- }
- else if( m_pForeignTopLevel && pEvent->xconfigure.window == m_aForeignTopLevelWindow )
- {
- bContinueDispatch = false;
- // update position
- int x = 0, y = 0;
- XLIB_Window aChild;
- XTranslateCoordinates( getDisplay()->GetDisplay(),
- widget_get_xid(m_pWindow),
- getDisplay()->GetRootWindow( getDisplay()->GetDefaultXScreen() ),
- 0, 0,
- &x, &y,
- &aChild );
- if( x != maGeometry.nX || y != maGeometry.nY )
- {
- maGeometry.nX = x;
- maGeometry.nY = y;
- getDisplay()->SendInternalEvent( this, NULL, SALEVENT_MOVE );
- }
- }
- }
- else if( pEvent->type == ClientMessage &&
- pEvent->xclient.message_type == getDisplay()->getWMAdaptor()->getAtom( vcl_sal::WMAdaptor::XEMBED ) &&
- pEvent->xclient.window == widget_get_xid(m_pWindow) &&
- m_bWindowIsGtkPlug
- )
- {
- // FIXME: this should not be necessary, GtkPlug should do this
- // transparently for us
- if( pEvent->xclient.data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE
- pEvent->xclient.data.l[1] == 2 // XEMBED_WINDOW_DEACTIVATE
- )
- {
- GdkEventFocus aEvent;
- aEvent.type = GDK_FOCUS_CHANGE;
- aEvent.window = widget_get_window( m_pWindow );
- aEvent.send_event = sal_True;
- aEvent.in = (pEvent->xclient.data.l[1] == 1);
- signalFocus( m_pWindow, &aEvent, this );
- }
- }
-
- return bContinueDispatch;
-}
-#endif
-
-gboolean GtkSalFrame::signalButton( GtkWidget*, GdkEventButton* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
- SalMouseEvent aEvent;
- sal_uInt16 nEventType = 0;
- switch( pEvent->type )
- {
- case GDK_BUTTON_PRESS:
- nEventType = SALEVENT_MOUSEBUTTONDOWN;
- break;
- case GDK_BUTTON_RELEASE:
- nEventType = SALEVENT_MOUSEBUTTONUP;
- break;
- default:
- return sal_False;
- }
- switch( pEvent->button )
- {
- case 1: aEvent.mnButton = MOUSE_LEFT; break;
- case 2: aEvent.mnButton = MOUSE_MIDDLE; break;
- case 3: aEvent.mnButton = MOUSE_RIGHT; break;
- default: return sal_False;
- }
- aEvent.mnTime = pEvent->time;
- aEvent.mnX = (long)pEvent->x_root - pThis->maGeometry.nX;
- aEvent.mnY = (long)pEvent->y_root - pThis->maGeometry.nY;
- aEvent.mnCode = GetMouseModCode( pEvent->state );
-
- bool bClosePopups = false;
- if( pEvent->type == GDK_BUTTON_PRESS &&
- (pThis->m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) == 0
- )
- {
- if( m_nFloats > 0 )
- {
- // close popups if user clicks outside our application
- gint x, y;
- bClosePopups = (gdk_display_get_window_at_pointer( pThis->getGdkDisplay(), &x, &y ) == NULL);
- }
- /* #i30306# release implicit pointer grab if no popups are open; else
- * Drag cannot grab the pointer and will fail.
- */
- if( m_nFloats < 1 || bClosePopups )
- gdk_display_pointer_ungrab( pThis->getGdkDisplay(), GDK_CURRENT_TIME );
- }
-
- if( pThis->m_bWindowIsGtkPlug &&
- pEvent->type == GDK_BUTTON_PRESS &&
- pEvent->button == 1 )
- {
- pThis->askForXEmbedFocus( pEvent->time );
- }
-
- // --- RTL --- (mirror mouse pos)
- if( Application::GetSettings().GetLayoutRTL() )
- aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
-
- vcl::DeletionListener aDel( pThis );
-
- pThis->CallCallback( nEventType, &aEvent );
-
- if( ! aDel.isDeleted() )
- {
- if( bClosePopups )
- {
- ImplSVData* pSVData = ImplGetSVData();
- if ( pSVData->maWinData.mpFirstFloat )
- {
- static const char* pEnv = getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
- if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) && !(pEnv && *pEnv) )
- pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
- }
- }
-
- if( ! aDel.isDeleted() )
- {
- int frame_x = (int)(pEvent->x_root - pEvent->x);
- int frame_y = (int)(pEvent->y_root - pEvent->y);
- if( frame_x != pThis->maGeometry.nX || frame_y != pThis->maGeometry.nY )
- {
- pThis->maGeometry.nX = frame_x;
- pThis->maGeometry.nY = frame_y;
- pThis->CallCallback( SALEVENT_MOVE, NULL );
- }
- }
- }
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalScroll( GtkWidget*, GdkEvent* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
- GdkEventScroll* pSEvent = (GdkEventScroll*)pEvent;
-
- static sal_uLong nLines = 0;
- if( ! nLines )
- {
- char* pEnv = getenv( "SAL_WHEELLINES" );
- nLines = pEnv ? atoi( pEnv ) : 3;
- if( nLines > 10 )
- nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL;
- }
-
- bool bNeg = (pSEvent->direction == GDK_SCROLL_DOWN || pSEvent->direction == GDK_SCROLL_RIGHT );
- SalWheelMouseEvent aEvent;
- aEvent.mnTime = pSEvent->time;
- aEvent.mnX = (sal_uLong)pSEvent->x;
- aEvent.mnY = (sal_uLong)pSEvent->y;
- aEvent.mnDelta = bNeg ? -120 : 120;
- aEvent.mnNotchDelta = bNeg ? -1 : 1;
- aEvent.mnScrollLines = nLines;
- aEvent.mnCode = GetMouseModCode( pSEvent->state );
- aEvent.mbHorz = (pSEvent->direction == GDK_SCROLL_LEFT || pSEvent->direction == GDK_SCROLL_RIGHT);
-
- // --- RTL --- (mirror mouse pos)
- if( Application::GetSettings().GetLayoutRTL() )
- aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
-
- pThis->CallCallback( SALEVENT_WHEELMOUSE, &aEvent );
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalMotion( GtkWidget*, GdkEventMotion* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- SalMouseEvent aEvent;
- aEvent.mnTime = pEvent->time;
- aEvent.mnX = (long)pEvent->x_root - pThis->maGeometry.nX;
- aEvent.mnY = (long)pEvent->y_root - pThis->maGeometry.nY;
- aEvent.mnCode = GetMouseModCode( pEvent->state );
- aEvent.mnButton = 0;
-
- // --- RTL --- (mirror mouse pos)
- if( Application::GetSettings().GetLayoutRTL() )
- aEvent.mnX = pThis->maGeometry.nWidth-1-aEvent.mnX;
-
- vcl::DeletionListener aDel( pThis );
-
- pThis->CallCallback( SALEVENT_MOUSEMOVE, &aEvent );
-
- if( ! aDel.isDeleted() )
- {
- int frame_x = (int)(pEvent->x_root - pEvent->x);
- int frame_y = (int)(pEvent->y_root - pEvent->y);
- if( frame_x != pThis->maGeometry.nX || frame_y != pThis->maGeometry.nY )
- {
- pThis->maGeometry.nX = frame_x;
- pThis->maGeometry.nY = frame_y;
- pThis->CallCallback( SALEVENT_MOVE, NULL );
- }
-
- if( ! aDel.isDeleted() )
- {
- // ask for the next hint
- gint x, y;
- GdkModifierType mask;
- gdk_window_get_pointer( widget_get_window(GTK_WIDGET(pThis->m_pWindow)), &x, &y, &mask );
- }
- }
-
- return sal_True;
-}
-
-gboolean GtkSalFrame::signalCrossing( GtkWidget*, GdkEventCrossing* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
- SalMouseEvent aEvent;
- aEvent.mnTime = pEvent->time;
- aEvent.mnX = (long)pEvent->x_root - pThis->maGeometry.nX;
- aEvent.mnY = (long)pEvent->y_root - pThis->maGeometry.nY;
- aEvent.mnCode = GetMouseModCode( pEvent->state );
- aEvent.mnButton = 0;
-
- pThis->CallCallback( (pEvent->type == GDK_ENTER_NOTIFY) ? SALEVENT_MOUSEMOVE : SALEVENT_MOUSELEAVE, &aEvent );
-
- return sal_True;
-}
-
-#if GTK_CHECK_VERSION(3,0,0)
-void GtkSalFrame::pushIgnoreDamage()
-{
- m_nDuringRender++;
-}
-
-void GtkSalFrame::popIgnoreDamage()
-{
- m_nDuringRender--;
-}
-
-bool GtkSalFrame::isDuringRender()
-{
- return m_nDuringRender;
-}
-
-#endif
-
-void GtkSalFrame::damaged (const basegfx::B2IBox& rDamageRect)
-{
-#if !GTK_CHECK_VERSION(3,0,0)
- (void)rDamageRect;
-#else
- if ( isDuringRender() )
- return;
-#if OSL_DEBUG_LEVEL > 1
- long long area = rDamageRect.getWidth() * rDamageRect.getHeight();
- if( area > 32 * 1024 )
- {
- fprintf( stderr, "bitmap damaged %d %d (%dx%d) area %lld widget\n",
- (int) rDamageRect.getMinX(),
- (int) rDamageRect.getMinY(),
- (int) rDamageRect.getWidth(),
- (int) rDamageRect.getHeight(),
- area );
- }
-#endif
- /* FIXME: this is a dirty hack, to render buttons correctly, we
- * should of course remove the -100 and + 200, but the whole area
- * won't be rendered then.
- */
- gtk_widget_queue_draw_area( m_pWindow,
- rDamageRect.getMinX() - 1,
- rDamageRect.getMinY() - 1,
- rDamageRect.getWidth() + 2,
- rDamageRect.getHeight() + 2 );
-#endif
-}
-
-#if GTK_CHECK_VERSION(3,0,0)
-// FIXME: This is incredibly lame ... but so is cairo's insistance on -exactly-
-// its own stride - neither more nor less - particularly not more aligned
-// we like 8byte aligned, it likes 4 - most odd.
-void GtkSalFrame::renderArea( cairo_t *cr, cairo_rectangle_t *area )
-{
- if( !m_aFrame.get() )
- return;
-
- basebmp::RawMemorySharedArray data = m_aFrame->getBuffer();
- basegfx::B2IVector size = m_aFrame->getSize();
- sal_Int32 nStride = m_aFrame->getScanlineStride();
-
- long ax = area->x;
- long ay = area->y;
- long awidth = area->width;
- long aheight = area->height;
-
- // Sanity check bounds - we get some odd things here.
- if( ax >= size.getX() )
- ax = size.getX() - 1;
- if( ay >= size.getY() )
- ay = size.getY() - 1;
- if( ax < 0 )
- {
- ax = 0;
- awidth += ax;
- }
- if( ay < 0 )
- {
- ay = 0;
- aheight += ay;
- }
- if( ax + awidth > size.getX() )
- awidth = size.getX() - ax;
- if( ay + aheight > size.getY() )
- aheight = size.getY() - ay;
-
- cairo_save( cr );
-
- int cairo_stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, area->width);
- unsigned char *p, *src, *mem = (unsigned char *)malloc (32 * cairo_stride * area->height);
- p = mem;
- src = data.get();
- src += (int)ay * nStride + (int)ax * 3;
-
- for (int y = 0; y < aheight; ++y)
- {
- for (int x = 0; x < awidth; ++x)
- {
- p[x*4 + 0] = src[x*3 + 0]; // B
- p[x*4 + 1] = src[x*3 + 1]; // G
- p[x*4 + 2] = src[x*3 + 2]; // R
- p[x*4 + 3] = 255; // A
- }
- src += nStride;
- p += cairo_stride;
- }
- cairo_surface_t *pSurface =
- cairo_image_surface_create_for_data( mem,
- CAIRO_FORMAT_ARGB32,
- awidth, aheight,
- cairo_stride );
- /* g_warning( "Fixed cairo status %d %d strides: %d vs %d, mask %d\n",
- (int) cairo_status( cr ),
- (int) cairo_surface_status( pSurface ),
- (int) nStride,
- (int) cairo_stride,
- (int) (cairo_stride & (sizeof (uint32_t)-1)) ); */
-
- cairo_set_operator( cr, CAIRO_OPERATOR_OVER );
- cairo_set_source_surface( cr, pSurface, ax, ay );
- cairo_paint( cr );
- cairo_surface_destroy( pSurface );
- free (mem);
- cairo_restore( cr );
-
- // Render red rectangles to show what was re-rendered ...
- if (debugRedboxRedraws)
- {
- cairo_save( cr );
- cairo_set_line_width( cr, 1.0 );
- cairo_set_source_rgb( cr, 1.0, 0, 0 );
- cairo_rectangle( cr, ax + 1.0, ay + 1.0, awidth - 2.0, aheight - 2.0 );
- cairo_stroke( cr );
- cairo_restore( cr );
- }
-}
-
-gboolean GtkSalFrame::signalDraw( GtkWidget*, cairo_t *cr, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
- cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
-
- if (debugQueuePureRedraw > 0)
- {
- debugQueuePureRedraw--;
- fprintf (stderr, "skip signalDraw for debug %d\n", debugQueuePureRedraw);
- cairo_rectangle_t rect = { x1, y1, x2 - x1, y2 - y1 };
- pThis->renderArea( cr, &rect );
- return FALSE;
- }
-
- // FIXME: we quite probably want to stop re-rendering of pieces
- // that we know are just damaged by us and hence already re-rendered
- pThis->m_nDuringRender++;
-
- // FIXME: we need to profile whether re-rendering the entire
- // clip region, and just pushing (with renderArea) smaller pieces
- // is faster ...
- cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list (cr);
- fprintf( stderr, "paint %d regions\n", rects->num_rectangles);
- for (int i = 0; i < rects->num_rectangles; i++) {
- cairo_rectangle_t rect = rects->rectangles[i];
- fprintf( stderr, "\t%d -> %g,%g %gx%g\n", i,
- rect.x, rect.y, rect.width, rect.height );
-
- struct SalPaintEvent aEvent( rect.x, rect.y, rect.width, rect.height );
- aEvent.mbImmediateUpdate = true;
- pThis->CallCallback( SALEVENT_PAINT, &aEvent );
- pThis->renderArea( cr, &rect );
- }
-
- pThis->m_nDuringRender--;
-
- return FALSE;
-}
-#endif // GTK_CHECK_VERSION(3,0,0)
-
-
-gboolean GtkSalFrame::signalExpose( GtkWidget*, GdkEventExpose* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- struct SalPaintEvent aEvent( pEvent->area.x, pEvent->area.y, pEvent->area.width, pEvent->area.height );
-
- pThis->CallCallback( SALEVENT_PAINT, &aEvent );
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalFocus( GtkWidget*, GdkEventFocus* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- X11SalInstance *pSalInstance =
- static_cast< X11SalInstance* >(GetSalData()->m_pInstance);
-
- // check if printers have changed (analogous to salframe focus handler)
- pSalInstance->updatePrinterUpdate();
-
- if( !pEvent->in )
- {
- pThis->m_nKeyModifiers = 0;
- pThis->m_bSendModChangeOnRelease = false;
- }
-
- if( pThis->m_pIMHandler )
- pThis->m_pIMHandler->focusChanged( pEvent->in );
-
- // ask for changed printers like generic implementation
- if( pEvent->in && pSalInstance->isPrinterInit() )
- pSalInstance->updatePrinterUpdate();
-
- // FIXME: find out who the hell steals the focus from our frame
- // while we have the pointer grabbed, this should not come from
- // the window manager. Is this an event that was still queued ?
- // The focus does not seem to get set inside our process
- //
- // in the meantime do not propagate focus get/lose if floats are open
- if( m_nFloats == 0 )
- pThis->CallCallback( pEvent->in ? SALEVENT_GETFOCUS : SALEVENT_LOSEFOCUS, NULL );
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalMap( GtkWidget *pWidget, GdkEvent*, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- bool bSetFocus = pThis->m_bSetFocusOnMap;
- pThis->m_bSetFocusOnMap = false;
-
-#if !GTK_CHECK_VERSION(3,0,0)
- if( bSetFocus )
- {
- GetGenericData()->ErrorTrapPush();
- XSetInputFocus( pThis->getDisplay()->GetDisplay(),
- widget_get_xid(pWidget),
- RevertToParent, CurrentTime );
- XSync( pThis->getDisplay()->GetDisplay(), False );
- GetGenericData()->ErrorTrapPop();
- }
-#else
- (void)pWidget; (void)bSetFocus;
-# warning FIXME no set input focus ...
-#endif
-
- pThis->CallCallback( SALEVENT_RESIZE, NULL );
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalUnmap( GtkWidget*, GdkEvent*, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- pThis->CallCallback( SALEVENT_RESIZE, NULL );
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalConfigure( GtkWidget*, GdkEventConfigure* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- bool bMoved = false, bSized = false;
- int x = pEvent->x, y = pEvent->y;
-
- /* HACK: during sizing/moving a toolbar pThis->maGeometry is actually
- * already exact; even worse: due to the asynchronicity of configure
- * events the borderwindow which would evaluate this event
- * would size/move based on wrong data if we would actually evaluate
- * this event. So let's swallow it.
- */
- if( (pThis->m_nStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) &&
- pThis->getDisplay()->GetCaptureFrame() == pThis )
- return sal_False;
-
- /* #i31785# claims we cannot trust the x,y members of the event;
- * they are e.g. not set correctly on maximize/demaximize;
- * yet the gdkdisplay-x11.c code handling configure_events has
- * done this XTranslateCoordinates work since the day ~zero.
- */
- if( x != pThis->maGeometry.nX || y != pThis->maGeometry.nY )
- {
- bMoved = true;
- pThis->maGeometry.nX = x;
- pThis->maGeometry.nY = y;
- }
- /* #i86302#
- * for non sizeable windows we set the min and max hint for the window manager to
- * achieve correct sizing. However this is asynchronous and e.g. on Compiz
- * it sometimes happens that the window gets resized to another size (some default)
- * if we update the size here, subsequent setMinMaxSize will use this wrong size
- * - which is not good since the window manager will now size the window back to this
- * wrong size at some point.
- */
- /* fprintf (stderr, "configure %d %d %d (%d) %d, %d diff? %d\n",
- (int)pThis->m_bFullscreen, (pThis->m_nStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_PLUG)), SAL_FRAME_STYLE_SIZEABLE,
- !!( pThis->m_bFullscreen || (pThis->m_nStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_PLUG)) == SAL_FRAME_STYLE_SIZEABLE ),
- pEvent->width, pEvent->height,
- !!(pEvent->width != (int)pThis->maGeometry.nWidth || pEvent->height != (int)pThis->maGeometry.nHeight)
- ); */
- if( pThis->m_bFullscreen || (pThis->m_nStyle & (SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_PLUG)) == SAL_FRAME_STYLE_SIZEABLE )
- {
- if( pEvent->width != (int)pThis->maGeometry.nWidth || pEvent->height != (int)pThis->maGeometry.nHeight )
- {
- bSized = true;
- pThis->maGeometry.nWidth = pEvent->width;
- pThis->maGeometry.nHeight = pEvent->height;
- }
- }
-
- // update decoration hints
- if( ! (pThis->m_nStyle & SAL_FRAME_STYLE_PLUG) )
- {
- GdkRectangle aRect;
- gdk_window_get_frame_extents( widget_get_window(GTK_WIDGET(pThis->m_pWindow)), &aRect );
- pThis->maGeometry.nTopDecoration = y - aRect.y;
- pThis->maGeometry.nBottomDecoration = aRect.y + aRect.height - y - pEvent->height;
- pThis->maGeometry.nLeftDecoration = x - aRect.x;
- pThis->maGeometry.nRightDecoration = aRect.x + aRect.width - x - pEvent->width;
- }
- else
- {
- pThis->maGeometry.nTopDecoration =
- pThis->maGeometry.nBottomDecoration =
- pThis->maGeometry.nLeftDecoration =
- pThis->maGeometry.nRightDecoration = 0;
- }
-
- pThis->updateScreenNumber();
- if( bSized )
- pThis->AllocateFrame();
-
- if( bMoved && bSized )
- pThis->CallCallback( SALEVENT_MOVERESIZE, NULL );
- else if( bMoved )
- pThis->CallCallback( SALEVENT_MOVE, NULL );
- else if( bSized )
- pThis->CallCallback( SALEVENT_RESIZE, NULL );
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalKey( GtkWidget*, GdkEventKey* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- vcl::DeletionListener aDel( pThis );
-
- if( pThis->m_pIMHandler )
- {
- if( pThis->m_pIMHandler->handleKeyEvent( pEvent ) )
- return sal_True;
- }
-
- // handle modifiers
- if( pEvent->keyval == GDK_Shift_L || pEvent->keyval == GDK_Shift_R ||
- pEvent->keyval == GDK_Control_L || pEvent->keyval == GDK_Control_R ||
- pEvent->keyval == GDK_Alt_L || pEvent->keyval == GDK_Alt_R ||
- pEvent->keyval == GDK_Meta_L || pEvent->keyval == GDK_Meta_R ||
- pEvent->keyval == GDK_Super_L || pEvent->keyval == GDK_Super_R )
- {
- SalKeyModEvent aModEvt;
-
- sal_uInt16 nModCode = GetKeyModCode( pEvent->state );
-
- aModEvt.mnModKeyCode = 0; // emit no MODKEYCHANGE events
- if( pEvent->type == GDK_KEY_PRESS && !pThis->m_nKeyModifiers )
- pThis->m_bSendModChangeOnRelease = true;
-
- else if( pEvent->type == GDK_KEY_RELEASE &&
- pThis->m_bSendModChangeOnRelease )
- {
- aModEvt.mnModKeyCode = pThis->m_nKeyModifiers;
- pThis->m_nKeyModifiers = 0;
- }
-
- sal_uInt16 nExtModMask = 0;
- sal_uInt16 nModMask = 0;
- // pressing just the ctrl key leads to a keysym of XK_Control but
- // the event state does not contain ControlMask. In the release
- // event its the other way round: it does contain the Control mask.
- // The modifier mode therefore has to be adapted manually.
- switch( pEvent->keyval )
- {
- case GDK_Control_L:
- nExtModMask = MODKEY_LMOD1;
- nModMask = KEY_MOD1;
- break;
- case GDK_Control_R:
- nExtModMask = MODKEY_RMOD1;
- nModMask = KEY_MOD1;
- break;
- case GDK_Alt_L:
- nExtModMask = MODKEY_LMOD2;
- nModMask = KEY_MOD2;
- break;
- case GDK_Alt_R:
- nExtModMask = MODKEY_RMOD2;
- nModMask = KEY_MOD2;
- break;
- case GDK_Shift_L:
- nExtModMask = MODKEY_LSHIFT;
- nModMask = KEY_SHIFT;
- break;
- case GDK_Shift_R:
- nExtModMask = MODKEY_RSHIFT;
- nModMask = KEY_SHIFT;
- break;
- // Map Meta/Super to MOD3 modifier on all Unix systems
- // except Mac OS X
- case GDK_Meta_L:
- case GDK_Super_L:
- nExtModMask = MODKEY_LMOD3;
- nModMask = KEY_MOD3;
- break;
- case GDK_Meta_R:
- case GDK_Super_R:
- nExtModMask = MODKEY_RMOD3;
- nModMask = KEY_MOD3;
- break;
- }
- if( pEvent->type == GDK_KEY_RELEASE )
- {
- nModCode &= ~nModMask;
- pThis->m_nKeyModifiers &= ~nExtModMask;
- }
- else
- {
- nModCode |= nModMask;
- pThis->m_nKeyModifiers |= nExtModMask;
- }
-
- aModEvt.mnCode = nModCode;
- aModEvt.mnTime = pEvent->time;
-
- pThis->CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt );
-
- }
- else
- {
- pThis->doKeyCallback( pEvent->state,
- pEvent->keyval,
- pEvent->hardware_keycode,
- pEvent->group,
- pEvent->time,
- sal_Unicode(gdk_keyval_to_unicode( pEvent->keyval )),
- (pEvent->type == GDK_KEY_PRESS),
- false );
- if( ! aDel.isDeleted() )
- pThis->m_bSendModChangeOnRelease = false;
- }
-
- if( !aDel.isDeleted() && pThis->m_pIMHandler )
- pThis->m_pIMHandler->updateIMSpotLocation();
-
- return sal_True;
-}
-
-gboolean GtkSalFrame::signalDelete( GtkWidget*, GdkEvent*, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- pThis->CallCallback( SALEVENT_CLOSE, NULL );
-
- return sal_True;
-}
-
-void GtkSalFrame::signalStyleSet( GtkWidget*, GtkStyle* pPrevious, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
-
- // every frame gets an initial style set on creation
- // do not post these as the whole application tends to
- // redraw itself to adjust to the new style
- // where there IS no new style resulting in tremendous unnecessary flickering
- if( pPrevious != NULL )
- {
- // signalStyleSet does NOT usually have the gdk lock
- // so post user event to safely dispatch the SALEVENT_SETTINGSCHANGED
- // note: settings changed for multiple frames is avoided in winproc.cxx ImplHandleSettings
- pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_SETTINGSCHANGED );
- pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_FONTCHANGED );
- }
-
-#if !GTK_CHECK_VERSION(3,0,0)
- /* #i64117# gtk sets a nice background pixmap
- * but we actually don't really want that, so save
- * some time on the Xserver as well as prevent
- * some paint issues
- */
- GdkWindow* pWin = widget_get_window(GTK_WIDGET(pThis->getWindow()));
- if( pWin )
- {
- XLIB_Window aWin = GDK_WINDOW_XWINDOW(pWin);
- if( aWin != None )
- XSetWindowBackgroundPixmap( pThis->getDisplay()->GetDisplay(),
- aWin,
- pThis->m_hBackgroundPixmap );
- }
- if( ! pThis->m_pParent )
- {
- // signalize theme changed for NWF caches
- // FIXME: should be called only once for a style change
- GtkSalGraphics::bThemeChanged = sal_True;
- }
-#endif
-}
-
-gboolean GtkSalFrame::signalState( GtkWidget*, GdkEvent* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
- if( (pThis->m_nState & GDK_WINDOW_STATE_ICONIFIED) != (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED ) )
- pThis->getDisplay()->SendInternalEvent( pThis, NULL, SALEVENT_RESIZE );
-
- if( (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_MAXIMIZED) &&
- ! (pThis->m_nState & GDK_WINDOW_STATE_MAXIMIZED) )
- {
- pThis->m_aRestorePosSize =
- Rectangle( Point( pThis->maGeometry.nX, pThis->maGeometry.nY ),
- Size( pThis->maGeometry.nWidth, pThis->maGeometry.nHeight ) );
- }
- pThis->m_nState = pEvent->window_state.new_window_state;
-
- #if OSL_DEBUG_LEVEL > 1
- if( (pEvent->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN) )
- {
- fprintf( stderr, "window %p %s full screen state\n",
- pThis,
- (pEvent->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ? "enters" : "leaves");
- }
- #endif
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::signalVisibility( GtkWidget*, GdkEventVisibility* pEvent, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
- pThis->m_nVisibility = pEvent->state;
-
- return sal_False;
-}
-
-void GtkSalFrame::signalDestroy( GtkWidget* pObj, gpointer frame )
-{
- GtkSalFrame* pThis = (GtkSalFrame*)frame;
- if( pObj == pThis->m_pWindow )
- {
- pThis->m_pFixedContainer = NULL;
- pThis->m_pWindow = NULL;
- }
-}
-
-// ----------------------------------------------------------------------
-// GtkSalFrame::IMHandler
-// ----------------------------------------------------------------------
-
-GtkSalFrame::IMHandler::IMHandler( GtkSalFrame* pFrame )
-: m_pFrame(pFrame),
- m_nPrevKeyPresses( 0 ),
- m_pIMContext( NULL ),
- m_bFocused( true ),
- m_bPreeditJustChanged( false )
-{
- m_aInputEvent.mpTextAttr = NULL;
- createIMContext();
-}
-
-GtkSalFrame::IMHandler::~IMHandler()
-{
- // cancel an eventual event posted to begin preedit again
- m_pFrame->getDisplay()->CancelInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
- deleteIMContext();
-}
-
-void GtkSalFrame::IMHandler::createIMContext()
-{
- if( ! m_pIMContext )
- {
- m_pIMContext = gtk_im_multicontext_new ();
- g_signal_connect( m_pIMContext, "commit",
- G_CALLBACK (signalIMCommit), this );
- g_signal_connect( m_pIMContext, "preedit_changed",
- G_CALLBACK (signalIMPreeditChanged), this );
- g_signal_connect( m_pIMContext, "retrieve_surrounding",
- G_CALLBACK (signalIMRetrieveSurrounding), this );
- g_signal_connect( m_pIMContext, "delete_surrounding",
- G_CALLBACK (signalIMDeleteSurrounding), this );
- g_signal_connect( m_pIMContext, "preedit_start",
- G_CALLBACK (signalIMPreeditStart), this );
- g_signal_connect( m_pIMContext, "preedit_end",
- G_CALLBACK (signalIMPreeditEnd), this );
-
- GetGenericData()->ErrorTrapPush();
- gtk_im_context_set_client_window( m_pIMContext, widget_get_window(GTK_WIDGET(m_pFrame->m_pWindow)) );
- gtk_im_context_focus_in( m_pIMContext );
- GetGenericData()->ErrorTrapPop();
- m_bFocused = true;
- }
-}
-
-void GtkSalFrame::IMHandler::deleteIMContext()
-{
- if( m_pIMContext )
- {
- // first give IC a chance to deinitialize
- GetGenericData()->ErrorTrapPush();
- gtk_im_context_set_client_window( m_pIMContext, NULL );
- GetGenericData()->ErrorTrapPop();
- // destroy old IC
- g_object_unref( m_pIMContext );
- m_pIMContext = NULL;
- }
-}
-
-void GtkSalFrame::IMHandler::doCallEndExtTextInput()
-{
- m_aInputEvent.mpTextAttr = NULL;
- m_pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL );
-}
-
-void GtkSalFrame::IMHandler::updateIMSpotLocation()
-{
- SalExtTextInputPosEvent aPosEvent;
- m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent );
- GdkRectangle aArea;
- aArea.x = aPosEvent.mnX;
- aArea.y = aPosEvent.mnY;
- aArea.width = aPosEvent.mnWidth;
- aArea.height = aPosEvent.mnHeight;
- GetGenericData()->ErrorTrapPush();
- gtk_im_context_set_cursor_location( m_pIMContext, &aArea );
- GetGenericData()->ErrorTrapPop();
-}
-
-void GtkSalFrame::IMHandler::setInputContext( SalInputContext* )
-{
-}
-
-void GtkSalFrame::IMHandler::sendEmptyCommit()
-{
- vcl::DeletionListener aDel( m_pFrame );
-
- SalExtTextInputEvent aEmptyEv;
- aEmptyEv.mnTime = 0;
- aEmptyEv.mpTextAttr = 0;
- aEmptyEv.maText = String();
- aEmptyEv.mnCursorPos = 0;
- aEmptyEv.mnCursorFlags = 0;
- aEmptyEv.mnDeltaStart = 0;
- aEmptyEv.mbOnlyCursor = False;
- m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEmptyEv );
- if( ! aDel.isDeleted() )
- m_pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL );
-}
-
-void GtkSalFrame::IMHandler::endExtTextInput( sal_uInt16 /*nFlags*/ )
-{
- gtk_im_context_reset ( m_pIMContext );
-
- if( m_aInputEvent.mpTextAttr )
- {
- vcl::DeletionListener aDel( m_pFrame );
- // delete preedit in sal (commit an empty string)
- sendEmptyCommit();
- if( ! aDel.isDeleted() )
- {
- // mark previous preedit state again (will e.g. be sent at focus gain)
- m_aInputEvent.mpTextAttr = &m_aInputFlags[0];
- if( m_bFocused )
- {
- // begin preedit again
- m_pFrame->getDisplay()->SendInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
- }
- }
- }
-}
-
-void GtkSalFrame::IMHandler::focusChanged( bool bFocusIn )
-{
- m_bFocused = bFocusIn;
- if( bFocusIn )
- {
- GetGenericData()->ErrorTrapPush();
- gtk_im_context_focus_in( m_pIMContext );
- GetGenericData()->ErrorTrapPop();
- if( m_aInputEvent.mpTextAttr )
- {
- sendEmptyCommit();
- // begin preedit again
- m_pFrame->getDisplay()->SendInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
- }
- }
- else
- {
- GetGenericData()->ErrorTrapPush();
- gtk_im_context_focus_out( m_pIMContext );
- GetGenericData()->ErrorTrapPop();
- // cancel an eventual event posted to begin preedit again
- m_pFrame->getDisplay()->CancelInternalEvent( m_pFrame, &m_aInputEvent, SALEVENT_EXTTEXTINPUT );
- }
-}
-
-bool GtkSalFrame::IMHandler::handleKeyEvent( GdkEventKey* pEvent )
-{
- vcl::DeletionListener aDel( m_pFrame );
-
- if( pEvent->type == GDK_KEY_PRESS )
- {
- // Add this key press event to the list of previous key presses
- // to which we compare key release events. If a later key release
- // event has a matching key press event in this list, we swallow
- // the key release because some GTK Input Methods don't swallow it
- // for us.
- m_aPrevKeyPresses.push_back( PreviousKeyPress(pEvent) );
- m_nPrevKeyPresses++;
-
- // Also pop off the earliest key press event if there are more than 10
- // already.
- while (m_nPrevKeyPresses > 10)
- {
- m_aPrevKeyPresses.pop_front();
- m_nPrevKeyPresses--;
- }
-
- GObject* pRef = G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext ) ) );
-
- // #i51353# update spot location on every key input since we cannot
- // know which key may activate a preedit choice window
- updateIMSpotLocation();
- if( aDel.isDeleted() )
- return true;
-
- gboolean bResult = gtk_im_context_filter_keypress( m_pIMContext, pEvent );
- g_object_unref( pRef );
-
- if( aDel.isDeleted() )
- return true;
-
- m_bPreeditJustChanged = false;
-
- if( bResult )
- return true;
- else
- {
- DBG_ASSERT( m_nPrevKeyPresses > 0, "key press has vanished !" );
- if( ! m_aPrevKeyPresses.empty() ) // sanity check
- {
- // event was not swallowed, do not filter a following
- // key release event
- // note: this relies on gtk_im_context_filter_keypress
- // returning without calling a handler (in the "not swallowed"
- // case ) which might change the previous key press list so
- // we would pop the wrong event here
- m_aPrevKeyPresses.pop_back();
- m_nPrevKeyPresses--;
- }
- }
- }
-
- // Determine if we got an earlier key press event corresponding to this key release
- if (pEvent->type == GDK_KEY_RELEASE)
- {
- GObject* pRef = G_OBJECT( g_object_ref( G_OBJECT( m_pIMContext ) ) );
- gboolean bResult = gtk_im_context_filter_keypress( m_pIMContext, pEvent );
- g_object_unref( pRef );
-
- if( aDel.isDeleted() )
- return true;
-
- m_bPreeditJustChanged = false;
-
- std::list<PreviousKeyPress>::iterator iter = m_aPrevKeyPresses.begin();
- std::list<PreviousKeyPress>::iterator iter_end = m_aPrevKeyPresses.end();
- while (iter != iter_end)
- {
- // If we found a corresponding previous key press event, swallow the release
- // and remove the earlier key press from our list
- if (*iter == pEvent)
- {
- m_aPrevKeyPresses.erase(iter);
- m_nPrevKeyPresses--;
- return true;
- }
- ++iter;
- }
-
- if( bResult )
- return true;
- }
-
- return false;
-}
-
-/* FIXME:
-* #122282# still more hacking: some IMEs never start a preedit but simply commit
-* in this case we cannot commit a single character. Workaround: do not do the
-* single key hack for enter or space if the unicode commited does not match
-*/
-
-static bool checkSingleKeyCommitHack( guint keyval, sal_Unicode cCode )
-{
- bool bRet = true;
- switch( keyval )
- {
- case GDK_KP_Enter:
- case GDK_Return:
- if( cCode != '\n' && cCode != '\r' )
- bRet = false;
- break;
- case GDK_space:
- case GDK_KP_Space:
- if( cCode != ' ' )
- bRet = false;
- break;
- default:
- break;
- }
- return bRet;
-}
-
-#ifdef SOLARIS
-#define CONTEXT_ARG pContext
-#else
-#define CONTEXT_ARG EMPTYARG
-#endif
-void GtkSalFrame::IMHandler::signalIMCommit( GtkIMContext* CONTEXT_ARG, gchar* pText, gpointer im_handler )
-{
- GtkSalFrame::IMHandler* pThis = (GtkSalFrame::IMHandler*)im_handler;
-
- SolarMutexGuard aGuard;
- vcl::DeletionListener aDel( pThis->m_pFrame );
- {
- const bool bWasPreedit =
- (pThis->m_aInputEvent.mpTextAttr != 0) ||
- pThis->m_bPreeditJustChanged;
-
- pThis->m_aInputEvent.mnTime = 0;
- pThis->m_aInputEvent.mpTextAttr = 0;
- pThis->m_aInputEvent.maText = String( pText, RTL_TEXTENCODING_UTF8 );
- pThis->m_aInputEvent.mnCursorPos = pThis->m_aInputEvent.maText.getLength();
- pThis->m_aInputEvent.mnCursorFlags = 0;
- pThis->m_aInputEvent.mnDeltaStart = 0;
- pThis->m_aInputEvent.mbOnlyCursor = False;
-
- pThis->m_aInputFlags.clear();
-
- /* necessary HACK: all keyboard input comes in here as soon as a IMContext is set
- * which is logical and consequent. But since even simple input like
- * <space> comes through the commit signal instead of signalKey
- * and all kinds of windows only implement KeyInput (e.g. PushButtons,
- * RadioButtons and a lot of other Controls), will send a single
- * KeyInput/KeyUp sequence instead of an ExtText event if there
- * never was a preedit and the text is only one character.
- *
- * In this case there the last ExtText event must have been
- * SALEVENT_ENDEXTTEXTINPUT, either because of a regular commit
- * or because there never was a preedit.
- */
- bool bSingleCommit = false;
- if( ! bWasPreedit
- && pThis->m_aInputEvent.maText.getLength() == 1
- && ! pThis->m_aPrevKeyPresses.empty()
- )
- {
- const PreviousKeyPress& rKP = pThis->m_aPrevKeyPresses.back();
- sal_Unicode aOrigCode = pThis->m_aInputEvent.maText[0];
-
- if( checkSingleKeyCommitHack( rKP.keyval, aOrigCode ) )
- {
- pThis->m_pFrame->doKeyCallback( rKP.state, rKP.keyval, rKP.hardware_keycode, rKP.group, rKP.time, aOrigCode, true, true );
- bSingleCommit = true;
- }
- }
- if( ! bSingleCommit )
- {
- pThis->m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&pThis->m_aInputEvent);
- if( ! aDel.isDeleted() )
- pThis->doCallEndExtTextInput();
- }
- if( ! aDel.isDeleted() )
- {
- // reset input event
- pThis->m_aInputEvent.maText = String();
- pThis->m_aInputEvent.mnCursorPos = 0;
- pThis->updateIMSpotLocation();
- }
- }
- #ifdef SOLARIS
- // #i51356# workaround a solaris IIIMP bug
- // in case of partial commits the preedit changed signal
- // and commit signal come in wrong order
- if( ! aDel.isDeleted() )
- signalIMPreeditChanged( pContext, im_handler );
- #endif
-}
-
-void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext*, gpointer im_handler )
-{
- GtkSalFrame::IMHandler* pThis = (GtkSalFrame::IMHandler*)im_handler;
-
- char* pText = NULL;
- PangoAttrList* pAttrs = NULL;
- gint nCursorPos = 0;
-
- gtk_im_context_get_preedit_string( pThis->m_pIMContext,
- &pText,
- &pAttrs,
- &nCursorPos );
- if( pText && ! *pText ) // empty string
- {
- // change from nothing to nothing -> do not start preedit
- // e.g. this will activate input into a calc cell without
- // user input
- if( pThis->m_aInputEvent.maText.getLength() == 0 )
- {
- g_free( pText );
- pango_attr_list_unref( pAttrs );
- return;
- }
- }
-
- pThis->m_bPreeditJustChanged = true;
-
- bool bEndPreedit = (!pText || !*pText) && pThis->m_aInputEvent.mpTextAttr != NULL;
- pThis->m_aInputEvent.mnTime = 0;
- pThis->m_aInputEvent.maText = String( pText, RTL_TEXTENCODING_UTF8 );
- pThis->m_aInputEvent.mnCursorPos = nCursorPos;
- pThis->m_aInputEvent.mnCursorFlags = 0;
- pThis->m_aInputEvent.mnDeltaStart = 0;
- pThis->m_aInputEvent.mbOnlyCursor = False;
-
- pThis->m_aInputFlags = std::vector<sal_uInt16>( std::max( 1, (int)pThis->m_aInputEvent.maText.getLength() ), 0 );
-
- PangoAttrIterator *iter = pango_attr_list_get_iterator(pAttrs);
- do
- {
- GSList *attr_list = NULL;
- GSList *tmp_list = NULL;
- gint start, end;
- guint sal_attr = 0;
-
- pango_attr_iterator_range (iter, &start, &end);
- if (end == G_MAXINT)
- end = pText ? strlen (pText) : 0;
- if (end == start)
- continue;
-
- start = g_utf8_pointer_to_offset (pText, pText + start);
- end = g_utf8_pointer_to_offset (pText, pText + end);
-
- tmp_list = attr_list = pango_attr_iterator_get_attrs (iter);
- while (tmp_list)
- {
- PangoAttribute *pango_attr = (PangoAttribute *)(tmp_list->data);
-
- switch (pango_attr->klass->type)
- {
- case PANGO_ATTR_BACKGROUND:
- sal_attr |= (EXTTEXTINPUT_ATTR_HIGHLIGHT | EXTTEXTINPUT_CURSOR_INVISIBLE);
- break;
- case PANGO_ATTR_UNDERLINE:
- sal_attr |= EXTTEXTINPUT_ATTR_UNDERLINE;
- break;
- case PANGO_ATTR_STRIKETHROUGH:
- sal_attr |= EXTTEXTINPUT_ATTR_REDTEXT;
- break;
- default:
- break;
- }
- pango_attribute_destroy (pango_attr);
- tmp_list = tmp_list->next;
- }
- if (sal_attr == 0)
- sal_attr |= EXTTEXTINPUT_ATTR_UNDERLINE;
- g_slist_free (attr_list);
-
- // Set the sal attributes on our text
- for (int i = start; i < end; ++i)
- {
- SAL_WARN_IF(i >= static_cast<int>(pThis->m_aInputFlags.size()),
- "vcl.gtk", "pango attrib out of range. Broken range: "
- << start << "," << end << " Legal range: 0,"
- << pThis->m_aInputFlags.size());
- if (i >= static_cast<int>(pThis->m_aInputFlags.size()))
- continue;
- pThis->m_aInputFlags[i] |= sal_attr;
- }
- } while (pango_attr_iterator_next (iter));
- pango_attr_iterator_destroy(iter);
-
- pThis->m_aInputEvent.mpTextAttr = &pThis->m_aInputFlags[0];
-
- g_free( pText );
- pango_attr_list_unref( pAttrs );
-
- SolarMutexGuard aGuard;
- vcl::DeletionListener aDel( pThis->m_pFrame );
-
- pThis->m_pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&pThis->m_aInputEvent);
- if( bEndPreedit && ! aDel.isDeleted() )
- pThis->doCallEndExtTextInput();
- if( ! aDel.isDeleted() )
- pThis->updateIMSpotLocation();
-}
-
-void GtkSalFrame::IMHandler::signalIMPreeditStart( GtkIMContext*, gpointer /*im_handler*/ )
-{
-}
-
-void GtkSalFrame::IMHandler::signalIMPreeditEnd( GtkIMContext*, gpointer im_handler )
-{
- GtkSalFrame::IMHandler* pThis = (GtkSalFrame::IMHandler*)im_handler;
-
- pThis->m_bPreeditJustChanged = true;
-
- SolarMutexGuard aGuard;
- vcl::DeletionListener aDel( pThis->m_pFrame );
- pThis->doCallEndExtTextInput();
- if( ! aDel.isDeleted() )
- pThis->updateIMSpotLocation();
-}
-
-uno::Reference<accessibility::XAccessibleEditableText>
- FindFocus(uno::Reference< accessibility::XAccessibleContext > xContext)
-{
- if (!xContext.is())
- uno::Reference< accessibility::XAccessibleEditableText >();
-
- uno::Reference<accessibility::XAccessibleStateSet> xState = xContext->getAccessibleStateSet();
- if (xState.is())
- {
- if (xState->contains(accessibility::AccessibleStateType::FOCUSED))
- return uno::Reference<accessibility::XAccessibleEditableText>(xContext, uno::UNO_QUERY);
- }
-
- for (sal_Int32 i = 0; i < xContext->getAccessibleChildCount(); ++i)
- {
- uno::Reference< accessibility::XAccessible > xChild = xContext->getAccessibleChild(i);
- if (!xChild.is())
- continue;
- uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
- if (!xChildContext.is())
- continue;
- uno::Reference< accessibility::XAccessibleEditableText > xText = FindFocus(xChildContext);
- if (xText.is())
- return xText;
- }
- return uno::Reference< accessibility::XAccessibleEditableText >();
-}
-
-static uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText()
-{
- uno::Reference<accessibility::XAccessibleEditableText> xText;
- Window* pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
- if (!pFocusWin)
- return xText;
-
- try
- {
- uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible( true ) );
- if (xAccessible.is())
- xText = FindFocus(xAccessible->getAccessibleContext());
- }
- catch(const uno::Exception& e)
- {
- g_warning( "Exception in getting input method surrounding text" );
- }
- return xText;
-}
-
-gboolean GtkSalFrame::IMHandler::signalIMRetrieveSurrounding( GtkIMContext* pContext, gpointer /*im_handler*/ )
-{
- uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText();
-
- if (xText.is())
- {
- sal_uInt32 nPosition = xText->getCaretPosition();
- OUString sAllText = xText->getText();
- if (sAllText.isEmpty())
- return sal_False;
- OString sUTF = OUStringToOString(sAllText, RTL_TEXTENCODING_UTF8);
- OUString sCursorText(sAllText.copy(0, nPosition));
- gtk_im_context_set_surrounding(pContext, sUTF.getStr(), sUTF.getLength(),
- OUStringToOString(sCursorText, RTL_TEXTENCODING_UTF8).getLength());
- return sal_True;
- }
-
- return sal_False;
-}
-
-gboolean GtkSalFrame::IMHandler::signalIMDeleteSurrounding( GtkIMContext*, gint offset, gint nchars,
- gpointer /*im_handler*/ )
-{
- uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText();
-
- if (xText.is())
- {
- sal_uInt32 nPosition = xText->getCaretPosition();
- // #i111768# range checking
- sal_Int32 nDeletePos = nPosition + offset;
- sal_Int32 nDeleteEnd = nDeletePos + nchars;
- if (nDeletePos < 0)
- nDeletePos = 0;
- if (nDeleteEnd < 0)
- nDeleteEnd = 0;
- if (nDeleteEnd > xText->getCharacterCount())
- nDeleteEnd = xText->getCharacterCount();
-
- xText->deleteText(nDeletePos, nDeleteEnd);
- return sal_True;
- }
-
- return sal_False;
-}
-
-Size GtkSalDisplay::GetScreenSize( int nDisplayScreen )
-{
- Rectangle aRect = m_pSys->GetDisplayScreenPosSizePixel( nDisplayScreen );
- return Size( aRect.GetWidth(), aRect.GetHeight() );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */