Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/libreofficekit/qa/gtktiledviewer/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 26 kB image not shown  

Quelle  gtv-lok-dialog.cxx   Sprache: C

 
/* -*- 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/.
 */


#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include <iostream>

#include <LibreOfficeKit/LibreOfficeKitGtk.h>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>

#include "gtv-application-window.hxx"
#include "gtv-lok-dialog.hxx"

#include <com/sun/star/awt/Key.hpp>

#include <o3tl/unit_conversion.hxx>
#include <vcl/event.hxx>

namespace {

struct GtvLokDialogPrivate
{
    LOKDocView* lokdocview;
    GtkWidget* pDialogDrawingArea;
    GtkWidget* pFloatingWin;

    // state for dialog
    guint32 m_nLastButtonPressTime;
    guint32 m_nLastButtonReleaseTime;
    guint32 m_nKeyModifier;
    guint32 m_nLastButtonPressed;
    guint32 m_nWidth;
    guint32 m_nHeight;

    // state for child floating windows
    guint32 m_nChildId;
    guint32 m_nChildWidth;
    guint32 m_nChildHeight;
    guint32 m_nChildLastButtonPressTime;
    guint32 m_nChildLastButtonReleaseTime;
    guint32 m_nChildKeyModifier;
    guint32 m_nChildLastButtonPressed;

    guint dialogid;
};

}

#if defined __clang__
#if __has_warning("-Wdeprecated-volatile")
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-volatile"
#endif
#endif
G_DEFINE_TYPE_WITH_PRIVATE(GtvLokDialog, gtv_lok_dialog, GTK_TYPE_DIALOG);
#if defined __clang__
#if __has_warning("-Wdeprecated-volatile")
#pragma clang diagnostic pop
#endif
#endif

enum
{
    PROP_0,
    PROP_LOKDOCVIEW_CONTEXT,
    PROP_DIALOG_ID,
    PROP_DIALOG_WIDTH,
    PROP_DIALOG_HEIGHT,
    PROP_LAST
};

static GParamSpec* properties[PROP_LAST];

static GtvLokDialogPrivate*
getPrivate(GtvLokDialog* dialog)
{
    return static_cast<GtvLokDialogPrivate*>(gtv_lok_dialog_get_instance_private(dialog));
}

static void
gtv_lok_dialog_draw(GtkWidget* pDialogDrawingArea, cairo_t* pCairo, gpointer)
{
    GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
    GtvLokDialogPrivate* priv = getPrivate(pDialog);

    GdkRectangle aRect;
    gdk_cairo_get_clip_rectangle(pCairo, &aRect);
    g_info("Painting dialog region: %d, %d, %d, %d", aRect.x, aRect.y, aRect.width, aRect.height);

    int nWidth = priv->m_nWidth;
    int nHeight = priv->m_nHeight;
    if (aRect.width != 0 && aRect.height != 0)
    {
        nWidth = aRect.width;
        nHeight = aRect.height;
    }

    cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
    unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
    LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
    pDocument->pClass->paintWindow(pDocument, priv->dialogid, pBuffer, aRect.x, aRect.y, nWidth, nHeight);

    gtk_widget_set_size_request(GTK_WIDGET(pDialogDrawingArea), priv->m_nWidth, priv->m_nHeight);

    cairo_surface_flush(pSurface);
    cairo_surface_mark_dirty(pSurface);

    cairo_set_source_surface(pCairo, pSurface, aRect.x, aRect.y);
    // paint the dialog image
    cairo_paint(pCairo);

    // debug red-colored border around the painted region
    cairo_set_source_rgb(pCairo, 1.0, 0, 0);
    cairo_rectangle(pCairo, aRect.x, aRect.y, nWidth, nHeight);
    cairo_stroke(pCairo);
}

