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/dcclient.h"
23 #include "wx/gtk/win_gtk.h"
24 #include "wx/gtk/private.h"
26 //-----------------------------------------------------------------------------
28 //-----------------------------------------------------------------------------
30 extern bool g_blockEventsOnDrag
;
31 extern bool g_blockEventsOnScroll
;
32 extern GtkWidget
*wxGetRootWindow();
34 //-----------------------------------------------------------------------------
35 // "expose_event" of m_mainWidget
36 //-----------------------------------------------------------------------------
38 // StepColour() it a utility function that simply darkens
39 // or lightens a color, based on the specified percentage
40 static wxColor
StepColour(const wxColor
& c
, int percent
)
42 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
43 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
44 (unsigned char)wxMin((g
*percent
)/100,255),
45 (unsigned char)wxMin((b
*percent
)/100,255));
48 static wxColor
LightContrastColour(const wxColour
& c
)
52 // if the color is especially dark, then
53 // make the contrast even lighter
54 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
57 return StepColour(c
, amount
);
61 static gboolean
gtk_window_own_expose_callback(GtkWidget
* widget
, GdkEventExpose
* gdk_event
, wxMiniFrame
* win
)
63 // don't need to install idle handler, its done from "event" signal
65 if (!win
->m_hasVMT
|| gdk_event
->count
> 0)
68 GtkPizza
*pizza
= GTK_PIZZA(widget
);
70 gtk_paint_shadow (widget
->style
,
74 NULL
, NULL
, NULL
, // FIXME: No clipping?
76 win
->m_width
, win
->m_height
);
78 int style
= win
->GetWindowStyle();
82 dc
.m_window
= pizza
->bin_window
;
84 if (style
& wxRESIZE_BORDER
)
86 dc
.SetBrush( *wxGREY_BRUSH
);
87 dc
.SetPen( *wxTRANSPARENT_PEN
);
88 dc
.DrawRectangle( win
->m_width
- 14, win
->m_height
-14, 14, 14 );
91 if (!win
->GetTitle().empty() &&
92 ((style
& wxCAPTION
) ||
93 (style
& wxTINY_CAPTION_HORIZ
) ||
94 (style
& wxTINY_CAPTION_VERT
)))
96 dc
.SetFont( *wxSMALL_FONT
);
97 int height
= dc
.GetCharHeight();
99 wxBrush
brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) ) );
100 dc
.SetBrush( brush
);
101 dc
.SetPen( *wxTRANSPARENT_PEN
);
102 dc
.DrawRectangle( 3, 3, win
->m_width
- 7, height
);
104 dc
.SetTextForeground( *wxWHITE
);
105 dc
.DrawText( win
->GetTitle(), 6, 3 );
107 if (style
& wxCLOSE_BOX
)
108 dc
.DrawBitmap( win
->m_closeButton
, win
->m_width
-19, 2, true );
114 //-----------------------------------------------------------------------------
115 // "button_press_event" of m_mainWidget
116 //-----------------------------------------------------------------------------
119 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
121 // don't need to install idle handler, its done from "event" signal
123 if (!win
->m_hasVMT
) return FALSE
;
124 if (g_blockEventsOnDrag
) return TRUE
;
125 if (g_blockEventsOnScroll
) return TRUE
;
127 if (win
->m_isDragging
) return TRUE
;
129 GtkPizza
*pizza
= GTK_PIZZA(widget
);
130 if (gdk_event
->window
!= pizza
->bin_window
) return TRUE
;
132 int style
= win
->GetWindowStyle();
134 int y
= (int)gdk_event
->y
;
135 int x
= (int)gdk_event
->x
;
137 if ((style
& wxRESIZE_BORDER
) &&
138 (x
> win
->m_width
-14) && (y
> win
->m_height
-14))
140 GtkWidget
*ancestor
= gtk_widget_get_toplevel( widget
);
142 GdkWindow
*source
= GTK_PIZZA(widget
)->bin_window
;
146 gdk_window_get_origin( source
, &org_x
, &org_y
);
148 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
149 GDK_WINDOW_EDGE_SOUTH_EAST
,
158 if ((style
& wxCLOSE_BOX
) &&
159 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
161 if ((y
> 3) && (y
< 19) && (x
> win
->m_width
-19) && (x
< win
->m_width
-3))
169 dc
.SetFont( *wxSMALL_FONT
);
170 int height
= dc
.GetCharHeight() + 1;
173 if (y
> height
) return TRUE
;
175 gdk_window_raise( win
->m_widget
->window
);
177 gdk_pointer_grab( widget
->window
, FALSE
,
179 (GDK_BUTTON_PRESS_MASK
|
180 GDK_BUTTON_RELEASE_MASK
|
181 GDK_POINTER_MOTION_MASK
|
182 GDK_POINTER_MOTION_HINT_MASK
|
183 GDK_BUTTON_MOTION_MASK
|
184 GDK_BUTTON1_MOTION_MASK
),
187 (unsigned int) GDK_CURRENT_TIME
);
194 win
->m_isDragging
= true;
200 //-----------------------------------------------------------------------------
201 // "button_release_event" of m_mainWidget
202 //-----------------------------------------------------------------------------
205 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
207 // don't need to install idle handler, its done from "event" signal
209 if (!win
->m_hasVMT
) return FALSE
;
210 if (g_blockEventsOnDrag
) return TRUE
;
211 if (g_blockEventsOnScroll
) return TRUE
;
213 if (!win
->m_isDragging
) return TRUE
;
215 win
->m_isDragging
= false;
217 int x
= (int)gdk_event
->x
;
218 int y
= (int)gdk_event
->y
;
220 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
223 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
224 x
+= org_x
- win
->m_diffX
;
225 y
+= org_y
- win
->m_diffY
;
228 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
234 //-----------------------------------------------------------------------------
235 // "leave_notify_event" of m_mainWidget
236 //-----------------------------------------------------------------------------
240 gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxMiniFrame
*win
)
242 // don't need to install idle handler, its done from "event" signal
244 if (!win
->m_hasVMT
) return FALSE
;
245 if (g_blockEventsOnDrag
) return FALSE
;
247 gdk_window_set_cursor( widget
->window
, NULL
);
253 //-----------------------------------------------------------------------------
254 // "motion_notify_event" of m_mainWidget
255 //-----------------------------------------------------------------------------
259 gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxMiniFrame
*win
)
261 // don't need to install idle handler, its done from "event" signal
263 if (!win
->m_hasVMT
) return FALSE
;
264 if (g_blockEventsOnDrag
) return TRUE
;
265 if (g_blockEventsOnScroll
) return TRUE
;
267 if (gdk_event
->is_hint
)
271 GdkModifierType state
;
272 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
275 gdk_event
->state
= state
;
278 int style
= win
->GetWindowStyle();
280 int x
= (int)gdk_event
->x
;
281 int y
= (int)gdk_event
->y
;
283 if (!win
->m_isDragging
)
285 if (style
& wxRESIZE_BORDER
)
287 if ((x
> win
->m_width
-14) && (y
> win
->m_height
-14))
288 gdk_window_set_cursor( widget
->window
, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER
) );
290 gdk_window_set_cursor( widget
->window
, NULL
);
295 win
->m_oldX
= x
- win
->m_diffX
;
296 win
->m_oldY
= y
- win
->m_diffY
;
300 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
301 x
+= org_x
- win
->m_diffX
;
302 y
+= org_y
- win
->m_diffY
;
305 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
312 //-----------------------------------------------------------------------------
314 //-----------------------------------------------------------------------------
316 static unsigned char close_bits
[]={
317 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
318 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
319 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
322 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
)
324 bool wxMiniFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
325 const wxPoint
&pos
, const wxSize
&size
,
326 long style
, const wxString
&name
)
328 style
= style
| wxCAPTION
;
330 if ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
))
333 if (style
& wxRESIZE_BORDER
)
337 m_isDragging
= false;
343 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
345 if (m_parent
&& (GTK_IS_WINDOW(m_parent
->m_widget
)))
347 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
350 if ((style
& wxCLOSE_BOX
) &&
351 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
353 wxImage img
= wxBitmap((const char*)close_bits
, 16, 16).ConvertToImage();
354 img
.Replace(0,0,0,123,123,123);
355 img
.SetMaskColour(123,123,123);
356 m_closeButton
= wxBitmap( img
);
359 /* these are called when the borders are drawn */
360 g_signal_connect (m_mainWidget
, "expose_event",
361 G_CALLBACK (gtk_window_own_expose_callback
), this );
363 /* these are required for dragging the mini frame around */
364 g_signal_connect (m_mainWidget
, "button_press_event",
365 G_CALLBACK (gtk_window_button_press_callback
), this);
366 g_signal_connect (m_mainWidget
, "button_release_event",
367 G_CALLBACK (gtk_window_button_release_callback
), this);
368 g_signal_connect (m_mainWidget
, "motion_notify_event",
369 G_CALLBACK (gtk_window_motion_notify_callback
), this);
370 g_signal_connect (m_mainWidget
, "leave_notify_event",
371 G_CALLBACK (gtk_window_leave_callback
), this);
375 void wxMiniFrame::SetTitle( const wxString
&title
)
377 wxFrame::SetTitle( title
);
379 if (GTK_PIZZA(m_mainWidget
)->bin_window
)
380 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true );
383 #endif // wxUSE_MINIFRAME