1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/minifram.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  13 #include "wx/minifram.h" 
  17 #include "wx/dcscreen.h" 
  20 #include "wx/gtk/win_gtk.h" 
  21 #include "wx/gtk/private.h" 
  24 #include <gdk/gdkprivate.h> 
  27 //----------------------------------------------------------------------------- 
  29 //----------------------------------------------------------------------------- 
  31 extern bool        g_blockEventsOnDrag
; 
  32 extern bool        g_blockEventsOnScroll
; 
  33 extern GtkWidget  
*wxGetRootWindow(); 
  35 //----------------------------------------------------------------------------- 
  37 //----------------------------------------------------------------------------- 
  39 /* draw XOR rectangle when moving mine frame around */ 
  41 static void DrawFrame( GtkWidget 
*widget
, int x
, int y
, int w
, int h 
) 
  45     gdk_window_get_origin( widget
->window
, &org_x
, &org_y 
); 
  49     GdkGC 
*gc 
= gdk_gc_new( GDK_ROOT_PARENT() ); 
  50     gdk_gc_set_subwindow( gc
, GDK_INCLUDE_INFERIORS 
); 
  51     gdk_gc_set_function( gc
, GDK_INVERT 
); 
  53     gdk_draw_rectangle( GDK_ROOT_PARENT(), gc
, FALSE
, x
, y
, w
, h 
); 
  57 //----------------------------------------------------------------------------- 
  58 // "expose_event" of m_mainWidget 
  59 //----------------------------------------------------------------------------- 
  62 static void gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxFrame 
*win 
) 
  64     if (g_isIdle
) wxapp_install_idle_handler(); 
  66     if (!win
->m_hasVMT
) return; 
  67     if (gdk_event
->count 
> 0) return; 
  69     GtkPizza 
*pizza 
= GTK_PIZZA(widget
); 
  71     gtk_paint_shadow (widget
->style
, 
  75                       NULL
, NULL
, NULL
, // FIXME: No clipping? 
  77                       win
->m_width
, win
->m_height
); 
  79     if (!win
->GetTitle().empty() && 
  80         ((win
->GetWindowStyle() & wxCAPTION
) || 
  81          (win
->GetWindowStyle() & wxTINY_CAPTION_HORIZ
) || 
  82          (win
->GetWindowStyle() & wxTINY_CAPTION_VERT
))) 
  85         dc
.SetFont( *wxSMALL_FONT 
); 
  86         int height 
= dc
.GetCharHeight(); 
  88         GdkGC 
*gc 
= gdk_gc_new( pizza
->bin_window 
); 
  89         gdk_gc_set_foreground( gc
, &widget
->style
->bg
[GTK_STATE_SELECTED
] ); 
  90         gdk_draw_rectangle( pizza
->bin_window
, gc
, TRUE
, 
  98         dc
.m_window 
= pizza
->bin_window
; 
  99         dc
.SetTextForeground( *wxWHITE 
); 
 100         dc
.DrawText( win
->GetTitle(), 6, 3 ); 
 105 //----------------------------------------------------------------------------- 
 106 // "button_press_event" of m_mainWidget 
 107 //----------------------------------------------------------------------------- 
 110 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxMiniFrame 
*win 
) 
 112     if (g_isIdle
) wxapp_install_idle_handler(); 
 114     if (!win
->m_hasVMT
) return FALSE
; 
 115     if (g_blockEventsOnDrag
) return TRUE
; 
 116     if (g_blockEventsOnScroll
) return TRUE
; 
 118     if (win
->m_isDragging
) return TRUE
; 
 120     GtkPizza 
*pizza 
= GTK_PIZZA(widget
); 
 121     if (gdk_event
->window 
!= pizza
->bin_window
) return TRUE
; 
 124     dc
.SetFont( *wxSMALL_FONT 
); 
 125     int height 
= dc
.GetCharHeight() + 1; 
 127     if (gdk_event
->y 
> height
) return TRUE
; 
 129     gdk_window_raise( win
->m_widget
->window 
); 
 131     gdk_pointer_grab( widget
->window
, FALSE
, 
 133                          (GDK_BUTTON_PRESS_MASK 
| 
 134                           GDK_BUTTON_RELEASE_MASK 
| 
 135                           GDK_POINTER_MOTION_MASK        
| 
 136                           GDK_POINTER_MOTION_HINT_MASK  
| 
 137                           GDK_BUTTON_MOTION_MASK        
| 
 138                           GDK_BUTTON1_MOTION_MASK
), 
 141                       (unsigned int) GDK_CURRENT_TIME 
); 
 143     win
->m_diffX 
= (int)gdk_event
->x
; 
 144     win
->m_diffY 
= (int)gdk_event
->y
; 
 145     DrawFrame( widget
, 0, 0, win
->m_width
, win
->m_height 
); 
 149     win
->m_isDragging 
= true; 
 155 //----------------------------------------------------------------------------- 
 156 // "button_release_event" of m_mainWidget 
 157 //----------------------------------------------------------------------------- 
 160 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxMiniFrame 
*win 
) 
 162     if (g_isIdle
) wxapp_install_idle_handler(); 
 164     if (!win
->m_hasVMT
) return FALSE
; 
 165     if (g_blockEventsOnDrag
) return TRUE
; 
 166     if (g_blockEventsOnScroll
) return TRUE
; 
 168     if (!win
->m_isDragging
) return TRUE
; 
 170     win