static gboolean
gtv_lok_dialog_signal_button(GtkWidget* pDialogDrawingArea, GdkEventButton* pEvent)
{
    GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
    GtvLokDialogPrivate* priv = getPrivate(pDialog);

    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
    LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));

    std::string aEventType = "unknown";
    if (pEvent->type == GDK_BUTTON_PRESS)
        aEventType = "BUTTON_PRESS";
    else if (pEvent->type == GDK_BUTTON_RELEASE)
        aEventType = "BUTTON_RELEASE";

    g_info("lok_dialog_signal_button (type: %s): %d, %d",
           aEventType.c_str(),
           static_cast<int>(pEvent->x), static_cast<int>(pEvent->y));
    gtk_widget_grab_focus(pDialogDrawingArea);

    switch (pEvent->type)
    {
    case GDK_BUTTON_PRESS:
    {
        int nCount = 1;
        if ((pEvent->time - priv->m_nLastButtonPressTime) < 250)
            nCount++;
        priv->m_nLastButtonPressTime = pEvent->time;
        int nEventButton = 0;
        switch (pEvent->button)
        {
        case 1:
            nEventButton = MOUSE_LEFT;
            break;
        case 2:
            nEventButton = MOUSE_MIDDLE;
            break;
        case 3:
            nEventButton = MOUSE_RIGHT;
            break;
        }
        priv->m_nLastButtonPressed = nEventButton;
        pDocument->pClass->postWindowMouseEvent(pDocument,
                                                priv->dialogid,
                                                LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
                                                (pEvent->x),
                                                (pEvent->y),
                                                nCount,
                                                nEventButton,
                                                priv->m_nKeyModifier);

        break;
    }
    case GDK_BUTTON_RELEASE:
    {
        int nCount = 1;
        if ((pEvent->time - priv->m_nLastButtonReleaseTime) < 250)
            nCount++;
        priv->m_nLastButtonReleaseTime = pEvent->time;
        int nEventButton = 0;
        switch (pEvent->button)
        {
        case 1:
            nEventButton = MOUSE_LEFT;
            break;
        case 2:
            nEventButton = MOUSE_MIDDLE;
            break;
        case 3:
            nEventButton = MOUSE_RIGHT;
            break;
        }
        priv->m_nLastButtonPressed = nEventButton;
        pDocument->pClass->postWindowMouseEvent(pDocument,
                                                priv->dialogid,
                                                LOK_MOUSEEVENT_MOUSEBUTTONUP,
                                                (pEvent->x),
                                                (pEvent->y),
                                                nCount,
                                                nEventButton,
                                                priv->m_nKeyModifier);
        break;
    }
    default:
        break;
    }
    return FALSE;
}

static gboolean
gtv_lok_dialog_signal_motion(GtkWidget* pDialogDrawingArea, GdkEventButton* pEvent)
{
    GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
    GtvLokDialogPrivate* priv = getPrivate(pDialog);

    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
    LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));

    g_info("lok_dialog_signal_motion: %d, %d (in twips: %d, %d)",
           static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
           static_cast<int>(o3tl::toTwips(pEvent->x, o3tl::Length::px)),
           static_cast<int>(o3tl::toTwips(pEvent->y, o3tl::Length::px)));

    pDocument->pClass->postWindowMouseEvent(pDocument,
                                            priv->dialogid,
                                            LOK_MOUSEEVENT_MOUSEMOVE,
                                            (pEvent->x),
                                            (pEvent->y),
                                            1,
                                            priv->m_nLastButtonPressed,
                                            priv->m_nKeyModifier);

    return FALSE;
}

