Changeset 29080 in webkit


Ignore:
Timestamp:
Jan 2, 2008 2:25:57 AM (16 years ago)
Author:
alp@webkit.org
Message:

2008-01-02 Luca Bruno <lethalman88@gmail.com>

Reviewed by Alp Toker.

http://bugs.webkit.org/show_bug.cgi?id=16115
[GTK] ContextMenu and ContextMenuItem lacks an implementation

Add context menu support.

Based on a patch by Holger Freyther.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r29079 r29080  
     12008-01-02  Luca Bruno  <lethalman88@gmail.com>
     2
     3        Reviewed by Alp Toker.
     4
     5        http://bugs.webkit.org/show_bug.cgi?id=16115
     6        [GTK] ContextMenu and ContextMenuItem lacks an implementation
     7
     8        Add context menu support.
     9
     10        Based on a patch by Holger Freyther.
     11
     12        * platform/gtk/ContextMenuGtk.cpp:
     13        (WebCore::menuItemActivated):
     14        (WebCore::ContextMenu::ContextMenu):
     15        (WebCore::ContextMenu::~ContextMenu):
     16        (WebCore::ContextMenu::appendItem):
     17        (WebCore::ContextMenu::setPlatformDescription):
     18        (WebCore::ContextMenu::releasePlatformDescription):
     19        * platform/gtk/ContextMenuItemGtk.cpp:
     20        (WebCore::ContextMenuItem::ContextMenuItem):
     21        (WebCore::ContextMenuItem::~ContextMenuItem):
     22        (WebCore::ContextMenuItem::releasePlatformDescription):
     23        (WebCore::ContextMenuItem::type):
     24        (WebCore::ContextMenuItem::action):
     25        (WebCore::ContextMenuItem::setAction):
     26        (WebCore::ContextMenuItem::platformSubMenu):
     27        (WebCore::ContextMenuItem::setSubMenu):
     28        (WebCore::ContextMenuItem::setChecked):
     29        (WebCore::ContextMenuItem::setEnabled):
     30
    1312008-01-02  Alp Toker  <alp@atoker.com>
    232
  • trunk/WebCore/platform/gtk/ContextMenuGtk.cpp

    r28728 r29080  
    11/*
     2 *  Copyright (C) 2007 Holger Hans Peter Freyther
     3 *
    24 *  This library is free software; you can redistribute it and/or
    35 *  modify it under the terms of the GNU Lesser General Public
     
    1820#include "ContextMenu.h"
    1921
    20 #include "NotImplemented.h"
     22#include "ContextMenuController.h"
     23
     24#include <gtk/gtk.h>
    2125
    2226namespace WebCore {
    2327
     28// TODO: On-the-fly menu item creation and ref-counting correctness checking.
     29// See http://bugs.webkit.org/show_bug.cgi?id=16115
     30
     31static void menuItemActivated(GtkMenuItem* item, ContextMenu* menu)
     32{
     33    ContextMenuItem contextItem(item);
     34    menu->controller()->contextMenuItemSelected(&contextItem);
     35}
     36
    2437ContextMenu::ContextMenu(const HitTestResult& result)
    2538    : m_hitTestResult(result)
    26     , m_platformDescription(0)
    2739{
    28     notImplemented();
     40    m_platformDescription = GTK_MENU(gtk_menu_new());
     41
     42#if GLIB_CHECK_VERSION(2,10,0)
     43    g_object_ref_sink(G_OBJECT(m_platformDescription));
     44#else
     45    g_object_ref(G_OBJECT(m_platformDescription));
     46    gtk_object_sink(GTK_OBJECT(m_platformDescription));
     47#endif
    2948}
    3049
    3150ContextMenu::~ContextMenu()
    3251{
    33     notImplemented();
     52  if (m_platformDescription)
     53      g_object_unref(m_platformDescription);
    3454}
    3555
    36 void ContextMenu::appendItem(ContextMenuItem&)
     56void ContextMenu::appendItem(ContextMenuItem& item)
    3757{
    38     notImplemented();
     58    ASSERT(m_platformDescription);
     59    checkOrEnableIfNeeded(item);
     60
     61    GtkMenuItem* platformItem = item.releasePlatformDescription();
     62    ASSERT(platformItem);
     63
     64    g_signal_connect(platformItem, "activate", G_CALLBACK(menuItemActivated), this);
     65    gtk_menu_shell_append(GTK_MENU_SHELL(m_platformDescription), GTK_WIDGET(platformItem));
     66    gtk_widget_show(GTK_WIDGET(platformItem));
     67    g_object_unref(platformItem);
    3968}
    4069
    4170void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
    4271{
     72    ASSERT(menu);
     73    if (m_platformDescription)
     74        g_object_unref(m_platformDescription);
     75
    4376    m_platformDescription = menu;
     77    g_object_ref(m_platformDescription);
    4478}
    4579
     
    5185PlatformMenuDescription ContextMenu::releasePlatformDescription()
    5286{
    53     notImplemented();
    54     return 0;
     87    PlatformMenuDescription description = m_platformDescription;
     88    m_platformDescription = 0;
     89
     90    return description;
    5591}
    5692
  • trunk/WebCore/platform/gtk/ContextMenuItemGtk.cpp

    r28728 r29080  
    11/*
     2 *  Copyright (C) 2007 Holger Hans Peter Freyther
     3 *
    24 *  This library is free software; you can redistribute it and/or
    35 *  modify it under the terms of the GNU Lesser General Public
     
    1618
    1719#include "config.h"
     20#include "ContextMenu.h"
    1821#include "ContextMenuItem.h"
     22#include "CString.h"
     23#include "NotImplemented.h"
    1924
    20 #include "NotImplemented.h"
     25#include <gtk/gtk.h>
     26
     27#define WEBKIT_CONTEXT_MENU_ACTION "webkit-context-menu"
    2128
    2229namespace WebCore {
    2330
    24 ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription)
     31ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
     32    : m_platformDescription(item)
    2533{
    26     notImplemented();
     34    g_object_ref(m_platformDescription);
    2735}
    2836
     
    3240}
    3341
    34 ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, ContextMenu*)
     42ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
     43    : m_platformDescription(0)
    3544{
    36     notImplemented();
     45    if (type == SeparatorType) {
     46        m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
     47    } else {
     48        m_platformDescription = GTK_MENU_ITEM(gtk_menu_item_new_with_label(title.utf8().data()));
     49        setAction(action);
     50
     51        if (subMenu)
     52            setSubMenu(subMenu);
     53    }
     54
     55#if GLIB_CHECK_VERSION(2,10,0)
     56    g_object_ref_sink(G_OBJECT(m_platformDescription));
     57#else
     58    g_object_ref(G_OBJECT(m_platformDescription));
     59    gtk_object_sink(GTK_OBJECT(m_platformDescription));
     60#endif
    3761}
    3862
    3963ContextMenuItem::~ContextMenuItem()
    4064{
    41     notImplemented();
     65    if (m_platformDescription)
     66        g_object_unref(m_platformDescription);
    4267}
    4368
    4469PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
    4570{
    46     notImplemented();
    47     return m_platformDescription;
     71    PlatformMenuItemDescription menuItem = m_platformDescription;
     72    m_platformDescription = 0;
     73    return menuItem;
    4874}
    4975
    5076ContextMenuItemType ContextMenuItem::type() const
    5177{
    52     notImplemented();
    53     return ActionType;
     78    if (GTK_IS_SEPARATOR_MENU_ITEM(m_platformDescription))
     79        return SeparatorType;
     80    if (gtk_menu_item_get_submenu(m_platformDescription))
     81        return SubmenuType;
     82
     83    return ActionType;
    5484}
    5585
     
    6191ContextMenuAction ContextMenuItem::action() const
    6292{
    63     notImplemented();
    64     return ContextMenuItemTagNoAction;
     93    ASSERT(m_platformDescription);
     94   
     95    return *static_cast<ContextMenuAction*>(g_object_get_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION));
    6596}
    6697
    67 void ContextMenuItem::setAction(ContextMenuAction)
     98void ContextMenuItem::setAction(ContextMenuAction action)
    6899{
    69     notImplemented();
     100    ASSERT(m_platformDescription);
     101
     102    // FIXME: Check the memory management of menuAction.
     103    ContextMenuAction* menuAction = static_cast<ContextMenuAction*>(malloc(sizeof(ContextMenuAction*)));
     104    *menuAction = action;
     105    g_object_set_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION, menuAction);
    70106}
    71107
     
    83119PlatformMenuDescription ContextMenuItem::platformSubMenu() const
    84120{
    85     notImplemented();
    86     return 0;
     121    return GTK_MENU(gtk_menu_item_get_submenu(m_platformDescription));
    87122}
    88123
    89 void ContextMenuItem::setSubMenu(ContextMenu*)
     124void ContextMenuItem::setSubMenu(ContextMenu* menu)
    90125{
    91     notImplemented();
     126    gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->releasePlatformDescription()));
    92127}
    93128
    94 void ContextMenuItem::setChecked(bool)
     129void ContextMenuItem::setChecked(bool shouldCheck)
    95130{
    96     notImplemented();
     131    ASSERT(type() == ActionType);
     132
     133    if (GTK_IS_CHECK_MENU_ITEM(m_platformDescription)) {
     134        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(m_platformDescription), shouldCheck);
     135    } else {
     136        // TODO: Need to morph this into a GtkCheckMenuItem.
     137        notImplemented();
     138    }
    97139}
    98140
    99 void ContextMenuItem::setEnabled(bool)
     141void ContextMenuItem::setEnabled(bool shouldEnable)
    100142{
    101     notImplemented();
     143    gtk_widget_set_sensitive(GTK_WIDGET(m_platformDescription), shouldEnable);
    102144}
    103145
  • trunk/WebKit/gtk/ChangeLog

    r29033 r29080  
     12008-01-02  Luca Bruno  <lethalman88@gmail.com>
     2
     3        Reviewed by Alp Toker.
     4
     5        http://bugs.webkit.org/show_bug.cgi?id=16115
     6        [GTK] ContextMenu and ContextMenuItem lacks an implementation
     7
     8        Add context menu support.
     9
     10        Based on a patch by Holger Freyther.
     11
     12        * WebCoreSupport/ContextMenuClientGtk.cpp:
     13        (WebKit::ContextMenuClient::getCustomMenuFromDefaultItems):
     14        * WebView/webkitprivate.h:
     15        * WebView/webkitwebview.cpp:
     16
    1172007-12-29  Jan Michael Alonzo  <jmalonzo@unpluggable.com>
    218
  • trunk/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp

    r28862 r29080  
    1616
    1717#include "config.h"
     18#include "ContextMenu.h"
    1819#include "ContextMenuClientGtk.h"
    1920
     
    3132}
    3233
    33 PlatformMenuDescription ContextMenuClient::getCustomMenuFromDefaultItems(ContextMenu*)
     34PlatformMenuDescription ContextMenuClient::getCustomMenuFromDefaultItems(ContextMenu* menu)
    3435{
    35     notImplemented();
    36     return PlatformMenuDescription();
     36    return menu->releasePlatformDescription();
    3737}
    3838
  • trunk/WebKit/gtk/WebView/webkitprivate.h

    r28963 r29080  
    6262        WebCore::String* userAgent;
    6363
     64        gint lastPopupXPosition;
     65        gint lastPopupYPosition;
     66
    6467        HashSet<GtkWidget*> children;
    6568        bool editable;
  • trunk/WebKit/gtk/WebView/webkitwebview.cpp

    r29013 r29080  
    2929#include "CString.h"
    3030#include "ChromeClientGtk.h"
     31#include "ContextMenu.h"
    3132#include "ContextMenuClientGtk.h"
     33#include "ContextMenuController.h"
     34#include "Cursor.h"
    3235#include "DragClientGtk.h"
    3336#include "Editor.h"
     
    8992G_DEFINE_TYPE(WebKitWebView, webkit_web_view, GTK_TYPE_CONTAINER)
    9093
     94static void webkit_web_view_context_menu_position_func(GtkMenu*, gint* x, gint* y, gboolean* pushIn, WebKitWebViewPrivate* data)
     95{
     96    *pushIn = FALSE;
     97    *x = data->lastPopupXPosition;
     98    *y = data->lastPopupYPosition;
     99}
     100
     101static gboolean webkit_web_view_forward_context_menu_event(WebKitWebView* webView, const PlatformMouseEvent& event)
     102{
     103    Page* page = core(webView);
     104    page->contextMenuController()->clearContextMenu();
     105    Frame* focusedFrame = page->focusController()->focusedOrMainFrame();
     106    focusedFrame->view()->setCursor(pointerCursor());
     107    bool handledEvent = focusedFrame->eventHandler()->sendContextMenuEvent(event);
     108    if (!handledEvent)
     109        return FALSE;
     110
     111    ContextMenu* coreMenu = page->contextMenuController()->contextMenu();
     112    if (!coreMenu)
     113        return FALSE;
     114
     115    if (!coreMenu->platformDescription())
     116        return FALSE;
     117
     118
     119    WebKitWebViewPrivate* pageData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView);
     120    pageData->lastPopupXPosition = event.globalX();
     121    pageData->lastPopupYPosition = event.globalY();
     122    gtk_menu_popup(GTK_MENU(coreMenu->platformDescription()), NULL, NULL,
     123                   reinterpret_cast<GtkMenuPositionFunc>(webkit_web_view_context_menu_position_func), pageData,
     124                   event.button() + 1, gtk_get_current_event_time());
     125    return TRUE;
     126}
     127
     128static gboolean webkit_web_view_popup_menu_handler(GtkWidget* widget)
     129{
     130    static const int contextMenuMargin = 1;
     131
     132    // The context menu event was generated from the keyboard, so show the context menu by the current selection.
     133    Page* page = core(WEBKIT_WEB_VIEW(widget));
     134    FrameView* view = page->mainFrame()->view();
     135    Position start = page->mainFrame()->selectionController()->selection().start();
     136    Position end = page->mainFrame()->selectionController()->selection().end();
     137
     138    int rightAligned = FALSE;
     139    IntPoint location;
     140
     141    if (!start.node() || !end.node())
     142        location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin);
     143    else {
     144        RenderObject* renderer = start.node()->renderer();
     145        if (!renderer)
     146            return FALSE;
     147
     148        // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:]).
     149        int extraWidthToEndOfLine = 0;
     150        IntRect startCaretRect = renderer->caretRect(start.offset(), DOWNSTREAM, &extraWidthToEndOfLine);
     151        IntRect endCaretRect = renderer->caretRect(end.offset(), UPSTREAM);
     152
     153        IntRect firstRect;
     154        if (startCaretRect.y() == endCaretRect.y())
     155            firstRect = IntRect(MIN(startCaretRect.x(), endCaretRect.x()),
     156                                startCaretRect.y(),
     157                                abs(endCaretRect.x() - startCaretRect.x()),
     158                                MAX(startCaretRect.height(), endCaretRect.height()));
     159        else
     160            firstRect = IntRect(startCaretRect.x(),
     161                                startCaretRect.y(),
     162                                startCaretRect.width() + extraWidthToEndOfLine,
     163                                startCaretRect.height());
     164
     165        location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom());
     166    }
     167
     168    int x, y;
     169    gdk_window_get_origin(GTK_WIDGET(view->containingWindow())->window, &x, &y);
     170
     171    // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element.
     172    // Ideally we'd have the position of a context menu event be separate from its target node.
     173    location = view->contentsToWindow(location) + IntSize(0, -1);
     174    IntPoint global = location + IntSize(x, y);
     175    PlatformMouseEvent event(location, global, NoButton, MouseEventPressed, 0, false, false, false, false, gtk_get_current_event_time());
     176
     177    return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), event);
     178}
     179
    91180static void webkit_web_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
    92181    WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
     
    181270    // FIXME: need to keep track of subframe focus for key events
    182271    gtk_widget_grab_focus(GTK_WIDGET(widget));
    183     return frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
     272
     273    if (event->button == 3)
     274        return webkit_web_view_forward_context_menu_event(WEBKIT_WEB_VIEW(widget), PlatformMouseEvent(event));
     275    else
     276        return frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
    184277}
    185278
     
    804897    widgetClass->scroll_event = webkit_web_view_scroll_event;
    805898    widgetClass->size_allocate = webkit_web_view_size_allocate;
     899    widgetClass->popup_menu = webkit_web_view_popup_menu_handler;
    806900
    807901    GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webViewClass);
     
    887981    GTK_WIDGET_SET_FLAGS(webView, GTK_CAN_FOCUS);
    888982    webViewData->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView));
     983    webViewData->lastPopupXPosition = webViewData->lastPopupYPosition = -1;
    889984    webViewData->editable = false;
    890985
Note: See TracChangeset for help on using the changeset viewer.