Home | History | Annotate | Download | only in libgtk2ui
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
      6 
      7 #include <gdk/gdk.h>
      8 #include <gdk/gdkx.h>
      9 #include <gtk/gtk.h>
     10 
     11 #include "base/command_line.h"
     12 #include "base/environment.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "ui/aura/window.h"
     15 #include "ui/aura/window_tree_host.h"
     16 #include "ui/base/accelerators/accelerator.h"
     17 #include "ui/events/event_constants.h"
     18 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
     19 #include "ui/gfx/size.h"
     20 
     21 namespace {
     22 
     23 const char kAuraTransientParent[] = "aura-transient-parent";
     24 
     25 void CommonInitFromCommandLine(const CommandLine& command_line,
     26                                void (*init_func)(gint*, gchar***)) {
     27   const std::vector<std::string>& args = command_line.argv();
     28   int argc = args.size();
     29   scoped_ptr<char *[]> argv(new char *[argc + 1]);
     30   for (size_t i = 0; i < args.size(); ++i) {
     31     // TODO(piman (at) google.com): can gtk_init modify argv? Just being safe
     32     // here.
     33     argv[i] = strdup(args[i].c_str());
     34   }
     35   argv[argc] = NULL;
     36   char **argv_pointer = argv.get();
     37 
     38   init_func(&argc, &argv_pointer);
     39   for (size_t i = 0; i < args.size(); ++i) {
     40     free(argv[i]);
     41   }
     42 }
     43 
     44 }  // namespace
     45 
     46 namespace libgtk2ui {
     47 
     48 void GtkInitFromCommandLine(const CommandLine& command_line) {
     49   CommonInitFromCommandLine(command_line, gtk_init);
     50 }
     51 
     52 // TODO(erg): This method was copied out of shell_integration_linux.cc. Because
     53 // of how this library is structured as a stand alone .so, we can't call code
     54 // from browser and above.
     55 std::string GetDesktopName(base::Environment* env) {
     56 #if defined(GOOGLE_CHROME_BUILD)
     57   return "google-chrome.desktop";
     58 #else  // CHROMIUM_BUILD
     59   // Allow $CHROME_DESKTOP to override the built-in value, so that development
     60   // versions can set themselves as the default without interfering with
     61   // non-official, packaged versions using the built-in value.
     62   std::string name;
     63   if (env->GetVar("CHROME_DESKTOP", &name) && !name.empty())
     64     return name;
     65   return "chromium-browser.desktop";
     66 #endif
     67 }
     68 
     69 void SetAlwaysShowImage(GtkWidget* image_menu_item) {
     70   gtk_image_menu_item_set_always_show_image(
     71       GTK_IMAGE_MENU_ITEM(image_menu_item), TRUE);
     72 }
     73 
     74 guint GetGdkKeyCodeForAccelerator(const ui::Accelerator& accelerator) {
     75   // The second parameter is false because accelerator keys are expressed in
     76   // terms of the non-shift-modified key.
     77   return XKeysymForWindowsKeyCode(accelerator.key_code(), false);
     78 }
     79 
     80 GdkModifierType GetGdkModifierForAccelerator(
     81     const ui::Accelerator& accelerator) {
     82   int event_flag = accelerator.modifiers();
     83   int modifier = 0;
     84   if (event_flag & ui::EF_SHIFT_DOWN)
     85     modifier |= GDK_SHIFT_MASK;
     86   if (event_flag & ui::EF_CONTROL_DOWN)
     87     modifier |= GDK_CONTROL_MASK;
     88   if (event_flag & ui::EF_ALT_DOWN)
     89     modifier |= GDK_MOD1_MASK;
     90   return static_cast<GdkModifierType>(modifier);
     91 }
     92 
     93 int EventFlagsFromGdkState(guint state) {
     94   int flags = ui::EF_NONE;
     95   flags |= (state & GDK_LOCK_MASK) ? ui::EF_CAPS_LOCK_DOWN : ui::EF_NONE;
     96   flags |= (state & GDK_CONTROL_MASK) ? ui::EF_CONTROL_DOWN : ui::EF_NONE;
     97   flags |= (state & GDK_SHIFT_MASK) ? ui::EF_SHIFT_DOWN : ui::EF_NONE;
     98   flags |= (state & GDK_MOD1_MASK) ? ui::EF_ALT_DOWN : ui::EF_NONE;
     99   flags |= (state & GDK_BUTTON1_MASK) ? ui::EF_LEFT_MOUSE_BUTTON : ui::EF_NONE;
    100   flags |=
    101       (state & GDK_BUTTON2_MASK) ? ui::EF_MIDDLE_MOUSE_BUTTON : ui::EF_NONE;
    102   flags |= (state & GDK_BUTTON3_MASK) ? ui::EF_RIGHT_MOUSE_BUTTON : ui::EF_NONE;
    103   return flags;
    104 }
    105 
    106 void SetGtkTransientForAura(GtkWidget* dialog, aura::Window* parent) {
    107   if (!parent || !parent->GetHost())
    108     return;
    109 
    110   gtk_widget_realize(dialog);
    111   GdkWindow* gdk_window = gtk_widget_get_window(dialog);
    112 
    113   // TODO(erg): Check to make sure we're using X11 if wayland or some other
    114   // display server ever happens. Otherwise, this will crash.
    115   XSetTransientForHint(GDK_WINDOW_XDISPLAY(gdk_window),
    116                        GDK_WINDOW_XID(gdk_window),
    117                        parent->GetHost()->GetAcceleratedWidget());
    118 
    119   // We also set the |parent| as a property of |dialog|, so that we can unlink
    120   // the two later.
    121   g_object_set_data(G_OBJECT(dialog), kAuraTransientParent, parent);
    122 }
    123 
    124 aura::Window* GetAuraTransientParent(GtkWidget* dialog) {
    125   return reinterpret_cast<aura::Window*>(
    126       g_object_get_data(G_OBJECT(dialog), kAuraTransientParent));
    127 }
    128 
    129 void ClearAuraTransientParent(GtkWidget* dialog) {
    130   g_object_set_data(G_OBJECT(dialog), kAuraTransientParent, NULL);
    131 }
    132 
    133 GtkStateType GetGtkState(ui::NativeTheme::State state) {
    134   switch (state) {
    135     case ui::NativeTheme::kDisabled: return GTK_STATE_INSENSITIVE;
    136     case ui::NativeTheme::kHovered:  return GTK_STATE_PRELIGHT;
    137     case ui::NativeTheme::kNormal:   return GTK_STATE_NORMAL;
    138     case ui::NativeTheme::kPressed:  return GTK_STATE_ACTIVE;
    139     case ui::NativeTheme::kMaxState: NOTREACHED() << "Unknown state: " << state;
    140   }
    141   return GTK_STATE_NORMAL;
    142 }
    143 
    144 }  // namespace libgtk2ui
    145