static gboolean
gtv_lok_dialog_signal_key(GtkWidget* pDialogDrawingArea, GdkEventKey* pEvent)
{
    GtvLokDialog* pDialog = GTV_LOK_DIALOG(gtk_widget_get_toplevel(pDialogDrawingArea));
    GtvLokDialogPrivate* priv = getPrivate(pDialog);
    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
    LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));

    g_info("lok_dialog_signal_key");
    int nCharCode = 0;
    int nKeyCode = 0;
    priv->m_nKeyModifier &= KEY_MOD2;
    switch (pEvent->keyval)
    {
    case GDK_KEY_BackSpace:
        nKeyCode = css::awt::Key::BACKSPACE;
        break;
    case GDK_KEY_Delete:
        nKeyCode = css::awt::Key::DELETE;
        break;
    case GDK_KEY_Return:
    case GDK_KEY_KP_Enter:
        nKeyCode = css::awt::Key::RETURN;
        break;
    case GDK_KEY_Escape:
        nKeyCode = css::awt::Key::ESCAPE;
        break;
    case GDK_KEY_Tab:
        nKeyCode = css::awt::Key::TAB;
        break;
    case GDK_KEY_Down:
        nKeyCode = css::awt::Key::DOWN;
        break;
    case GDK_KEY_Up:
        nKeyCode = css::awt::Key::UP;
        break;
    case GDK_KEY_Left:
        nKeyCode = css::awt::Key::LEFT;
        break;
    case GDK_KEY_Right:
        nKeyCode = css::awt::Key::RIGHT;
        break;
    case GDK_KEY_Page_Down:
        nKeyCode = css::awt::Key::PAGEDOWN;
        break;
    case GDK_KEY_Page_Up:
        nKeyCode = css::awt::Key::PAGEUP;
        break;
    case GDK_KEY_Insert:
        nKeyCode = css::awt::Key::INSERT;
        break;
    case GDK_KEY_Shift_L:
    case GDK_KEY_Shift_R:
        if (pEvent->type == GDK_KEY_PRESS)
            priv->m_nKeyModifier |= KEY_SHIFT;
        break;
    case GDK_KEY_Control_L:
    case GDK_KEY_Control_R:
        if (pEvent->type == GDK_KEY_PRESS)
            priv->m_nKeyModifier |= KEY_MOD1;
        break;
    case GDK_KEY_Alt_L:
    case GDK_KEY_Alt_R:
        if (pEvent->type == GDK_KEY_PRESS)
            priv->m_nKeyModifier |= KEY_MOD2;
        else
            priv->m_nKeyModifier &= ~KEY_MOD2;
        break;
    default:
        if (pEvent->keyval >= GDK_KEY_F1 && pEvent->keyval <= GDK_KEY_F26)
            nKeyCode = css::awt::Key::F1 + (pEvent->keyval - GDK_KEY_F1);
        else
            nCharCode = gdk_keyval_to_unicode(pEvent->keyval);
    }

    // rsc is not public API, but should be good enough for debugging purposes.
    // If this is needed for real, then probably a new param of type
    // css::awt::KeyModifier is needed in postKeyEvent().
    if (pEvent->state & GDK_SHIFT_MASK)
        nKeyCode |= KEY_SHIFT;

    if (pEvent->state & GDK_CONTROL_MASK)
        nKeyCode |= KEY_MOD1;

    if (priv->m_nKeyModifier & KEY_MOD2)
        nKeyCode |= KEY_MOD2;

    if (nKeyCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)) {
        if (pEvent->keyval >= GDK_KEY_a && pEvent->keyval <= GDK_KEY_z)
        {
            nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_a);
        }
        else if (pEvent->keyval >= GDK_KEY_A && pEvent->keyval <= GDK_KEY_Z) {
                nKeyCode |= 512 + (pEvent->keyval - GDK_KEY_A);
        }
        else if (pEvent->keyval >= GDK_KEY_0 && pEvent->keyval <= GDK_KEY_9) {
                nKeyCode |= 256 + (pEvent->keyval - GDK_KEY_0);
        }
    }

    std::stringstream ss;
    ss << "gtv_lok_dialog::postKey(" << pEvent->type << ", " << nCharCode << ", " << nKeyCode << ")";
    g_info("%s", ss.str().c_str());

    pDocument->pClass->postWindowKeyEvent(pDocument,
                                          priv->dialogid,
                                          pEvent->type == GDK_KEY_RELEASE ? LOK_KEYEVENT_KEYUP : LOK_KEYEVENT_KEYINPUT,
                                          nCharCode,
                                          nKeyCode);

    return FALSE;
}

