pidgin/plugins/win32/winprefs/gtkappbar.c

branch
cpw.khc.msnp14
changeset 20481
65485e2ed8a3
parent 14286
9ff15ceacd34
parent 20478
46933dc62880
equal deleted inserted replaced
20480:df9df972434f 20481:65485e2ed8a3
1 /*
2 * purple - WinPurple Options Plugin
3 *
4 * File: gtkappbar.c
5 * Date: August 2, 2003
6 * Description: Appbar functionality for Windows GTK+ applications
7 *
8 * Copyright (C) 2003, Herman Bloggs <hermanator12002@yahoo.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25 /*
26 * TODO:
27 * - Move 'App on top' feature from Trans plugin to here
28 * - Bug: Multiple Show/Hide Desktop calls causes client area to disappear
29 */
30 #include <windows.h>
31 #include <winver.h>
32 #include <stdio.h>
33 #include <gtk/gtk.h>
34 #include <gdk/gdkwin32.h>
35 #include "gtkappbar.h"
36 #include "debug.h"
37
38 #define APPBAR_CALLBACK WM_USER + 1010
39
40 typedef HMONITOR WINAPI purple_MonitorFromPoint(POINT, DWORD);
41 typedef HMONITOR WINAPI purple_MonitorFromWindow(HWND, DWORD);
42 typedef BOOL WINAPI purple_GetMonitorInfo(HMONITOR, LPMONITORINFO);
43
44 /* Retrieve the rectangular display area from the specified monitor
45 * Return TRUE if successful, otherwise FALSE
46 */
47 static gboolean
48 get_rect_from_monitor(HMODULE hmod, HMONITOR monitor, RECT *rect) {
49 purple_GetMonitorInfo *the_GetMonitorInfo;
50 MONITORINFO info;
51
52 if (!(the_GetMonitorInfo = (purple_GetMonitorInfo*)
53 GetProcAddress(hmod, "GetMonitorInfoA"))) {
54 return FALSE;
55 }
56
57 info.cbSize = sizeof(info);
58 if (!the_GetMonitorInfo(monitor, &info)) {
59 return FALSE;
60 }
61
62 CopyRect(rect, &(info.rcMonitor));
63
64 return TRUE;
65 }
66
67 /**
68 * This will only work on Win98+ and Win2K+
69 * Return TRUE if successful, otherwise FALSE
70 */
71 static gboolean
72 get_rect_at_point_multimonitor(POINT pt, RECT *rect) {
73 HMODULE hmod;
74 purple_MonitorFromPoint *the_MonitorFromPoint;
75 HMONITOR monitor;
76
77 if (!(hmod = GetModuleHandle("user32"))) {
78 return FALSE;
79 }
80
81 if (!(the_MonitorFromPoint = (purple_MonitorFromPoint*)
82 GetProcAddress(hmod, "MonitorFromPoint"))) {
83 return FALSE;
84 }
85
86 monitor =
87 the_MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
88
89 return get_rect_from_monitor(hmod, monitor, rect);
90 }
91
92 /**
93 * This will only work on Win98+ and Win2K+
94 * Return TRUE if successful, otherwise FALSE
95 */
96 static gboolean
97 get_rect_of_window_multimonitor(HWND window, RECT *rect) {
98 HMODULE hmod;
99 purple_MonitorFromWindow *the_MonitorFromWindow;
100 HMONITOR monitor;
101
102 if (!(hmod = GetModuleHandle("user32"))) {
103 return FALSE;
104 }
105
106 if (!(the_MonitorFromWindow = (purple_MonitorFromWindow*)
107 GetProcAddress(hmod, "MonitorFromWindow"))) {
108 return FALSE;
109 }
110
111 monitor =
112 the_MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
113
114 return get_rect_from_monitor(hmod, monitor, rect);
115 }
116
117 /*
118 * Fallback if cannot get the RECT from the monitor directly
119 */
120 static void get_default_workarea(RECT *rect) {
121 if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, FALSE)) {
122 /* I don't think this will ever happen */
123 rect->left = 0;
124 rect->top = 0;
125 rect->bottom = GetSystemMetrics(SM_CYSCREEN);
126 rect->right = GetSystemMetrics(SM_CXSCREEN);
127 }
128 }
129
130 /* Retrieve the rectangle of the active work area at a point */
131 static void get_rect_at_point(POINT pt, RECT *rc) {
132 if (!get_rect_at_point_multimonitor(pt, rc)) {
133 get_default_workarea(rc);
134 }
135 }
136
137 /* Retrieve the rectangle of the active work area of a window*/
138 static void get_rect_of_window(HWND window, RECT *rc) {
139 if (!get_rect_of_window_multimonitor(window, rc)) {
140 get_default_workarea(rc);
141 }
142 }
143
144 static void get_window_normal_rc(HWND hwnd, RECT *rc) {
145 WINDOWPLACEMENT wplc;
146 GetWindowPlacement(hwnd, &wplc);
147 CopyRect(rc, &wplc.rcNormalPosition);
148 }
149 #if 0
150 static void print_rect(RECT *rc) {
151 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "RECT: L:%ld R:%ld T:%ld B:%ld\n",
152 rc->left, rc->right, rc->top, rc->bottom);
153 }
154 #endif
155 /** Set the window style to be the "Tool Window" style - small header, no min/max buttons */
156 static void set_toolbar(HWND hwnd, gboolean val) {
157 LONG style=0;
158
159 style = GetWindowLong(hwnd, GWL_EXSTYLE);
160 if(val && !(style & WS_EX_TOOLWINDOW))
161 style |= WS_EX_TOOLWINDOW;
162 else if(!val && style & WS_EX_TOOLWINDOW)
163 style &= ~WS_EX_TOOLWINDOW;
164 else
165 return;
166 SetWindowLong(hwnd, GWL_EXSTYLE, style);
167 SetWindowPos(hwnd, 0, 0, 0, 0, 0,
168 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
169
170 /* This really should be the following, but SWP_FRAMECHANGED strangely causes initermittent problems "Show Desktop" done more than once.
171 * Not having SWP_FRAMECHANGED *should* cause the Style not to be applied, but i haven't noticed any problems
172 * SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
173 */
174 }
175 /** Register the window as an appbar */
176 static gboolean gtk_appbar_register(GtkAppBar *ab, HWND hwnd) {
177 APPBARDATA abd;
178
179 abd.cbSize = sizeof(APPBARDATA);
180 abd.hWnd = hwnd;
181 abd.uCallbackMessage = APPBAR_CALLBACK;
182
183 ab->registered = SHAppBarMessage(ABM_NEW, &abd);
184
185 return ab->registered;
186 }
187 /** Unregister the window as an appbar */
188 static gboolean gtk_appbar_unregister(GtkAppBar *ab, HWND hwnd) {
189 APPBARDATA abd;
190
191 if(!ab->registered)
192 return TRUE;
193
194 abd.cbSize = sizeof(APPBARDATA);
195 abd.hWnd = hwnd;
196
197 SHAppBarMessage(ABM_REMOVE, &abd); /** This always returns TRUE */
198
199 ab->registered = FALSE;
200
201 ab->docked = FALSE;
202 ab->docking = FALSE;
203
204 return TRUE;
205 }
206
207 static void gtk_appbar_querypos(GtkAppBar *ab, HWND hwnd, RECT rcWorkspace) {
208 APPBARDATA abd;
209 guint iWidth = 0;
210
211 if(!ab->registered)
212 gtk_appbar_register(ab, hwnd);
213
214 abd.hWnd = hwnd;
215 abd.cbSize = sizeof(APPBARDATA);
216 abd.uEdge = ab->side;
217
218 iWidth = ab->docked_rect.right - ab->docked_rect.left;
219
220 abd.rc.top = rcWorkspace.top;
221 abd.rc.bottom = rcWorkspace.bottom;
222 switch (abd.uEdge)
223 {
224 case ABE_LEFT:
225 abd.rc.left = rcWorkspace.left;
226 abd.rc.right = rcWorkspace.left + iWidth;
227 break;
228
229 case ABE_RIGHT:
230 abd.rc.right = rcWorkspace.right;
231 abd.rc.left = rcWorkspace.right - iWidth;
232 break;
233 }
234
235 /* Ask the system for the screen space */
236 SHAppBarMessage(ABM_QUERYPOS, &abd);
237
238 switch (abd.uEdge)
239 {
240 case ABE_LEFT:
241 abd.rc.right = abd.rc.left + iWidth;
242 break;
243
244 case ABE_RIGHT:
245 abd.rc.left = abd.rc.right - iWidth;
246 break;
247 }
248
249 CopyRect(&(ab->docked_rect), &abd.rc);
250 }
251 /* Actually set the size and screen location of the appbar */
252 static void gtk_appbar_setpos(GtkAppBar *ab, HWND hwnd) {
253 APPBARDATA abd;
254
255 if(!ab->registered)
256 gtk_appbar_register(ab, hwnd);
257
258 abd.hWnd = hwnd;
259 abd.cbSize = sizeof(APPBARDATA);
260 CopyRect(&abd.rc, &(ab->docked_rect));
261 abd.uEdge = ab->side;
262
263 SHAppBarMessage(ABM_SETPOS, &abd);
264 }
265 /** Let any callbacks know that we have docked or undocked */
266 static void gtk_appbar_dispatch_dock_cbs(GtkAppBar *ab, gboolean val) {
267 GList *lst = ab->dock_cbs;
268
269 while(lst) {
270 GtkAppBarDockCB dock_cb = lst->data;
271 dock_cb(val);
272 lst = lst->next;
273 }
274 }
275
276 static GdkFilterReturn wnd_moving(GtkAppBar *ab, GdkXEvent *xevent) {
277 MSG *msg = (MSG*)xevent;
278 POINT cp;
279 RECT *rc = (RECT*)msg->lParam;
280 RECT monRect;
281 int side = -1;
282 long dockAreaWidth = 0;
283
284 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_moving\n");
285
286 GetCursorPos(&cp);
287 get_rect_at_point(cp, &monRect);
288
289 dockAreaWidth = (monRect.right - monRect.left) / 10;
290 /* Which part of the screen are we in ? */
291 if (cp.x > (monRect.right - dockAreaWidth)) {
292 side = ABE_RIGHT;
293 } else if (cp.x < (monRect.left + dockAreaWidth)) {
294 side = ABE_LEFT;
295 }
296
297 if(!ab->docked) {
298 if( (side == ABE_RIGHT || side == ABE_LEFT) ) {
299 if( !ab->docking ) {
300 ab->side = side;
301 GetWindowRect(msg->hwnd, &(ab->docked_rect));
302 gtk_appbar_querypos(ab, msg->hwnd, monRect);
303
304 /* save pre-docking height */
305 ab->undocked_height = rc->bottom - rc->top;
306 ab->docking = TRUE;
307 }
308 }
309 else
310 ab->docking = FALSE;
311 }
312 else if(side < 0) {
313 gtk_appbar_unregister(ab, msg->hwnd);
314 rc->bottom = rc->top + ab->undocked_height;
315 }
316
317 /* Switch to toolbar/regular caption*/
318 if(ab->docking)
319 set_toolbar(msg->hwnd, TRUE);
320 else if(!ab->docked)
321 set_toolbar(msg->hwnd, FALSE);
322
323 return GDK_FILTER_CONTINUE;
324 }
325
326 static GdkFilterReturn wnd_sizing(GtkAppBar *ab, GdkXEvent *xevent) {
327 MSG *msg = (MSG*)xevent;
328
329 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_sizing\n");
330 if(ab->docked) {
331 RECT *rc = (RECT*)msg->lParam;
332 if(ab->side == ABE_LEFT && msg->wParam == WMSZ_RIGHT) {
333 ab->docked_rect.right = rc->right;
334 gtk_appbar_setpos(ab, msg->hwnd);
335 }
336 else if(ab->side == ABE_RIGHT && msg->wParam == WMSZ_LEFT) {
337 ab->docked_rect.left = rc->left;
338 gtk_appbar_setpos(ab, msg->hwnd);
339 }
340 return GDK_FILTER_REMOVE;
341 }
342 return GDK_FILTER_CONTINUE;
343 }
344 /** Notify the system that the appbar has been activated */
345 static GdkFilterReturn wnd_activate(GtkAppBar *ab, GdkXEvent *xevent) {
346 if (ab->registered) {
347 APPBARDATA abd;
348 MSG *msg = (MSG*)xevent;
349 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_activate\n");
350
351 abd.hWnd = msg->hwnd;
352 abd.cbSize = sizeof(APPBARDATA);
353
354 SHAppBarMessage(ABM_ACTIVATE, &abd);
355 }
356 return GDK_FILTER_CONTINUE;
357 }
358 /** Notify the system that the appbar's position has changed */
359 static GdkFilterReturn wnd_poschanged(GtkAppBar *ab, GdkXEvent *xevent) {
360 if (ab->registered) {
361 APPBARDATA abd;
362 MSG *msg = (MSG*)xevent;
363 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_poschanged\n");
364
365 abd.hWnd = msg->hwnd;
366 abd.cbSize = sizeof(APPBARDATA);
367
368 SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
369 }
370 return GDK_FILTER_CONTINUE;
371 }
372 /** The window is about to change */
373 static GdkFilterReturn wnd_poschanging(GtkAppBar *ab, GdkXEvent *xevent) {
374 MSG *msg = (MSG*)xevent;
375 WINDOWPOS *wpos = (WINDOWPOS*)msg->lParam;
376
377 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_poschanging\n");
378
379 if(ab->docked || ab->docking) {
380 wpos->x = ab->docked_rect.left;
381 wpos->y = ab->docked_rect.top;
382 wpos->cx = ab->docked_rect.right - ab->docked_rect.left;
383 wpos->cy = ab->docked_rect.bottom - ab->docked_rect.top;
384 if(IsIconic(msg->hwnd))
385 set_toolbar(msg->hwnd, FALSE);
386 /*return GDK_FILTER_REMOVE;*/
387 }
388 return GDK_FILTER_CONTINUE;
389 }
390
391 static GdkFilterReturn wnd_exitsizemove(GtkAppBar *ab, GdkXEvent *xevent) {
392 MSG *msg = (MSG*)xevent;
393
394 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_exitsizemove\n");
395 if(ab->docking) {
396 gtk_appbar_setpos(ab, msg->hwnd);
397 ab->docking = FALSE;
398 ab->docked = TRUE;
399 gtk_appbar_dispatch_dock_cbs(ab, TRUE);
400 }
401 else if(!ab->docked) {
402 gtk_appbar_unregister(ab, msg->hwnd);
403 gtk_appbar_dispatch_dock_cbs(ab, FALSE);
404 }
405
406 return GDK_FILTER_CONTINUE;
407 }
408
409 static GdkFilterReturn wnd_showwindow(GtkAppBar *ab, GdkXEvent *xevent) {
410 MSG *msg = (MSG*)xevent;
411
412 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_showwindow\n");
413 if(msg->wParam && ab->docked) {
414 ab->iconized = FALSE;
415 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "shown\n");
416 ab->docked = FALSE;
417 gtk_appbar_dock(ab, ab->side);
418 }
419 else if(!msg->wParam && ab->docked) {
420 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "hidden\n");
421 gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
422 set_toolbar(GDK_WINDOW_HWND(ab->win->window), FALSE);
423 ab->docked = TRUE;
424 ab->iconized = TRUE;
425 }
426 return GDK_FILTER_CONTINUE;
427 }
428 /** The window's size has changed */
429 static GdkFilterReturn wnd_size(GtkAppBar *ab, GdkXEvent *xevent) {
430 MSG *msg = (MSG*)xevent;
431
432 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_size\n");
433
434 if(msg->wParam == SIZE_MINIMIZED) {
435 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "Minimize\n");
436 if(ab->docked) {
437 gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
438 ab->docked = TRUE;
439 }
440 }
441 else if(msg->wParam == SIZE_RESTORED) {
442 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "Restore\n");
443 if (!ab->iconized && ab->docked) {
444 gtk_appbar_dock(ab, ab->side);
445 }
446 }
447 return GDK_FILTER_CONTINUE;
448 }
449
450 static GdkFilterReturn wnd_nchittest(GtkAppBar *ab, GdkXEvent *xevent) {
451 MSG *msg = (MSG*)xevent;
452
453 if(ab->docked) {
454 UINT ret = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
455
456 switch(ret) {
457 case HTBOTTOM:
458 case HTBOTTOMLEFT:
459 case HTBOTTOMRIGHT:
460 case HTTOP:
461 case HTTOPLEFT:
462 case HTTOPRIGHT:
463 return GDK_FILTER_REMOVE;
464 case HTLEFT:
465 if(ab->side == ABE_LEFT)
466 return GDK_FILTER_REMOVE;
467 break;
468 case HTRIGHT:
469 if(ab->side == ABE_RIGHT)
470 return GDK_FILTER_REMOVE;
471 break;
472 }
473 }
474 return GDK_FILTER_CONTINUE;
475 }
476
477 #if 0
478 static GdkFilterReturn wnd_initmenupopup(GtkAppBar *ab, GdkXEvent *xevent) {
479 MSG *msg = (MSG*)xevent;
480
481 if(ab->docked && HIWORD(msg->lParam)) {
482 HMENU sysmenu = GetSystemMenu(msg->hwnd, FALSE);
483 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_initpopupmenu: docked: %d ismenu: %d\n", ab->docked, IsMenu(sysmenu));
484 if(EnableMenuItem(sysmenu, SC_MAXIMIZE, MF_BYCOMMAND|MF_GRAYED)<0)
485 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "SC_MAXIMIZE Menu item does not exist\n");
486 if(EnableMenuItem(sysmenu, SC_MOVE, MF_BYCOMMAND|MF_GRAYED)<0)
487 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "SC_MOVE Menu item does not exist\n");
488 return GDK_FILTER_CONTINUE;
489 }
490 else
491 GetSystemMenu(msg->hwnd, TRUE);
492 return GDK_FILTER_CONTINUE;
493 }
494 #endif
495
496 static GdkFilterReturn gtk_appbar_callback(GtkAppBar *ab, GdkXEvent *xevent) {
497 MSG *msg = (MSG*)xevent;
498 RECT orig, windowRect;
499
500 switch (msg->wParam) {
501 case ABN_STATECHANGE:
502 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_STATECHANGE\n");
503 break;
504
505 case ABN_FULLSCREENAPP:
506 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_FULLSCREENAPP: %d\n", (BOOL)msg->lParam);
507 if (!ab->iconized && ab->docked) {
508 if ((BOOL)msg->lParam) {
509 SetWindowPos(msg->hwnd, HWND_BOTTOM, 0, 0, 0, 0,
510 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
511 } else {
512 SetWindowPos(msg->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
513 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED);
514 }
515 }
516
517 break;
518 case ABN_POSCHANGED:
519 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n");
520 CopyRect(&orig, &(ab->docked_rect));
521 get_rect_of_window(msg->hwnd, &windowRect);
522 gtk_appbar_querypos(ab, msg->hwnd, windowRect);
523 if (EqualRect(&orig, &(ab->docked_rect)) == 0) {
524 MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top,
525 ab->docked_rect.right - ab->docked_rect.left,
526 ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
527 }
528 gtk_appbar_setpos(ab, msg->hwnd);
529 break;
530 #if 0
531 default:
532 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: %d\n", msg->wParam);
533 #endif
534 }
535 return GDK_FILTER_CONTINUE;
536 }
537
538 static GdkFilterReturn gtk_appbar_event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) {
539 MSG *msg = (MSG*)xevent;
540
541 /*printf("MSG: %s\n", message_to_string (msg->message));*/
542 switch(msg->message) {
543 case WM_EXITSIZEMOVE:
544 return wnd_exitsizemove(data, xevent);
545 case WM_WINDOWPOSCHANGING:
546 return wnd_poschanging(data, xevent);
547 case WM_WINDOWPOSCHANGED:
548 return wnd_poschanged(data, xevent);
549 case WM_ACTIVATE:
550 return wnd_activate(data, xevent);
551 case WM_SIZING:
552 return wnd_sizing(data, xevent);
553 case WM_MOVING:
554 return wnd_moving(data, xevent);
555 case WM_SHOWWINDOW:
556 return wnd_showwindow(data, xevent);
557 case WM_NCHITTEST:
558 return wnd_nchittest(data, xevent);
559 #if 0
560 case WM_INITMENUPOPUP:
561 return wnd_initmenupopup(data, xevent);
562 #endif
563 case WM_SIZE:
564 return wnd_size(data, xevent);
565 case APPBAR_CALLBACK:
566 return gtk_appbar_callback(data, xevent);
567 #if 0
568 default:
569 purple_debug_info("gtkappbar", "gtk_appbar_event_filter %d\n", msg->message);
570 #endif
571 }
572 return GDK_FILTER_CONTINUE;
573 }
574
575 void gtk_appbar_dock(GtkAppBar *ab, UINT side) {
576 RECT orig, windowRect;
577
578 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_dock\n");
579
580 if(!ab || !IsWindow(GDK_WINDOW_HWND(ab->win->window)))
581 return;
582
583 ab->side = side;
584 get_window_normal_rc(GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect));
585 CopyRect(&orig, &(ab->docked_rect));
586 get_rect_of_window(GDK_WINDOW_HWND(ab->win->window), &windowRect);
587 gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window), windowRect);
588 if(EqualRect(&orig, &(ab->docked_rect)) == 0)
589 MoveWindow(GDK_WINDOW_HWND(ab->win->window),
590 ab->docked_rect.left,
591 ab->docked_rect.top,
592 ab->docked_rect.right - ab->docked_rect.left,
593 ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
594 gtk_appbar_setpos(ab, GDK_WINDOW_HWND(ab->win->window));
595 set_toolbar(GDK_WINDOW_HWND(ab->win->window), TRUE);
596 ab->docked = TRUE;
597 }
598
599 void gtk_appbar_add_dock_cb(GtkAppBar *ab, GtkAppBarDockCB dock_cb) {
600 if(!ab)
601 return;
602 ab->dock_cbs = g_list_append(ab->dock_cbs, dock_cb);
603 }
604
605 GtkAppBar *gtk_appbar_add(GtkWidget *win) {
606 GtkAppBar *ab;
607
608 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_add\n");
609
610 if(!win)
611 return NULL;
612 ab = g_new0(GtkAppBar, 1);
613 ab->win = win;
614
615 /* init docking coords */
616 get_window_normal_rc(GDK_WINDOW_HWND(win->window), &(ab->docked_rect));
617
618 /* Add main window filter */
619 gdk_window_add_filter(win->window,
620 gtk_appbar_event_filter,
621 ab);
622 return ab;
623 }
624
625 void gtk_appbar_remove(GtkAppBar *ab) {
626 purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_remove\n");
627
628 if(!ab)
629 return;
630 gdk_window_remove_filter(ab->win->window,
631 gtk_appbar_event_filter,
632 ab);
633 if(ab->docked) {
634 gtk_window_resize(GTK_WINDOW(ab->win),
635 ab->docked_rect.right - ab->docked_rect.left,
636 ab->undocked_height);
637 set_toolbar(GDK_WINDOW_HWND(ab->win->window), FALSE);
638 }
639 gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
640
641 g_free(ab);
642 }

mercurial