->m_isDragging 
= FALSE
; 
 172     int x 
= (int)gdk_event
->x
; 
 173     int y 
= (int)gdk_event
->y
; 
 175     DrawFrame( widget
, win
->m_oldX
, win
->m_oldY
, win
->m_width
, win
->m_height 
); 
 176     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
 179     gdk_window_get_origin( widget
->window
, &org_x
, &org_y 
); 
 180     x 
+= org_x 
- win
->m_diffX
; 
 181     y 
+= org_y 
- win
->m_diffY
; 
 184     gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y 
); 
 190 //----------------------------------------------------------------------------- 
 191 // "motion_notify_event" of m_mainWidget 
 192 //----------------------------------------------------------------------------- 
 195 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, GdkEventMotion 
*gdk_event
, wxMiniFrame 
*win 
) 
 197     if (g_isIdle
) wxapp_install_idle_handler(); 
 199     if (!win
->m_hasVMT
) return FALSE
; 
 200     if (g_blockEventsOnDrag
) return TRUE
; 
 201     if (g_blockEventsOnScroll
) return TRUE
; 
 203     if (!win
->m_isDragging
) return TRUE
; 
 205     if (gdk_event
->is_hint
) 
 209        GdkModifierType state
; 
 210        gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 213        gdk_event
->state 
= state
; 
 216     DrawFrame( widget
, win
->m_oldX
, win
->m_oldY
, win
->m_width
, win
->m_height 
); 
 217     win
->m_oldX 
= (int)gdk_event
->x 
- win
->m_diffX
; 
 218     win
->m_oldY 
= (int)gdk_event
->y 
- win
->m_diffY
; 
 219     DrawFrame( widget
, win
->m_oldX
, win
->m_oldY
, win
->m_width
, win
->m_height 
); 
 225 //----------------------------------------------------------------------------- 
 226 // "clicked" of X system button 
 227 //----------------------------------------------------------------------------- 
 230 static void gtk_button_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxMiniFrame 
*mf 
) 
 232     if (g_isIdle
) wxapp_install_idle_handler(); 
 238 //----------------------------------------------------------------------------- 
 240 //----------------------------------------------------------------------------- 
 242 static const char *cross_xpm
[] = { 
 243 /* columns rows colors chars-per-pixel */ 
 255 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
) 
 257 bool wxMiniFrame::Create( wxWindow 
*parent
, wxWindowID id
, const wxString 
&title
, 
 258       const wxPoint 
&pos
, const wxSize 
&size
, 
 259       long style
, const wxString 
&name 
) 
 261     style 
= style 
| wxCAPTION
; 
 263     if ((style 
& wxCAPTION
) || (style 
& wxTINY_CAPTION_HORIZ
) || (style 
& wxTINY_CAPTION_VERT
)) 
 267     m_isDragging 
= false; 
 273     wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name 
); 
 275     if (m_parent 
&& (GTK_IS_WINDOW(m_parent
->m_widget
))) 
 277         gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) ); 
 280     if ((style 
& wxSYSTEM_MENU
) && 
 281         ((style 
& wxCAPTION
) || (style 
& wxTINY_CAPTION_HORIZ
) || (style 
& wxTINY_CAPTION_VERT
))) 
 283         GdkBitmap 
*mask 
= (GdkBitmap
*) NULL
; 
 284         GdkPixmap 
*pixmap 
= gdk_pixmap_create_from_xpm_d
 
 286                                 wxGetRootWindow()->window
, 
 292         GtkWidget 
*pw 
= gtk_pixmap_new( pixmap
, mask 
); 
 293         gdk_bitmap_unref( mask 
); 
 294         gdk_pixmap_unref( pixmap 
); 
 295         gtk_widget_show( pw 
); 
 297         GtkWidget 
*close_button 
= gtk_button_new(); 
 299         if (!gtk_check_version(2,4,0)) 
 300             gtk_button_set_focus_on_click( GTK_BUTTON(close_button
), FALSE 
); 
 302         gtk_container_add( GTK_CONTAINER(close_button
), pw 
); 
 304         gtk_pizza_put( GTK_PIZZA(m_mainWidget
), 
 306                          size
.x
-16, 4, 11, 11 ); 
 308         gtk_widget_show( close_button 
); 
 310         g_signal_connect (close_button
, "clicked", 
 311                           G_CALLBACK (gtk_button_clicked_callback
), 
 315     /* these are called when the borders are drawn */ 
 316     g_signal_connect (m_mainWidget
, "expose_event", 
 317                       G_CALLBACK (gtk_window_own_expose_callback
), this ); 
 319     /* these are required for dragging the mini frame around */ 
 320     g_signal_connect (m_mainWidget
, "button_press_event", 
 321                       G_CALLBACK (gtk_window_button_press_callback
), this); 
 322     g_signal_connect (m_mainWidget
, "button_release_event", 
 323                       G_CALLBACK (gtk_window_button_release_callback
), this); 
 324     g_signal_connect (m_mainWidget
, "motion_notify_event", 
 325                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
 330 void wxMiniFrame::SetTitle( const wxString 
&title 
) 
 332     wxFrame::SetTitle( title 
); 
 334     gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true );