static void
gtv_lok_dialog_init(GtvLokDialog* dialog)
{
    GtvLokDialogPrivate* priv = getPrivate(dialog);

    GtkWidget* pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
    priv->pDialogDrawingArea = gtk_drawing_area_new();
    priv->pFloatingWin = nullptr;
    priv->m_nChildId = 0;
    priv->m_nChildWidth = 0;
    priv->m_nChildHeight = 0;

    priv->m_nLastButtonPressTime = 0;
    priv->m_nLastButtonReleaseTime = 0;
    priv->m_nKeyModifier = 0;
    priv->m_nLastButtonPressed = 0;

    gtk_widget_add_events(priv->pDialogDrawingArea,
                          GDK_BUTTON_PRESS_MASK
                          |GDK_BUTTON_RELEASE_MASK
                          |GDK_BUTTON_MOTION_MASK
                          |GDK_KEY_PRESS_MASK
                          |GDK_KEY_RELEASE_MASK);
    // This is required to be able to capture key events on the drawing area
    gtk_widget_set_can_focus(priv->pDialogDrawingArea, true);

    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_draw), nullptr);
    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_signal_button), nullptr);
    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_signal_button), nullptr);
    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_signal_motion), nullptr);
    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "key-press-event", G_CALLBACK(gtv_lok_dialog_signal_key), nullptr);
    g_signal_connect(G_OBJECT(priv->pDialogDrawingArea), "key-release-event", G_CALLBACK(gtv_lok_dialog_signal_key), nullptr);
    gtk_container_add(GTK_CONTAINER(pContentArea), priv->pDialogDrawingArea);
}

static void
gtv_lok_dialog_set_property(GObject* object, guint propId, const GValue* value, GParamSpec* pspec)
{
    GtvLokDialog* self = GTV_LOK_DIALOG(object);
    GtvLokDialogPrivate* priv = getPrivate(self);

    switch(propId)
    {
    case PROP_LOKDOCVIEW_CONTEXT:
        priv->lokdocview = LOK_DOC_VIEW(g_value_get_object(value));
        break;
    case PROP_DIALOG_ID:
        priv->dialogid = g_value_get_uint(value);
        break;
    case PROP_DIALOG_WIDTH:
        priv->m_nWidth = g_value_get_uint(value);
        break;
    case PROP_DIALOG_HEIGHT:
        priv->m_nHeight = g_value_get_uint(value);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
    }

    //if (propId == PROP_DIALOG_WIDTH || propId == PROP_DIALOG_HEIGHT)
    //  gtk_widget_set_size_request(GTK_WIDGET(priv->pDialogDrawingArea), priv->m_nWidth, priv->m_nHeight);
}

static void
gtv_lok_dialog_get_property(GObject* object, guint propId, GValue* value, GParamSpec* pspec)
{
    GtvLokDialog* self = GTV_LOK_DIALOG(object);
    GtvLokDialogPrivate* priv = getPrivate(self);

    switch(propId)
    {
    case PROP_LOKDOCVIEW_CONTEXT:
        g_value_set_object(value, priv->lokdocview);
        break;
    case PROP_DIALOG_ID:
        g_value_set_uint(value, priv->dialogid);
        break;
    case PROP_DIALOG_WIDTH:
        g_value_set_uint(value, priv->m_nWidth);
        break;
    case PROP_DIALOG_HEIGHT:
        g_value_set_uint(value, priv->m_nHeight);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
    }
}

