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"
15 #include "wx/minifram.h"
18 #include "wx/settings.h"
19 #include "wx/dcscreen.h"
23 #include "wx/gtk/win_gtk.h"
24 #include "wx/gtk/private.h"
27 #include <gdk/gdkprivate.h>
30 //-----------------------------------------------------------------------------
32 //-----------------------------------------------------------------------------
34 extern bool g_blockEventsOnDrag
;
35 extern bool g_blockEventsOnScroll
;
36 extern GtkWidget
*wxGetRootWindow();
38 //-----------------------------------------------------------------------------
39 // "expose_event" of m_mainWidget
40 //-----------------------------------------------------------------------------
42 // StepColour() it a utility function that simply darkens
43 // or lightens a color, based on the specified percentage
44 static wxColor
StepColour(const wxColor
& c
, int percent
)
46 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
47 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
48 (unsigned char)wxMin((g
*percent
)/100,255),
49 (unsigned char)wxMin((b
*percent
)/100,255));
52 static wxColor
LightContrastColour(const wxColour
& c
)
56 // if the color is especially dark, then
57 // make the contrast even lighter
58 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
61 return StepColour(c
, amount
);
65 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxMiniFrame
*win
)
67 if (g_isIdle
) wxapp_install_idle_handler();
69 if (!win
->m_hasVMT
) return;
70 if (gdk_event
->count
> 0) return;
72 GtkPizza
*pizza
= GTK_PIZZA(widget
);
74 gtk_paint_shadow (widget
->style
,
78 NULL
, NULL
, NULL
, // FIXME: No clipping?
80 win
->m_width
, win
->m_height
);
82 int style
= win
->GetWindowStyle();
86 dc
.m_window
= pizza
->bin_window
;
88 if (style
& wxRESIZE_BORDER
)
90 dc
.SetBrush( *wxGREY_BRUSH
);
91 dc
.SetPen( *wxTRANSPARENT_PEN
);
92 dc
.DrawRectangle( win
->m_width
- 14, win
->m_height
-14, 14, 14 );
95 if (!win
->GetTitle().empty() &&
96 ((style
& wxCAPTION
) ||
97 (style
& wxTINY_CAPTION_HORIZ
) ||
98 (style
& wxTINY_CAPTION_VERT
)))
100 dc
.SetFont( *wxSMALL_FONT
);
101 int height
= dc
.GetCharHeight();
103 wxBrush
brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) ) );
104 dc
.SetBrush( brush
);
105 dc
.SetPen( *wxTRANSPARENT_PEN
);
106 dc
.DrawRectangle( 3, 3, win
->m_width
- 7, height
-2 );
108 dc
.SetTextForeground( *wxWHITE
);
109 dc
.DrawText( win
->GetTitle(), 6, 3 );
111 if (style
& wxCLOSE_BOX
)
112 dc
.DrawBitmap( win
->m_closeButton
, win
->m_width
-19, 3, true );
117 //-----------------------------------------------------------------------------
118 // "button_press_event" of m_mainWidget
119 //-----------------------------------------------------------------------------
122 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
124 if (g_isIdle
) wxapp_install_idle_handler();
126 if (!win
->m_hasVMT
) return FALSE
;
127 if (g_blockEventsOnDrag
) return TRUE
;
128 if (g_blockEventsOnScroll
) return TRUE
;
130 if (win
->m_isDragging
) return TRUE
;
132 GtkPizza
*pizza
= GTK_PIZZA(widget
);
133 if (gdk_event
->window
!= pizza
->bin_window
) return TRUE
;
135 int style
= win
->GetWindowStyle();
137 int y
= (int)gdk_event
->y
;
138 int x
= (int)gdk_event
->x
;
140 if ((style
& wxRESIZE_BORDER
) &&
141 (x
> win
->m_width
-14) && (y
> win
->m_height
-14))
143 GtkWidget
*ancestor
= gtk_widget_get_toplevel( widget
);
145 GdkWindow
*source
= GTK_PIZZA(widget
)->bin_window
;
149 gdk_window_get_origin( source
, &org_x
, &org_y
);
151 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
152 GDK_WINDOW_EDGE_SOUTH_EAST
,
161 if ((style
& wxCLOSE_BOX
) &&
162 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
164 if ((y
> 3) && (y
< 19) && (x
> win
->m_width
-19) && (x
< win
->m_width
-3))
172 dc
.SetFont( *wxSMALL_FONT
);
173 int height
= dc
.GetCharHeight() + 1;
176 if (y
> height
) return TRUE
;
178 gdk_window_raise( win
->m_widget
->window
);
180 gdk_pointer_grab( widget
->window
, FALSE
,
182 (GDK_BUTTON_PRESS_MASK
|
183 GDK_BUTTON_RELEASE_MASK
|
184 GDK_POINTER_MOTION_MASK
|
185 GDK_POINTER_MOTION_HINT_MASK
|
186 GDK_BUTTON_MOTION_MASK
|
187 GDK_BUTTON1_MOTION_MASK
),
190 (unsigned int) GDK_CURRENT_TIME
);
197 win
->m_isDragging
= true;
203 //-----------------------------------------------------------------------------
204 // "button_release_event" of m_mainWidget
205 //-----------------------------------------------------------------------------
208 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
210 if (g_isIdle
) wxapp_install_idle_handler();
212 if (!win
->m_hasVMT
) return FALSE
;
213 if (g_blockEventsOnDrag
) return TRUE
;
214 if (g_blockEventsOnScroll
) return TRUE
;
216 if (!win
->m_isDragging
) return TRUE
;
218 win
->m_isDragging
= false;
220 int x
= (int)gdk_event
->x
;
221 int y
= (int)gdk_event
->y
;
223 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
226 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
227 x
+= org_x
- win
->m_diffX
;
228 y
+= org_y
- win
->m_diffY
;
231 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
237 //-----------------------------------------------------------------------------
238 // "leave_notify_event" of m_mainWidget
239 //-----------------------------------------------------------------------------
243 gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxMiniFrame
*win
)
246 wxapp_install_idle_handler();
248 if (!win
->m_hasVMT
) return FALSE
;
249 if (g_blockEventsOnDrag
) return FALSE
;
251 gdk_window_set_cursor( widget
->window
, NULL
);
257 //-----------------------------------------------------------------------------
258 // "motion_notify_event" of m_mainWidget
259 //-----------------------------------------------------------------------------
263 gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxMiniFrame
*win
)
266 wxapp_install_idle_handler();
268 if (!win
->m_hasVMT
) return FALSE
;
269 if (g_blockEventsOnDrag
) return TRUE
;
270 if (g_blockEventsOnScroll
) return TRUE
;
272 if (gdk_event
->is_hint
)
276 GdkModifierType state
;
277 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
280 gdk_event
->state
= state
;
283 int style
= win
->GetWindowStyle();
285 int x
= (int)gdk_event
->x
;
286 int y
= (int)gdk_event
->y
;
288 if (!win
->m_isDragging
)
290 if (style
& wxRESIZE_BORDER
)
292 if ((x
> win
->m_width
-14) && (y
> win
->m_height
-14))
293 gdk_window_set_cursor( widget
->window
, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER
) );
295 gdk_window_set_cursor( widget
->window
, NULL
);
300 win
->m_oldX
= x
- win
->m_diffX
;
301 win
->m_oldY
= y
- win
->m_diffY
;
305 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
306 x
+= org_x
- win
->m_diffX
;
307 y
+= org_y
- win
->m_diffY
;
310 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
317 //-----------------------------------------------------------------------------
319 //-----------------------------------------------------------------------------
321 static unsigned char close_bits
[]={
322 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
323 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
324 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
327 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
)
329 bool wxMiniFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
330 const wxPoint
&pos
, const wxSize
&size
,
331 long style
, const wxString
&name
)
333 style
= style
| wxCAPTION
;
335 if ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
))
338 if (style
& wxRESIZE_BORDER
)
342 m_isDragging
= false;
348 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
350 if (m_parent
&& (GTK_IS_WINDOW(m_parent
->m_widget
)))
352 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
355 if ((style
& wxCLOSE_BOX
) &&
356 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
358 wxImage img
= wxBitmap((const char*)close_bits
, 16, 16).ConvertToImage();
359 img
.Replace(0,0,0,123,123,123);
360 img
.SetMaskColour(123,123,123);
361 m_closeButton
= wxBitmap( img
);
364 /* these are called when the borders are drawn */
365 g_signal_connect (m_mainWidget
, "expose_event",
366 G_CALLBACK (gtk_window_own_expose_callback
), this );
368 /* these are required for dragging the mini frame around */
369 g_signal_connect (m_mainWidget
, "button_press_event",
370 G_CALLBACK (gtk_window_button_press_callback
), this);
371 g_signal_connect (m_mainWidget
, "button_release_event",
372 G_CALLBACK (gtk_window_button_release_callback
), this);
373 g_signal_connect (m_mainWidget
, "motion_notify_event",
374 G_CALLBACK (gtk_window_motion_notify_callback
), this);
375 g_signal_connect (m_mainWidget
, "leave_notify_event",
376 G_CALLBACK (gtk_window_leave_callback
), this);
380 void wxMiniFrame::SetTitle( const wxString
&title
)
382 wxFrame::SetTitle( title
);
384 if (GTK_PIZZA(m_mainWidget
)->bin_window
)
385 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true );
388 #endif // wxUSE_MINIFRAME