Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern/wm_window.c')
-rw-r--r--source/blender/windowmanager/intern/wm_window.c582
1 files changed, 582 insertions, 0 deletions
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
new file mode 100644
index 00000000000..644f1a95c8e
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -0,0 +1,582 @@
+/**
+ * $Id: wm_window.c
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation but based
+ * on ghostwinlay.c (C) 2001-2002 by NaN Holding BV
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2008
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "DNA_listBase.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "GHOST_C-api.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_blender.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm.h"
+#include "wm_window.h"
+#include "wm_subwindow.h"
+#include "wm_event_system.h"
+
+#include "ED_screen.h"
+
+/* the global to talk to ghost */
+GHOST_SystemHandle g_system= NULL;
+
+/* set by commandline */
+static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0;
+
+
+/* ******** win open & close ************ */
+
+
+static void wm_get_screensize(int *width_r, int *height_r)
+{
+ unsigned int uiwidth;
+ unsigned int uiheight;
+
+ GHOST_GetMainDisplayDimensions(g_system, &uiwidth, &uiheight);
+ *width_r= uiwidth;
+ *height_r= uiheight;
+}
+
+static void wm_ghostwindow_destroy(wmWindow *win)
+{
+ if(win->ghostwin) {
+ GHOST_DisposeWindow(g_system, win->ghostwin);
+ win->ghostwin= NULL;
+ }
+}
+
+/* including window itself, C can be NULL.
+ ED_screen_exit should have been called */
+void wm_window_free(bContext *C, wmWindow *win)
+{
+ /* update context */
+ if(C) {
+ if(C->wm->windrawable==win)
+ C->wm->windrawable= NULL;
+ if(C->wm->winactive==win)
+ C->wm->winactive= NULL;
+ if(C->window==win)
+ C->window= NULL;
+ if(C->screen==win->screen)
+ C->screen= NULL;
+ }
+
+ if(win->eventstate) MEM_freeN(win->eventstate);
+
+ wm_event_free_all(win);
+ wm_subwindows_free(win);
+
+ wm_ghostwindow_destroy(win);
+
+ MEM_freeN(win);
+}
+
+static int find_free_winid(wmWindowManager *wm)
+{
+ wmWindow *win;
+ int id= 0;
+
+ for(win= wm->windows.first; win; win= win->next)
+ if(id <= win->winid)
+ id= win->winid+1;
+
+ return id;
+}
+
+/* dont change context itself */
+wmWindow *wm_window_new(bContext *C)
+{
+ wmWindow *win= MEM_callocN(sizeof(wmWindow), "window");
+
+ BLI_addtail(&C->wm->windows, win);
+ win->winid= find_free_winid(C->wm);
+
+ return win;
+}
+
+
+/* part of wm_window.c api */
+wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
+{
+ wmWindow *win= wm_window_new(C);
+
+ win->posx= winorig->posx+10;
+ win->posy= winorig->posy;
+ win->sizex= winorig->sizex;
+ win->sizey= winorig->sizey;
+
+ win->screen= ED_screen_duplicate(win, winorig->screen);
+ win->screen->do_refresh= 1;
+ win->screen->do_draw= 1;
+
+ return win;
+}
+
+/* this is event from ghost */
+static void wm_window_close(bContext *C, wmWindow *win)
+{
+ BLI_remlink(&C->wm->windows, win);
+
+ ED_screen_exit(C, win, win->screen);
+ wm_window_free(C, win);
+
+ if(C->wm->windows.first==NULL)
+ WM_exit(C);
+}
+
+/* belongs to below */
+static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow *win)
+{
+ GHOST_WindowHandle ghostwin;
+ GHOST_TWindowState inital_state;
+ int scr_w, scr_h, posy;
+
+ wm_get_screensize(&scr_w, &scr_h);
+ posy= (scr_h - win->posy - win->sizey);
+
+ // inital_state = GHOST_kWindowStateFullScreen;
+ // inital_state = GHOST_kWindowStateMaximized;
+ inital_state = GHOST_kWindowStateNormal;
+
+#ifdef __APPLE__
+ {
+ extern int macPrefState; /* creator.c */
+ inital_state += macPrefState;
+ }
+#endif
+
+ ghostwin= GHOST_CreateWindow(g_system, title,
+ win->posx, posy, win->sizex, win->sizey,
+ inital_state,
+ GHOST_kDrawingContextTypeOpenGL,
+ 0 /* no stereo */);
+
+ if (ghostwin) {
+ ListBase *keymap;
+
+ win->ghostwin= ghostwin;
+ GHOST_SetWindowUserData(ghostwin, win); /* pointer back */
+
+ if(win->eventstate==NULL)
+ win->eventstate= MEM_callocN(sizeof(wmEvent), "window event state");
+
+ /* add keymap handlers (1 handler for all keys in map!) */
+ keymap= WM_keymap_listbase(wm, "Window", 0, 0);
+ WM_event_add_keymap_handler(&win->handlers, keymap);
+
+ keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
+ WM_event_add_keymap_handler(&win->handlers, keymap);
+
+ /* until screens get drawn, make it nice grey */
+ glClearColor(.55, .55, .55, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ wm_window_swap_buffers(win);
+
+ /* standard state vars for window */
+ glEnable(GL_SCISSOR_TEST);
+ }
+}
+
+/* for wmWindows without ghostwin, open these and clear */
+/* window size is read from window, if 0 it uses prefsize */
+void wm_window_add_ghostwindows(wmWindowManager *wm)
+{
+ wmWindow *win;
+
+ /* no commandline prefsize? then we set this */
+ if (!prefsizx) {
+ wm_get_screensize(&prefsizx, &prefsizy);
+
+#ifdef __APPLE__
+ {
+ extern void wm_set_apple_prefsize(int, int); /* wm_apple.c */
+
+ wm_set_apple_prefsize(prefsizx, prefsizy);
+ }
+#else
+ prefstax= 0;
+ prefstay= 0;
+
+#endif
+ }
+
+ for(win= wm->windows.first; win; win= win->next) {
+ if(win->ghostwin==NULL) {
+ if(win->sizex==0) {
+ win->posx= prefstax;
+ win->posy= prefstay;
+ win->sizex= prefsizx;
+ win->sizey= prefsizy;
+ win->windowstate= 0;
+ }
+ wm_window_add_ghostwindow(wm, "Blender", win);
+ }
+ }
+}
+
+/* new window, no screen yet, but we open ghostwindow for it */
+/* also gets the window level handlers */
+/* area-rip calls this */
+wmWindow *WM_window_open(bContext *C, rcti *rect)
+{
+ wmWindow *win= wm_window_new(C);
+
+ win->posx= rect->xmin;
+ win->posy= rect->ymin;
+ win->sizex= rect->xmax - rect->xmin;
+ win->sizey= rect->ymax - rect->ymin;
+
+ wm_window_add_ghostwindow(C->wm, "Blender", win);
+
+ return win;
+}
+
+
+/* ****************** Operators ****************** */
+
+/* operator callback */
+int wm_window_duplicate_op(bContext *C, wmOperator *op)
+{
+ wm_window_copy(C, C->window);
+ wm_check(C);
+
+ return OPERATOR_FINISHED;
+}
+
+
+/* fullscreen operator callback */
+int wm_window_fullscreen_toggle_op(bContext *C, wmOperator *op)
+{
+ GHOST_TWindowState state = GHOST_GetWindowState(C->window->ghostwin);
+ if(state!=GHOST_kWindowStateFullScreen)
+ GHOST_SetWindowState(C->window->ghostwin, GHOST_kWindowStateFullScreen);
+ else
+ GHOST_SetWindowState(C->window->ghostwin, GHOST_kWindowStateNormal);
+
+ return OPERATOR_FINISHED;
+
+}
+
+
+/* exit blender */
+int wm_exit_blender_op(bContext *C, wmOperator *op)
+{
+ wmWindow *win= C->wm->windows.first;
+ while(win) {
+ wm_window_close(C, win);
+ win= win->next;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+
+/* ************ events *************** */
+
+static int query_qual(char qual)
+{
+ GHOST_TModifierKeyMask left, right;
+ int val= 0;
+
+ if (qual=='s') {
+ left= GHOST_kModifierKeyLeftShift;
+ right= GHOST_kModifierKeyRightShift;
+ } else if (qual=='c') {
+ left= GHOST_kModifierKeyLeftControl;
+ right= GHOST_kModifierKeyRightControl;
+ } else if (qual=='C') {
+ left= right= GHOST_kModifierKeyCommand;
+ } else {
+ left= GHOST_kModifierKeyLeftAlt;
+ right= GHOST_kModifierKeyRightAlt;
+ }
+
+ GHOST_GetModifierKeyState(g_system, left, &val);
+ if (!val)
+ GHOST_GetModifierKeyState(g_system, right, &val);
+
+ return val;
+}
+
+void wm_window_make_drawable(bContext *C, wmWindow *win)
+{
+ if (win != C->wm->windrawable && win->ghostwin) {
+// win->lmbut= 0; /* keeps hanging when mousepressed while other window opened */
+
+ C->wm->windrawable= win;
+ if(G.f & G_DEBUG) printf("set drawable %d\n", win->winid);
+ GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ }
+}
+
+/* called by ghost, here we handle events for windows themselves or send to event system */
+static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
+{
+ bContext *C= private;
+ GHOST_TEventType type= GHOST_GetEventType(evt);
+
+ if (type == GHOST_kEventQuit) {
+ WM_exit(C);
+ } else {
+ GHOST_WindowHandle ghostwin= GHOST_GetEventWindow(evt);
+ GHOST_TEventDataPtr data= GHOST_GetEventData(evt);
+ wmWindow *win;
+
+ if (!ghostwin) {
+ // XXX - should be checked, why are we getting an event here, and
+ // what is it?
+
+ return 1;
+ } else if (!GHOST_ValidWindow(g_system, ghostwin)) {
+ // XXX - should be checked, why are we getting an event here, and
+ // what is it?
+
+ return 1;
+ } else {
+ win= GHOST_GetWindowUserData(ghostwin);
+ }
+
+ switch(type) {
+ case GHOST_kEventWindowDeactivate:
+ win->active= 0; /* XXX */
+ break;
+ case GHOST_kEventWindowActivate:
+ {
+ GHOST_TEventKeyData kdata;
+ int cx, cy, wx, wy;
+
+ C->wm->winactive= win; /* no context change! c->wm->windrawable is drawable, or for area queues */
+
+ win->active= 1;
+// window_handle(win, INPUTCHANGE, win->active);
+
+ /* bad ghost support for modifier keys... so on activate we set the modifiers again */
+ kdata.ascii= 0;
+ if (win->eventstate->shift && !query_qual('s')) {
+ kdata.key= GHOST_kKeyLeftShift;
+ wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
+ }
+ if (win->eventstate->ctrl && !query_qual('c')) {
+ kdata.key= GHOST_kKeyLeftControl;
+ wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
+ }
+ if (win->eventstate->alt && !query_qual('a')) {
+ kdata.key= GHOST_kKeyLeftAlt;
+ wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
+ }
+ if (win->eventstate->oskey && !query_qual('C')) {
+ kdata.key= GHOST_kKeyCommand;
+ wm_event_add_ghostevent(win, GHOST_kEventKeyUp, &kdata);
+ }
+
+ /* entering window, update mouse pos. but no event */
+ GHOST_GetCursorPosition(g_system, &wx, &wy);
+
+ GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy);
+ win->eventstate->x= cx;
+ win->eventstate->y= (win->sizey-1) - cy;
+
+ ED_screen_set_subwinactive(win); /* active subwindow in screen */
+
+ wm_window_make_drawable(C, win);
+ break;
+ }
+ case GHOST_kEventWindowClose: {
+ wm_window_close(C, win);
+ break;
+ }
+ case GHOST_kEventWindowUpdate: {
+ if(G.f & G_DEBUG) printf("ghost redraw\n");
+
+ wm_window_make_drawable(C, win);
+ WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
+
+ break;
+ }
+ case GHOST_kEventWindowSize:
+ case GHOST_kEventWindowMove: {
+ GHOST_RectangleHandle client_rect;
+ int l, t, r, b, scr_w, scr_h;
+
+ client_rect= GHOST_GetClientBounds(win->ghostwin);
+ GHOST_GetRectangle(client_rect, &l, &t, &r, &b);
+
+ GHOST_DisposeRectangle(client_rect);
+
+ wm_get_screensize(&scr_w, &scr_h);
+ win->sizex= r-l;
+ win->sizey= b-t;
+ win->posx= l;
+ win->posy= scr_h - t - win->sizey;
+
+ /* debug prints */
+ if(0) {
+ GHOST_TWindowState state;
+ state = GHOST_GetWindowState(win->ghostwin);
+
+ if(state==GHOST_kWindowStateNormal) {
+ if(G.f & G_DEBUG) printf("window state: normal\n");
+ }
+ else if(state==GHOST_kWindowStateMinimized) {
+ if(G.f & G_DEBUG) printf("window state: minimized\n");
+ }
+ else if(state==GHOST_kWindowStateMaximized) {
+ if(G.f & G_DEBUG) printf("window state: maximized\n");
+ }
+ else if(state==GHOST_kWindowStateFullScreen) {
+ if(G.f & G_DEBUG) printf("window state: fullscreen\n");
+ }
+
+ if(type!=GHOST_kEventWindowSize) {
+ if(G.f & G_DEBUG) printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey);
+ }
+
+ }
+
+ wm_window_make_drawable(C, win);
+ WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
+
+ break;
+ }
+ default:
+ if(type==GHOST_kEventKeyDown) // XXX debug
+ WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
+ wm_event_add_ghostevent(win, type, data);
+ break;
+ }
+
+ }
+ return 1;
+}
+
+void wm_window_process_events(int wait_for_event)
+{
+ GHOST_ProcessEvents(g_system, wait_for_event);
+ GHOST_DispatchEvents(g_system);
+}
+
+/* **************** init ********************** */
+
+void wm_ghost_init(bContext *C)
+{
+ if (!g_system) {
+ GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(ghost_event_proc, C);
+
+ g_system= GHOST_CreateSystem();
+ GHOST_AddEventConsumer(g_system, consumer);
+ }
+}
+
+/* **************** timer ********************** */
+
+static void window_event_timer_proc(GHOST_TimerTaskHandle timer, GHOST_TUns64 time)
+{
+ wmWindow *window;
+
+ window= GHOST_GetTimerTaskUserData(timer);
+
+ wm_event_add_ghostevent(window, GHOST_kEventTimer, (wmTimerHandle*)timer);
+}
+
+wmTimerHandle *WM_event_add_window_timer(wmWindow *win, int delay_ms, int interval_ms)
+{
+ return (wmTimerHandle*)GHOST_InstallTimer(g_system, delay_ms, interval_ms,
+ window_event_timer_proc, win);
+}
+
+void WM_event_remove_window_timer(wmWindow *wm, wmTimerHandle *handle)
+{
+ GHOST_RemoveTimer(g_system, (GHOST_TimerTaskHandle)handle);
+}
+
+/* ************************************ */
+
+void wm_window_set_title(wmWindow *win, char *title)
+{
+ GHOST_SetTitle(win->ghostwin, title);
+}
+
+void wm_window_get_position(wmWindow *win, int *posx_r, int *posy_r)
+{
+ *posx_r= win->posx;
+ *posy_r= win->posy;
+}
+
+void wm_window_get_size(wmWindow *win, int *width_r, int *height_r)
+{
+ *width_r= win->sizex;
+ *height_r= win->sizey;
+}
+
+void wm_window_set_size(wmWindow *win, int width, int height)
+{
+ GHOST_SetClientSize(win->ghostwin, width, height);
+}
+
+void wm_window_lower(wmWindow *win)
+{
+ GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderBottom);
+}
+
+void wm_window_raise(wmWindow *win)
+{
+ GHOST_SetWindowOrder(win->ghostwin, GHOST_kWindowOrderTop);
+#ifdef _WIN32
+// markdirty_all(); /* to avoid redraw errors in fullscreen mode (aphex) */
+#endif
+}
+
+void wm_window_swap_buffers(wmWindow *win)
+{
+ GHOST_SwapWindowBuffers(win->ghostwin);
+}
+
+/* ******************* exported api ***************** */
+
+
+/* called whem no ghost system was initialized */
+void WM_setprefsize(int stax, int stay, int sizx, int sizy)
+{
+ prefstax= stax;
+ prefstay= stay;
+ prefsizx= sizx;
+ prefsizy= sizy;
+}
+