static void
gtv_lok_dialog_class_init(GtvLokDialogClass* klass)
{
    G_OBJECT_CLASS(klass)->get_property = gtv_lok_dialog_get_property;
    G_OBJECT_CLASS(klass)->set_property = gtv_lok_dialog_set_property;

    properties[PROP_LOKDOCVIEW_CONTEXT] = g_param_spec_object("lokdocview",
                                                              "LOKDocView Context",
                                                              "The LOKDocView context object to be used for dialog rendering",
                                                              LOK_TYPE_DOC_VIEW,
                                                              static_cast<GParamFlags>(G_PARAM_READWRITE |
                                                                                       G_PARAM_CONSTRUCT_ONLY |
                                                                                       G_PARAM_STATIC_STRINGS));

    properties[PROP_DIALOG_ID] = g_param_spec_uint("dialogid",
                                                   "Dialog identifier",
                                                   "Unique dialog identifier",
                                                   0, G_MAXUINT, 0,
                                                   static_cast<GParamFlags>(G_PARAM_READWRITE |
                                                                            G_PARAM_CONSTRUCT_ONLY |
                                                                            G_PARAM_STATIC_STRINGS));

    properties[PROP_DIALOG_WIDTH] = g_param_spec_uint("width",
                                                      "Dialog width",
                                                      "Dialog width",
                                                      0, 4096, 0,
                                                      static_cast<GParamFlags>(G_PARAM_READWRITE |
                                                                               G_PARAM_STATIC_STRINGS));

    properties[PROP_DIALOG_HEIGHT] = g_param_spec_uint("height",
                                                       "Dialog height",
                                                       "Dialog height",
                                                       0, 2048, 0,
                                                       static_cast<GParamFlags>(G_PARAM_READWRITE |
                                                                                G_PARAM_STATIC_STRINGS));

    g_object_class_install_properties (G_OBJECT_CLASS(klass), PROP_LAST, properties);
}

static void
gtv_lok_dialog_floating_win_draw(GtkWidget* pDrawingArea, cairo_t* pCairo, gpointer userdata)
{
    GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
    GtvLokDialogPrivate* priv = getPrivate(pDialog);

    g_info("gtv_lok_dialog_floating_win_draw triggered");
    cairo_surface_t* pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, priv->m_nChildWidth, priv->m_nChildHeight);
    unsigned char* pBuffer = cairo_image_surface_get_data(pSurface);
    LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(priv->lokdocview));
    pDocument->pClass->paintWindow(pDocument, priv->m_nChildId, pBuffer, 0, 0, priv->m_nChildWidth, priv->m_nChildHeight);

    gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), priv->m_nChildWidth, priv->m_nChildHeight);
    //gtk_widget_set_size_request(GTK_WIDGET(pDialog), nWidth, nHeight);
    //gtk_window_resize(GTK_WINDOW(pDialog), nWidth, nHeight);

    cairo_surface_flush(pSurface);
    cairo_surface_mark_dirty(pSurface);

    cairo_set_source_surface(pCairo, pSurface, 0, 0);
    cairo_paint(pCairo);
}

