4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2007 Blender Foundation but based
21 * on ghostwinlay.c (C) 2001-2002 by NaN Holding BV
22 * All rights reserved.
24 * Contributor(s): Blender Foundation, 2008
26 * ***** END GPL LICENSE BLOCK *****
32 #include "DNA_listBase.h"
33 #include "DNA_screen_types.h"
34 #include "DNA_windowmanager_types.h"
36 #include "MEM_guardedalloc.h"
38 #include "GHOST_C-api.h"
40 #include "BLI_blenlib.h"
42 #include "BKE_blender.h"
43 #include "BKE_global.h"
44 #include "BKE_utildefines.h"
51 #include "wm_window.h"
52 #include "wm_subwindow.h"
53 #include "wm_event_system.h"
55 #include "ED_screen.h"
57 /* the global to talk to ghost */
58 GHOST_SystemHandle g_system= NULL;
60 /* set by commandline */
61 static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0;
64 /* ******** win open & close ************ */
67 static void wm_get_screensize(int *width_r, int *height_r)
70 unsigned int uiheight;
72 GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight);
77 static void wm_ghostwindow_destroy(wmWindow *win)
80 GHOST_DisposeWindow(g_system, win->ghostwin);
85 /* including window itself, C can be NULL.
86 ED_screen_exit should have been called */
87 void wm_window_free(bContext *C, wmWindow *win)
91 if(C->wm->windrawable==win)
92 C->wm->windrawable= NULL;
93 if(C->wm->winactive==win)
94 C->wm->winactive= NULL;
97 if(C->screen==win->screen)
101 if(win->eventstate) MEM_freeN(win->eventstate);
103 wm_event_free_all(win);
104 wm_subwindows_free(win);
106 wm_ghostwindow_destroy(win);
111 static int find_free_winid(wmWindowManager *wm)
116 for(win= wm->windows.first; win; win= win->next)
123 /* dont change context itself */
124 wmWindow *wm_window_new(bContext *C)
126 wmWindow *win= MEM_callocN(sizeof(wmWindow), "window");
128 BLI_addtail(&C->wm->windows, win);
129 win->winid= find_free_winid(C->wm);
135 /* part of wm_window.c api */
136 wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
138 wmWindow *win= wm_window_new(C);
140 win->posx= winorig->posx+10;
141 win->posy= winorig->posy;
142 win->sizex= winorig->sizex;
143 win->sizey= winorig->sizey;
145 win->screen= ED_screen_duplicate(win, winorig->screen);
146 win->screen->do_refresh= 1;
147 win->screen->do_draw= 1;
152 /* this is event from ghost */
153 static void wm_window_close(bContext *C, wmWindow *win)
155 BLI_remlink(&C->wm->windows, win);
157 ED_screen_exit(C, win, win->screen);
158 wm_window_free(C, win);
160 if(C->wm->windows.first==NULL)
164 /* belongs to below */
165 static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow *win)
167 GHOST_WindowHandle ghostwin;
168 GHOST_TWindowState inital_state;
169 int scr_w, scr_h, posy;
171 wm_get_screensize(&scr_w, &scr_h);
172 posy= (scr_h - win->posy - win->sizey);
174 // inital_state = GHOST_kWindowStateFullScreen;
175 // inital_state = GHOST_kWindowStateMaximized;
176 inital_state = GHOST_kWindowStateNormal;
180 extern int macPrefState; /* creator.c */
181 inital_state += macPrefState;
185 ghostwin= GHOST_CreateWindow(g_system, title,
186 win->posx, posy, win->sizex, win->sizey,
188 GHOST_kDrawingContextTypeOpenGL,
194 win->ghostwin= ghostwin;
195 GHOST_SetWindowUserData(ghostwin, win); /* pointer back */
197 if(win->eventstate==NULL)
198 win->eventstate= MEM_callocN(sizeof(wmEvent), "window event state");
200 /* add keymap handlers (1 handler for all keys in map!) */
201 keymap= WM_keymap_listbase(wm, "Window", 0, 0);
202 WM_event_add_keymap_handler(&win->handlers, keymap);
204 keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
205 WM_event_add_keymap_handler(&win->handlers, keymap);
207 /* until screens get drawn, make it nice grey */
208 glClearColor(.55, .55, .55, 0.0);
209 glClear(GL_COLOR_BUFFER_BIT);
210 wm_window_swap_buffers(win);
212 /* standard state vars for window */
213 glEnable(GL_SCISSOR_TEST);
217 /* for wmWindows without ghostwin, open these and clear */
218 /* window size is read from window, if 0 it uses prefsize */
219 void wm_window_add_ghostwindows(wmWindowManager *wm)
223 /* no commandline prefsize? then we set this */
225 wm_get_screensize(&prefsizx, &prefsizy);
229 extern void wm_set_apple_prefsize(int, int); /* wm_apple.c */
231 wm_set_apple_prefsize(prefsizx, prefsizy);
240 for(win= wm->windows.first; win; win= win->next) {
241 if(win->ghostwin==NULL) {
245 win->sizex= prefsizx;
246 win->sizey= prefsizy;
249 wm_window_add_ghostwindow(wm, "Blender", win);
254 /* new window, no screen yet, but we open ghostwindow for it */
255 /* also gets the window level handlers */
256 /* area-rip calls this */
257 wmWindow *WM_window_open(bContext *C, rcti *rect)
259 wmWindow *win= wm_window_new(C);
261 win->posx= rect->xmin;
262 win->posy= rect->ymin;
263 win->sizex= rect->xmax - rect->xmin;
264 win->sizey= rect->ymax - rect->ymin;
266 wm_window_add_ghostwindow(C->wm, "Blender", win);
272 /* ****************** Operators ****************** */
274 /* operator callback */
275 int wm_window_duplicate_op(bContext *C, wmOperator *op)
277 wm_window_copy(C, C->window);
280 return OPERATOR_FINISHED;
284 /* fullscreen operator callback */
285 int wm_window_fullscreen_toggle_op(bContext *C, wmOperator *op)
287 GHOST_TWindowState state = GHOST_GetWindowState(C->window->ghostwin);
288 if(state!=GHOST_kWindowStateFullScreen)
289 GHOST_SetWindowState(C->window->ghostwin, GHOST_kWindowStateFullScreen);
291 GHOST_SetWindowState(C->window->ghostwin, GHOST_kWindowStateNormal);
293 return OPERATOR_FINISHED;
299 int wm_exit_blender_op(bContext *C, wmOperator *op)
301 wmWindow *win= C->wm->windows.first;
303 wm_window_close(C, win);
307 return OPERATOR_FINISHED;
311 /* ************ events *************** */
313 static int query_qual(char qual)
315 GHOST_TModifierKeyMask left, right;
319 left= GHOST_kModifierKeyLeftShift;
320 right= GHOST_kModifierKeyRightShift;
321 } else if (qual=='c') {
322 left= GHOST_kModifierKeyLeftControl;
323 right= GHOST_kModifierKeyRightControl;
324 } else if (qual=='C') {
325 left= right= GHOST_kModifierKeyCommand;
327 left= GHOST_kModifierKeyLeftAlt;
328 right= GHOST_kModifierKeyRightAlt;
331 GHOST_GetModifierKeyState(g_system, left, &val);
333 GHOST_GetModifierKeyState(g_system, right, &val);
338 void wm_window_make_drawable(bContext *C, wmWindow *win)
340 if (win != C->wm->windrawable && win->ghostwin) {
341 // win->lmbut= 0; /* keeps hanging when mousepressed while other window opened */
343 C->wm->windrawable= win;
344 if(G.f & G_DEBUG) printf("set drawable %d\n", win->winid);
345 GHOST_ActivateWindowDrawingContext(win->ghostwin);
349 /* called by ghost, here we handle events for windows themselves or send to event system */
350 static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
352 bContext *C= private;
353 GHOST_TEventType type= GHOST_GetEventType(evt);
355 if (type == GHOST_kEventQuit) {
358 GHOST_WindowHandle ghostwin= GHOST_GetEventWindow(evt);
359 GHOST_TEventDataPtr data= GHOST_GetEventData(evt);
363 // XXX - should be checked, why are we getting an event here, and
367 } else if (!GHOST_ValidWindow(g_system, ghostwin)) {
368 // XXX - should be checked, why are we getting an event here, and
373 win= GHOST_GetWindowUserData(ghostwin);
377 case GHOST_kEventWindowDeactivate:
378 win->active= 0; /* XXX */
380 case GHOST_kEventWindowActivate:
382 GHOST_TEventKeyData kdata;
385 C->wm->winactive= win; /* no context change! c->wm->windrawable is drawable, or for area queues */
388 // window_handle(win, INPUTCHANGE, win->active);
390 /* bad ghost support for modifier keys... so on activate we set the modifiers again */
392 if (win->eventstate->shift && !query_qual('s')) {
393 kdata.key= GHOST_kKeyLeftShift;
394 wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
396 if (win->eventstate->ctrl && !query_qual('c')) {
397 kdata.key= GHOST_kKeyLeftControl;
398 wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
400 if (win->eventstate->alt && !query_qual('a')) {
401 kdata.key= GHOST_kKeyLeftAlt;
402 wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
404 if (win->eventstate->oskey && !query_qual('C')) {
405 kdata.key= GHOST_kKeyCommand;
406 wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
409 /* entering window, update mouse pos. but no event */
410 GHOST_GetCursorPosition(g_system, &wx, &wy);
412 GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy);
413 win->eventstate->x= cx;
414 win->eventstate->y= (win->sizey-1) - cy;
416 ED_screen_set_subwinactive(win); /* active subwindow in screen */
418 wm_window_make_drawable(C, win);
421 case GHOST_kEventWindowClose: {
422 wm_window_close(C, win);
425 case GHOST_kEventWindowUpdate: {
426 if(G.f & G_DEBUG) printf("ghost redraw\n");
428 wm_window_make_drawable(C, win);
429 WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
433 case GHOST_kEventWindowSize:
434 case GHOST_kEventWindowMove: {
435 GHOST_RectangleHandle client_rect;
436 int l, t, r, b, scr_w, scr_h;
438 client_rect= GHOST_GetClientBounds(win->ghostwin);
439 GHOST_GetRectangle(client_rect, &l, &t, &r, &b);
441 GHOST_DisposeRectangle(client_rect);
443 wm_get_screensize(&scr_w, &scr_h);
447 win->posy= scr_h - t - win->sizey;
451 GHOST_TWindowState state;
452 state = GHOST_GetWindowState(win->ghostwin);
454 if(state==GHOST_kWindowStateNormal) {
455 if(G.f & G_DEBUG) printf("window state: normal\n");
457 else if(state==GHOST_kWindowStateMinimized) {
458 if(G.f & G_DEBUG) printf("window state: minimized\n");
460 else if(state==GHOST_kWindowStateMaximized) {
461 if(G.f & G_DEBUG) printf("window state: maximized\n");
463 else if(state==GHOST_kWindowStateFullScreen) {
464 if(G.f & G_DEBUG) printf("window state: fullscreen\n");
467 if(type!=GHOST_kEventWindowSize) {
468 if(G.f & G_DEBUG) printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey);
473 wm_window_make_drawable(C, win);
474 WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
479 if(type==GHOST_kEventKeyDown) // XXX debug
480 WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
481 wm_event_add_ghostevent(win, type, data);
489 void wm_window_process_events(int wait_for_event)
491 GHOST_ProcessEvents(g_system, wait_for_event);
492 GHOST_DispatchEvents(g_system);
495 /* **************** init ********************** */
497 void wm_ghost_init(bContext *C)
500 GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(ghost_event_proc, C);
502 g_system= GHOST_CreateSystem();
503 GHOST_AddEventConsumer(g_system, consumer);
507 /* **************** timer ********************** */
509 static void window_event_timer_proc(GHOST_TimerTaskHandle timer, GHOST_TUns64 time)
513 window= GHOST_GetTimerTaskUserData(timer);
515 wm_event_add_ghostevent(window, GHOST_kEventTimer, (wmTimerHandle*)timer);
518 wmTimerHandle *WM_event_add_window_timer(wmWindow *win, int delay_ms, int interval_ms)
520 return (wmTimerHandle*)GHOST_InstallTimer(g_system, delay_ms, interval_ms,
521 window_event_timer_proc, win);
524 void WM_event_remove_window_timer(wmWindow *wm, wmTimerHandle *handle)
526 GHOST_RemoveTimer(g_system, (GHOST_TimerTaskHandle)handle);
529 /* ************************************ */
531 void wm_window_set_title(wmWindow *win, char *title)
533 GHOST_SetTitle(win->ghostwin, title);
536 void wm_window_get_position(wmWindow *win, int *posx_r, int *posy_r)
542 void wm_window_get_size(wmWindow *win, int *width_r, int *height_r)
544 *width_r= win->sizex;
545 *height_r= win->sizey;
548 void wm_window_set_size(wmWindow *win, int width, int height)
550 GHOST_SetClientSize(win->ghostwin, width, height);
553 void wm_window_lower(wmWindow *win)
555 GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderBottom);
558 void wm_window_raise(wmWindow *win)
560 GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderTop);
562 // markdirty_all(); /* to avoid redraw errors in fullscreen mode (aphex) */
566 void wm_window_swap_buffers(wmWindow *win)
568 GHOST_SwapWindowBuffers(win->ghostwin);
571 /* ******************* exported api ***************** */
574 /* called whem no ghost system was initialized */
575 void WM_setprefsize(int stax, int stay, int sizx, int sizy)