static gboolean
gtv_lok_dialog_floating_win_signal_button(GtkWidget* /*pDialogChildDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
{
    GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
    GtvLokDialogPrivate* priv = getPrivate(pDialog);

    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
    LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));

    std::string aEventType = "unknown";
    if (pEvent->type == GDK_BUTTON_PRESS)
        aEventType = "BUTTON_PRESS";
    else if (pEvent->type == GDK_BUTTON_RELEASE)
        aEventType = "BUTTON_RELEASE";

    g_info("lok_dialog_floating_win_signal_button (type: %s): %d, %d (in twips: %d, %d)",
           aEventType.c_str(),
           static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
           static_cast<int>(o3tl::toTwips(pEvent->x, o3tl::Length::px)),
           static_cast<int>(o3tl::toTwips(pEvent->y, o3tl::Length::px)));

    switch (pEvent->type)
    {
    case GDK_BUTTON_PRESS:
    {
        int nCount = 1;
        if ((pEvent->time - priv->m_nChildLastButtonPressTime) < 250)
            nCount++;
        priv->m_nChildLastButtonPressTime = pEvent->time;
        int nEventButton = 0;
        switch (pEvent->button)
        {
        case 1:
            nEventButton = MOUSE_LEFT;
            break;
        case 2:
            nEventButton = MOUSE_MIDDLE;
            break;
        case 3:
            nEventButton = MOUSE_RIGHT;
            break;
        }
        priv->m_nChildLastButtonPressed = nEventButton;
        pDocument->pClass->postWindowMouseEvent(pDocument,
                                                priv->m_nChildId,
                                                LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
                                                (pEvent->x),
                                                (pEvent->y),
                                                nCount,
                                                nEventButton,
                                                priv->m_nChildKeyModifier);

        break;
    }
    case GDK_BUTTON_RELEASE:
    {
        int nCount = 1;
        if ((pEvent->time - priv->m_nChildLastButtonReleaseTime) < 250)
            nCount++;
        priv->m_nChildLastButtonReleaseTime = pEvent->time;
        int nEventButton = 0;
        switch (pEvent->button)
        {
        case 1:
            nEventButton = MOUSE_LEFT;
            break;
        case 2:
            nEventButton = MOUSE_MIDDLE;
            break;
        case 3:
            nEventButton = MOUSE_RIGHT;
            break;
        }
        priv->m_nChildLastButtonPressed = nEventButton;
        pDocument->pClass->postWindowMouseEvent(pDocument,
                                                priv->m_nChildId,
                                                LOK_MOUSEEVENT_MOUSEBUTTONUP,
                                                (pEvent->x),
                                                (pEvent->y),
                                                nCount,
                                                nEventButton,
                                                priv->m_nChildKeyModifier);
        break;
    }
    default:
        break;
    }
    return FALSE;
}

static gboolean
gtv_lok_dialog_floating_win_signal_motion(GtkWidget* /*pDialogDrawingArea*/, GdkEventButton* pEvent, gpointer userdata)
{
    GtvLokDialog* pDialog = GTV_LOK_DIALOG(userdata);
    GtvLokDialogPrivate* priv = getPrivate(pDialog);

    GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(pDialog)));
    LibreOfficeKitDocument* pDocument = lok_doc_view_get_document(LOK_DOC_VIEW(window->lokdocview));

    g_info("lok_dialog_floating_win_signal_motion: %d, %d (in twips: %d, %d)",
           static_cast<int>(pEvent->x), static_cast<int>(pEvent->y),
           static_cast<int>(o3tl::toTwips(pEvent->x, o3tl::Length::px)),
           static_cast<int>(o3tl::toTwips(pEvent->y, o3tl::Length::px)));

    pDocument->pClass->postWindowMouseEvent(pDocument,
                                            priv->m_nChildId,
                                            LOK_MOUSEEVENT_MOUSEMOVE,
                                            (pEvent->x),
                                            (pEvent->y),
                                            1,
                                            priv->m_nChildLastButtonPressed,
                                            priv->m_nChildKeyModifier);

    return FALSE;
}

// Public methods below

void gtv_lok_dialog_invalidate(GtvLokDialog* dialog, const GdkRectangle& aRectangle)
{
    GtvLokDialogPrivate* priv = getPrivate(dialog);
    if (aRectangle.width != 0 && aRectangle.height != 0)
        gtk_widget_queue_draw_area(priv->pDialogDrawingArea, aRectangle.x, aRectangle.y, aRectangle.width, aRectangle.height);
    else
        gtk_widget_queue_draw(priv->pDialogDrawingArea);
}

// checks if we are the parent of given childId
gboolean gtv_lok_dialog_is_parent_of(GtvLokDialog* dialog, guint childId)
{
    GtvLokDialogPrivate* priv = getPrivate(dialog);

    return priv->m_nChildId == childId;
}

void gtv_lok_dialog_child_create(GtvLokDialog* dialog, guint childId, guint nX, guint nY, guint width, guint height)
{
    GtvLokDialogPrivate* priv = getPrivate(dialog);

    g_debug("Dialog [ %d ] child window [ %d] being created, with dimensions [%dx%d]@(%d,%d)", priv->dialogid, childId, width, height, nX, nY);
    priv->pFloatingWin = gtk_window_new(GTK_WINDOW_POPUP);
    priv->m_nChildId = childId;
    priv->m_nChildWidth = width;
    priv->m_nChildHeight = height;
    GtkWidget* pDrawingArea = gtk_drawing_area_new();
    gtk_container_add(GTK_CONTAINER(priv->pFloatingWin), pDrawingArea);

    gtk_window_set_transient_for(GTK_WINDOW(priv->pFloatingWin), GTK_WINDOW(dialog));
    gtk_window_set_destroy_with_parent(GTK_WINDOW(priv->pFloatingWin), true);

    gtk_widget_add_events(pDrawingArea,
                          GDK_BUTTON_PRESS_MASK
                          |GDK_POINTER_MOTION_MASK
                          |GDK_BUTTON_RELEASE_MASK
                          |GDK_BUTTON_MOTION_MASK);

    g_signal_connect(G_OBJECT(pDrawingArea), "draw", G_CALLBACK(gtv_lok_dialog_floating_win_draw), dialog);
    g_signal_connect(G_OBJECT(pDrawingArea), "button-press-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
    g_signal_connect(G_OBJECT(pDrawingArea), "button-release-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_button), dialog);
    g_signal_connect(G_OBJECT(pDrawingArea), "motion-notify-event", G_CALLBACK(gtv_lok_dialog_floating_win_signal_motion), dialog);

    gtk_widget_set_size_request(priv->pFloatingWin, 1, 1);
    gtk_window_set_type_hint(GTK_WINDOW(priv->pFloatingWin), GDK_WINDOW_TYPE_HINT_POPUP_MENU);
    gtk_window_set_screen(GTK_WINDOW(priv->pFloatingWin), gtk_window_get_screen(GTK_WINDOW(dialog)));

    gtk_widget_show_all(priv->pFloatingWin);
    gtk_window_present(GTK_WINDOW(priv->pFloatingWin));
    gtk_widget_grab_focus(pDrawingArea);

    // Get the root coords of our new floating window
    GdkWindow* pGdkWin = gtk_widget_get_window(GTK_WIDGET(dialog));
    int nrX = 0;
    int nrY = 0;
    gdk_window_get_root_coords(pGdkWin, nX, nY, &nrX, &nrY);
    gtk_window_move(GTK_WINDOW(priv->pFloatingWin), nrX, nrY);
}

void gtv_lok_dialog_child_invalidate(GtvLokDialog* dialog)
{
    GtvLokDialogPrivate* priv = getPrivate(dialog);
    g_debug("Dialog [ %d ] child invalidate request", priv->dialogid);
    gtk_widget_queue_draw(priv->pFloatingWin);
}

void gtv_lok_dialog_child_close(GtvLokDialog* dialog)
{
    g_info("Dialog's floating window close");

    GtvLokDialogPrivate* priv = getPrivate(dialog);
    if (priv->pFloatingWin)
    {
        gtk_widget_destroy(priv->pFloatingWin);
        priv->pFloatingWin = nullptr;
        priv->m_nChildId = 0;
        priv->m_nChildWidth = 0;
        priv->m_nChildHeight = 0;
    }
}

GtkWidget* gtv_lok_dialog_new(LOKDocView* pDocView, guint dialogId, guint width, guint height)
{
    g_debug("Dialog [ %d ] of size: %d x %d created", dialogId, width, height);
    GtkWindow* pWindow = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(pDocView)));
    return GTK_WIDGET(g_object_new(GTV_TYPE_LOK_DIALOG,
                                   "lokdocview", pDocView,
                                   "dialogid", dialogId,
                                   "width", width,
                                   "height", height,
                                   "title""LOK Dialog",
                                   "modal"false,
                                   "transient-for", pWindow,
                                   nullptr));
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=96 G=95

¤ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.